From 59e4aeff3f4f9a22bb531a76f2ee332a290420e3 Mon Sep 17 00:00:00 2001 From: Alx Sa Date: Mon, 16 Feb 2026 14:26:27 +0000 Subject: [PATCH] plug-ins: Use original DDS format on export This patch adds a parasite on load that retains the original import settings of a DDS texture (such as compression, number of mipmaps, and flags). This parasite is then checked on export, and if it exists, we default the compression format to the original to reduce the chance the user will choose the wrong format for the game they're creating the texture for. The other data stored is not currently used, but can be implemented in future commits. --- plug-ins/file-dds/dds.h | 1 + plug-ins/file-dds/ddsread.c | 28 ++++++++++ plug-ins/file-dds/ddswrite.c | 101 +++++++++++++++++++++++++++++------ 3 files changed, 114 insertions(+), 16 deletions(-) diff --git a/plug-ins/file-dds/dds.h b/plug-ins/file-dds/dds.h index 6caa278590..2397503fa0 100644 --- a/plug-ins/file-dds/dds.h +++ b/plug-ins/file-dds/dds.h @@ -48,6 +48,7 @@ typedef enum DDS_COMPRESS_BC3N, /* DXT5n */ DDS_COMPRESS_BC4, /* ATI1 */ DDS_COMPRESS_BC5, /* ATI2 */ + DDS_COMPRESS_BC6H, DDS_COMPRESS_BC7, DDS_COMPRESS_RXGB, /* DXT5 */ DDS_COMPRESS_AEXP, /* DXT5 */ diff --git a/plug-ins/file-dds/ddsread.c b/plug-ins/file-dds/ddsread.c index 510cd43b66..cf76149250 100644 --- a/plug-ins/file-dds/ddsread.c +++ b/plug-ins/file-dds/ddsread.c @@ -743,6 +743,34 @@ read_dds (GFile *file, if (flip_import) gimp_image_flip (image, GIMP_ORIENTATION_VERTICAL); + /* Store original format to use as a default for export */ + if (load_info.comp_format || + load_info.d3d9_format || + load_info.dxgi_format || + load_info.mipmaps) + { + GimpParasite *parasite = NULL; + gchar *import_settings; + + /* Save parasite version, compression format, pixel format, + * DX10 format, flags, and number of mipmaps in the parasite */ + import_settings = g_strdup_printf ("1 %d %d %d %d %d", + load_info.comp_format, + load_info.d3d9_format, + load_info.dxgi_format, + load_info.flags, + load_info.mipmaps); + + parasite = gimp_parasite_new ("dds-import-settings", + GIMP_PARASITE_PERSISTENT, + strlen (import_settings) + 1, + (gpointer) import_settings); + g_free (import_settings); + + gimp_image_attach_parasite (image, parasite); + gimp_parasite_free (parasite); + } + *ret_image = image; return GIMP_PDB_SUCCESS; diff --git a/plug-ins/file-dds/ddswrite.c b/plug-ins/file-dds/ddswrite.c index e9809bf37b..15496c6783 100644 --- a/plug-ins/file-dds/ddswrite.c +++ b/plug-ins/file-dds/ddswrite.c @@ -44,15 +44,16 @@ #include "misc.h" -static gboolean write_image (FILE *fp, - GimpImage *image, - GimpDrawable *drawable, - GimpProcedureConfig *config); -static gboolean save_dialog (GimpImage *image, - GimpDrawable *drawable, - GimpProcedure *procedure, - GimpProcedureConfig *config); +static gboolean write_image (FILE *fp, + GimpImage *image, + GimpDrawable *drawable, + GimpProcedureConfig *config); +static gboolean save_dialog (GimpImage *image, + GimpDrawable *drawable, + GimpProcedure *procedure, + GimpProcedureConfig *config); +static const gchar * check_comp_format (guint32 format); static const gchar *cubemap_face_names[4][6] = { @@ -497,15 +498,15 @@ write_dds (GFile *file, GimpProcedureConfig *config, gboolean is_duplicate_image) { - FILE *fp; - gint rc = 0; - gint compression; - gint mipmaps; - gint savetype; + FILE *fp; + GimpParasite *parasite = NULL; + gint rc = 0; + gint compression; + gint mipmaps; + gint savetype; - savetype = gimp_procedure_config_get_choice_id (config, "save-type"); - compression = gimp_procedure_config_get_choice_id (config, "compression-format"); - mipmaps = gimp_procedure_config_get_choice_id (config, "mipmaps"); + savetype = gimp_procedure_config_get_choice_id (config, "save-type"); + mipmaps = gimp_procedure_config_get_choice_id (config, "mipmaps"); global_image = image; @@ -515,6 +516,45 @@ write_dds (GFile *file, is_volume = check_volume (image); is_array = check_array (image); + /* Check for imported DDS original settings */ + parasite = gimp_image_get_parasite (image, "dds-import-settings"); + if (parasite) + { + gchar *parasite_data; + guint32 parasite_size; + gint version = 0; + gint comp_format = 0; + gint d3d9_format = 0; + gint dxgi_format = 0; + guint flags = 0; + guint n_mipmaps = 0; + guint n_params = 0; + + parasite_data = (gchar *) gimp_parasite_get_data (parasite, + ¶site_size); + parasite_data = g_strndup (parasite_data, parasite_size); + + n_params = sscanf (parasite_data, "%d %d %d %d %d %d", &version, + &comp_format, &d3d9_format, &dxgi_format, &flags, + &n_mipmaps); + if (n_params == 6) + { + const gchar *config_comp_format; + + config_comp_format = check_comp_format (comp_format); + g_object_set (config, + "compression-format", config_comp_format, + NULL); + } + g_free (parasite_data); + + gimp_image_detach_parasite (image, "dds-import-settings"); + g_free (parasite); + } + + compression = gimp_procedure_config_get_choice_id (config, + "compression-format"); + if (interactive) { if (! is_mipmap_chain_valid && @@ -2014,3 +2054,32 @@ save_dialog (GimpImage *image, return run; } + +static const gchar * +check_comp_format (guint32 format) +{ + switch (format) + { + case DDS_COMPRESS_BC1: + return "bc1"; + + case DDS_COMPRESS_BC2: + return "bc2"; + + case DDS_COMPRESS_BC3: + return "bc3"; + + case DDS_COMPRESS_BC4: + return "bc4"; + + case DDS_COMPRESS_BC5: + return "bc5"; + + case DDS_COMPRESS_BC6H: + case DDS_COMPRESS_BC7: + return "bc7"; + + default: + return "none"; + } +}