Skip to content

Commit

Permalink
feat: 1.2 (add support filters)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sepera-okeq committed Nov 3, 2024
1 parent 35a9dfd commit ec0a1a0
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 56 deletions.
31 changes: 16 additions & 15 deletions DDS_EVRIKA_PLUGIN/dds_evrika_plugin/Manual.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@

<body>
<header>
<h1>Krita DDS Evrika Plugin - User Manual (Updated 1.1)</h1>
<h1>Krita DDS Evrika Plugin - User Manual (Updated 1.2)</h1>
</header>

<main>
<section id="introduction">
<h2>Introduction</h2>
<p>The DDS Evrika Plugin is an extension for <strong>Krita</strong>, enabling users to import and export DDS
image files using ImageMagick. DDS (DirectDraw Surface) is a popular format for storing textures and
images optimized for real-time rendering, often used in video games and 3D applications.</p>
<p>This updated version introduces support for customizable import, export settings, mipmap levels, and
integration with Krita's scripting interface for a more flexible workflow.</p>
image files using ImageMagick. DDS (DirectDraw Surface) is a popular format for storing textures and
images optimized for real-time rendering, often used in video games and 3D applications.</p>
<p>This updated version introduces the ability to choose filters during export (Lanczos, Box, and more),
customizable import/export settings, mipmap levels, and integration with Krita's scripting interface
for a more flexible workflow.</p>
</section>

<section id="installation">
Expand All @@ -45,8 +46,7 @@ <h2>Installation</h2>
</ul>
<li>Ensure that ImageMagick is installed and available in the "resources" folder of the plugin.</li>
<li>Restart Krita after copying the plugin files.</li>
<li>Activate the plugin from the Krita interface via <em>"Tools > Scripts > Evrika DDS Plugin".</em>
</li>
<li>Activate the plugin from the Krita interface via <em>"Tools > Scripts > Evrika DDS Plugin".</em></li>
</ol>
</section>

Expand All @@ -58,7 +58,7 @@ <h3>Importing DDS Files</h3>
<ol>
<li>Navigate to <strong>Tools > Scripts > Import DDS</strong>.</li>
<li>Select the DDS file you want to open.</li>
<li>The file will be converted to a chosen format such as PNG or TGA (based on your settings).</li>
<li>The file will be converted to a chosen format such as PNG, TIFF, GIF, or TGA (based on your settings).</li>
<li>The image will open in Krita after conversion.</li>
</ol>

Expand All @@ -71,10 +71,11 @@ <h3>Importing DDS Files with Custom Format</h3>
</ol>

<h3>Exporting DDS Files</h3>
<p>Exporting is straightforward with options for selecting compression and mipmap levels:</p>
<p>Exporting is straightforward with options for selecting compression, mipmap levels, and filters:</p>
<ol>
<li>Navigate to <strong>Tools > Scripts > Export DDS</strong>.</li>
<li>Select the compression type (DXT1, DXT3, DXT5, BC7) and set the Mipmap Levels (Auto, 1-5).</li>
<li>Select the compression type (DXT1, DXT3, DXT5, BC7) and set the Mipmap levels (Auto, 1-5).</li>
<li>Select a filter option (Lanczos, Box, Triangle, Mitchell, or Catmull-Rom)</li>
<li>Export the file using the DDS format.</li>
</ol>

Expand All @@ -83,18 +84,19 @@ <h3>Exporting DDS Files with Custom Settings</h3>
<ol>
<li>Use <strong>Tools > Scripts > Export DDS as...</strong>.</li>
<li>Select custom compression settings (DXT1, DXT3, DXT5, BC7, or None).</li>
<li>Adjust Mipmap levels, and export the file with the desired DDS settings.</li>
<li>Adjust Mipmap levels and filter settings.</li>
<li>Export the file with the desired DDS settings.</li>
</ol>
</section>

<section id="settings">
<h2>Plugin Settings</h2>
<p>The DDS Evrika Plugin allows saving custom settings, simplifying the import/export process. Access the
settings dialog by navigating to:</p>
settings dialog by navigating to:</p>
<ol>
<li><strong>Tools > Scripts > Evrika Settings</strong></li>
<li>Adjust the plugin to use the original filenames during import/export.</li>
<li>Customize export file names and formats based on your preferences.</li>
<li>Customize export file names, filters, and formats based on your preferences.</li>
<li>Configure default import/export formats for quicker conversions.</li>
</ol>
</section>
Expand All @@ -107,8 +109,7 @@ <h2>Troubleshooting</h2>
works on your system.</li>
<li>Double-check if the plugin was copied into the correct directory.</li>
<li>If Krita crashes or hangs during conversion, verify the file size and available system memory.</li>
<li>If MipMap issues occur during export, try reducing the mipmap level setting to "Auto" for better
compatibility.</li>
<li>If MipMap or filter issues occur during export, try tweaking the mipmap level or filter setting for better compatibility.</li>
</ul>
</section>

Expand Down
91 changes: 64 additions & 27 deletions DDS_EVRIKA_PLUGIN/dds_evrika_plugin/dds_evrika_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,17 @@ def __init__(self, settings_manager):
else:
self.locale_en()

# Основной layout
layout = QVBoxLayout(self)

# Секция для временных имен файлов
self.temp_export_check = QCheckBox(self.translations["use_original_export_name"])
self.temp_import_check = QCheckBox(self.translations["use_original_import_name"])
self.export_name_input = QLineEdit()
self.export_name_input.setPlaceholderText(self.translations["export_custom_name"])

# Загрузка сохраненных настроек
self.temp_export_check.setChecked(self.settings.get("use_original_export_name", False))
self.temp_import_check.setChecked(self.settings.get("use_original_import_name", False))
self.export_name_input.setText(self.settings.get("export_custom_name", ""))

# Импорт и экспорт: выбор формата и компрессии
form_layout = QFormLayout()
self.import_format_combo = QComboBox()
self.import_format_combo.addItems(["png", "tiff", "bmp", "jpeg", "tga"])
Expand All @@ -98,16 +94,18 @@ def __init__(self, settings_manager):
self.export_mipmap_combo.addItems(["1", "2", "3", "4", "5", "Auto"])
self.export_mipmap_combo.setCurrentText(self.settings.get("export_mipmap", "Auto"))

# Добавляем поля в форму
self.export_filter_combo = QComboBox()
self.export_filter_combo.addItems(["Undefined", "Point", "Box", "Triangle", "Hermite", "Hanning", "Hamming", "Blackman", "Gaussian", "Quadratic", "Cubic", "Catrom", "Mitchell", "Jinc", "Sinc", "SincFast", "Kaiser", "Welch", "Parzen", "Bohman", "Bartlett", "Lagrange", "Lanczos", "LanczosSharp", "Lanczos2", "Lanczos2Sharp", "Robidoux", "RobidouxSharp", "Cosine", "Spline", "Sentinel"])
self.export_filter_combo.setCurrentText(self.settings.get("export_filter", "Lanczos"))

form_layout.addRow(self.translations["import_format"], self.import_format_combo)
form_layout.addRow(self.translations["export_compression"], self.export_compression_combo)
form_layout.addRow(self.translations["export_mipmap"], self.export_mipmap_combo)
form_layout.addRow(self.translations["export_filter"], self.export_filter_combo)

# Кнопка "Сохранить"
save_button = QPushButton(self.translations["save_settings"])
save_button.clicked.connect(self.save_settings)

# Добавляем элементы на Layout
layout.addWidget(QLabel("<b>{}</b>".format(self.translations["temporary_file_settings"])))
layout.addWidget(self.temp_export_check)
layout.addWidget(self.temp_import_check)
Expand All @@ -124,6 +122,7 @@ def locale_ru(self):
"import_format": "Формат (импорт)",
"export_compression": "Компрессия (экспорт)",
"export_mipmap": "Уровни Mipmap (экспорт)",
"export_filter": "Фильтр (экспорт)",
"save_settings": "Сохранить настройки",
"temporary_file_settings": "Настройки временных файлов",
"custom_export_name": "Кастомное имя файла для экспорта",
Expand All @@ -138,20 +137,22 @@ def locale_en(self):
"import_format": "Format (import)",
"export_compression": "Compression (export)",
"export_mipmap": "Mipmap Levels (export)",
"export_filter": "Filter (export)",
"save_settings": "Save settings",
"temporary_file_settings": "Temporary file settings",
"custom_export_name": "Custom export file name",
"saved_seccess_settings": "Settings saved successfully"
}

def save_settings(self):
"""Сохраняем текущие настройки через объект SettingsManager."""
"""Save current settings through the SettingsManager."""
self.settings.set("use_original_export_name", self.temp_export_check.isChecked())
self.settings.set("use_original_import_name", self.temp_import_check.isChecked())
self.settings.set("export_custom_name", self.export_name_input.text())
self.settings.set("import_format", self.import_format_combo.currentText())
self.settings.set("export_compression", self.export_compression_combo.currentText())
self.settings.set("export_mipmap", self.export_mipmap_combo.currentText())
self.settings.set("export_filter", self.export_filter_combo.currentText())
QMessageBox.information(self, "Evrika Settings", self.translations["saved_seccess_settings"])


Expand Down Expand Up @@ -179,6 +180,7 @@ def init_translations(self):
"use_saved_settings": "Использовать мои настройки",
"overwrite_settings": "Перезаписать текущие настройки",
"mipmap_levels": "Уровни Mipmap",
"export_filter": "Фильтр (экспорт)",
"ok": "ОК",
"cancel": "Отмена",
"error": "Ошибка",
Expand All @@ -198,6 +200,7 @@ def init_translations(self):
"use_saved_settings": "Use my settings",
"overwrite_settings": "Overwrite current settings",
"mipmap_levels": "Mipmap levels",
"export_filter": "Filter (export)",
"ok": "OK",
"cancel": "Cancel",
"error": "Error",
Expand Down Expand Up @@ -349,11 +352,15 @@ def process_export(self, is_export_as):

compression_format = self.settings.get("export_compression", "dxt1")
mipmap_levels = self.settings.get("export_mipmap", "Auto")
export_filter = self.settings.get("export_filter", "Lanczos") # Get the export filter setting

args.extend(["-define", f"dds:compression={compression_format.lower()}"])

if compression_format != "none":
args.extend(["-define", f"dds:compression={compression_format.lower()}"])
if mipmap_levels != "Auto":
args.extend(["-define", f"dds:mipmaps={mipmap_levels}"])

# Add the filter option to the ImageMagick command
args.extend(["-filter", export_filter.lower()])

args.append(save_file)

Expand All @@ -377,11 +384,20 @@ def showImportExportDialog(self, is_import=True):
layout.addWidget(compression_format)

mipmaps_label = QLabel(self.translations["mipmap_levels"])
layout.addWidget(mipmaps_label)
mipmaps_combo = QComboBox()
mipmaps_combo.addItems(["Auto", "1", "2", "3", "4", "5"])
layout.addWidget(mipmaps_combo)

overwrite_checkbox = QCheckBox(self.translations["overwrite_settings"])
# Добавляем Label и ComboBox для выбора фильтра
filter_label = QLabel(self.translations["export_filter"])
layout.addWidget(filter_label)

filter_combo = QComboBox()
filter_combo.addItems(["Lanczos", "Undefined", "Point", "Box", "Triangle", "Hermite", "Hanning", "Hamming", "Blackman", "Gaussian", "Quadratic", "Cubic", "Catrom", "Mitchell", "Jinc", "Sinc", "SincFast", "Kaiser", "Welch", "Parzen", "Bohman", "Bartlett", "Lagrange", "LanczosSharp", "Lanczos2", "Lanczos2Sharp", "Robidoux", "RobidouxSharp", "Cosine", "Spline", "Sentinel"])
layout.addWidget(filter_combo)

overwrite_checkbox = QCheckBox(self.translations.get("overwrite_settings", "Overwrite current settings"))
layout.addWidget(overwrite_checkbox)

buttons_layout = QHBoxLayout()
Expand All @@ -394,18 +410,19 @@ def showImportExportDialog(self, is_import=True):
def save_temporary_settings():
compression = compression_format.currentText()
mipmaps = mipmaps_combo.currentText()
filter_option = filter_combo.currentText() # Получаем значение фильтра
overwrite = overwrite_checkbox.isChecked()

if overwrite:
self.save_user_preferences(compression, mipmaps)
self.save_user_preferences(compression, mipmaps, filter_option)

if is_import:
if is_import: # Для импорта
self.process_import_dialog(compression, mipmaps)
else:
self.process_export_dialog(compression, mipmaps)

else: # Для экспорта
self.process_export_dialog(compression, mipmaps, filter_option)
dialog.accept()

confirm_button.clicked.connect(save_temporary_settings)
cancel_button.clicked.connect(dialog.reject)
dialog.exec_()
Expand All @@ -424,10 +441,10 @@ def process_import_dialog(self, compression_format, mipmap_levels):
imagick_path = os.path.join(os.path.dirname(__file__), 'resources', 'magick.exe') if platform == "win32" else 'magick'
args = [imagick_path, input_file, output_file]

if compression_format != "none":
args.extend(['-define', f'dds:compression={compression_format.lower()}'])
if mipmap_levels != "Auto":
args.extend(['-define', f'dds:mipmaps={mipmap_levels}'])
#if compression_format != "none":
# args.extend(['-define', f'dds:compression={compression_format.lower()}'])
#if mipmap_levels != "Auto":
# args.extend(['-define', f'dds:mipmaps={mipmap_levels}'])

try:
subprocess.run(args, check=True)
Expand All @@ -438,18 +455,22 @@ def process_import_dialog(self, compression_format, mipmap_levels):
finally:
shutil.rmtree(temp_directory_location)

def process_export_dialog(self, compression_format, mipmap_levels):
def process_export_dialog(self, compression_format, mipmap_levels, filter_option):
"""Процесс экспорта с исправлением для обработки компрессии 'none'"""
doc = Krita.instance().activeDocument()

if not doc:
self.showError(self.translations["no_document"])
return

# Сохранение файла DDS
save_file, _ = QFileDialog.getSaveFileName(caption=self.translations["export_dds"], filter="DDS files (*.dds)")
if not save_file:
return
if not save_file.lower().endswith(".dds"):
save_file += ".dds"

# Генерация временного файла PNG
temp_filename = self.generate_temp_filename(doc.fileName(), ".png", for_export=True)
temp_directory_location = os.path.join(os.path.dirname(__file__), "temp_dds_export")
if not os.path.isdir(temp_directory_location):
Expand All @@ -458,27 +479,43 @@ def process_export_dialog(self, compression_format, mipmap_levels):
temp_png_file = os.path.join(temp_directory_location, temp_filename)
doc.saveAs(temp_png_file)

# Путь для работы с ImageMagick
imagick_path = os.path.join(os.path.dirname(__file__), "resources", "magick.exe") if platform == "win32" else "magick"

# Создаем список аргументов для команды
args = [imagick_path, temp_png_file]

if compression_format != "none":
args.extend(["-define", f"dds:compression={compression_format.lower()}"])
# Добавляем фильтр
if filter_option:
args.extend(["-filter", filter_option])

# Указываем формат компрессии, включая "none"
args.extend(["-define", f"dds:compression={compression_format.lower()}"])

# Добавляем количество уровней Mipmap, если оно не "Auto"
if mipmap_levels != "Auto":
args.extend(["-define", f"dds:mipmaps={mipmap_levels}"])

# Даем команду сохранить файл в формате DDS
args.append(save_file)

# Показываем финальную версию аргументов команды для ImageMagick
#QMessageBox.information(None, "Отладка", f"Сформированная команда для ImageMagick:\n{' '.join(args)}")

try:
# Запускаем команду через subprocess
subprocess.run(args, check=True)
self.showMessage(self.translations["file_saved"] + save_file)
self.showMessage(self.translations["file_saved"] + save_file) # Сообщаем об успешном сохранении
except subprocess.CalledProcessError as e:
self.showError(self.translations["error_processing"] + str(e))
finally:
shutil.rmtree(temp_directory_location)
shutil.rmtree(temp_directory_location) # Удаляем временные файлы

def save_user_preferences(self, compression, mipmaps):
def save_user_preferences(self, compression, mipmaps, filter_option):
"""Сохраняем пользовательские параметры экспорта, включая фильтр"""
self.settings.set("saved_compression", compression)
self.settings.set("saved_mipmap", mipmaps)
self.settings.set("saved_filter", filter_option)

def showError(self, message):
messageBox = QMessageBox()
Expand Down
Loading

0 comments on commit ec0a1a0

Please sign in to comment.