diff --git a/plug-ins/file-dds/color.c b/plug-ins/file-dds/color.c deleted file mode 100644 index 11086cd73e..0000000000 --- a/plug-ins/file-dds/color.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * DDS GIMP plugin - * - * Copyright (C) 2004-2012 Shawn Kirst , - * with parts (C) 2003 Arne Reuter where specified. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301, USA. - */ - -#include - -#include - -#include "color.h" - - -gfloat -linear_to_sRGB (gfloat c) -{ - gfloat v = (gfloat) c; - - if (v < 0.0f) - v = 0.0f; - else if (v > 1.0f) - v = 1.0f; - else if (v <= 0.0031308f) - v = 12.92f * v; - else - v = 1.055f * powf (v, 0.41666f) - 0.055f; - - return v; -} - -gfloat -sRGB_to_linear (gfloat c) -{ - gfloat v = (gfloat) c; - - if (v < 0.0f) - v = 0.0f; - else if (v > 1.0f) - v = 1.0f; - else if (v <= 0.04045f) - v /= 12.92f; - else - v = powf ((v + 0.055f) / 1.055f, 2.4f); - - return v; -} diff --git a/plug-ins/file-dds/color.h b/plug-ins/file-dds/color.h deleted file mode 100644 index f86c44bb1d..0000000000 --- a/plug-ins/file-dds/color.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * DDS GIMP plugin - * - * Copyright (C) 2004-2012 Shawn Kirst , - * with parts (C) 2003 Arne Reuter where specified. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __COLOR_H__ -#define __COLOR_H__ - - -#include "imath.h" - - -/* sRGB encoding & decoding */ -gfloat linear_to_sRGB (gfloat c); -gfloat sRGB_to_linear (gfloat c); - - -/* YCoCg encoding */ -static inline void -RGB_to_YCoCg (guchar *dst, gint r, gint g, gint b) -{ - gint y = ((r + (g << 1) + b) + 2) >> 2; - gint co = ((((r << 1) - (b << 1)) + 2) >> 2) + 128; - gint cg = (((-r + (g << 1) - b) + 2) >> 2) + 128; - - dst[0] = 255; - dst[1] = (cg > 255 ? 255 : (cg < 0 ? 0 : cg)); - dst[2] = (co > 255 ? 255 : (co < 0 ? 0 : co)); - dst[3] = (y > 255 ? 255 : (y < 0 ? 0 : y)); -} - - -/* Other color conversions */ -static inline gint -rgb_to_luminance (gint r, - gint g, - gint b) -{ - /* ITU-R BT.709 luma coefficients, scaled by 256 */ - return ((r * 54 + g * 182 + b * 20) + 128) >> 8; -} - -static inline gushort -pack_r5g6b5 (gint r, - gint g, - gint b) -{ - return (mul8bit (r, 31) << 11) | - (mul8bit (g, 63) << 5) | - (mul8bit (b, 31) ); -} - -static inline gushort -pack_rgba4 (gint r, - gint g, - gint b, - gint a) -{ - return (mul8bit (a, 15) << 12) | - (mul8bit (r, 15) << 8) | - (mul8bit (g, 15) << 4) | - (mul8bit (b, 15) ); -} - -static inline gushort -pack_rgb5a1 (gint r, - gint g, - gint b, - gint a) -{ - return (((a >> 7) & 0x01) << 15) | - (mul8bit (r, 31) << 10) | - (mul8bit (g, 31) << 5) | - (mul8bit (b, 31) ); -} - -static inline guchar -pack_r3g3b2 (gint r, - gint g, - gint b) -{ - return (mul8bit (r, 7) << 5) | - (mul8bit (g, 7) << 2) | - (mul8bit (b, 3) ); -} - -static inline guint -pack_rgb10a2 (gint r, gint g, gint b, gint a) -{ - return ((guint) ((a >> 6) & 0x003) << 30) | - ((guint) ((b << 2) & 0x3ff) << 20) | - ((guint) ((g << 2) & 0x3ff) << 10) | - ((guint) ((r << 2) & 0x3ff) ); -} - - -#endif /* __COLOR_H__ */ diff --git a/plug-ins/file-dds/dds.c b/plug-ins/file-dds/dds.c index b9313138dc..c15fd796e6 100644 --- a/plug-ins/file-dds/dds.c +++ b/plug-ins/file-dds/dds.c @@ -42,10 +42,6 @@ #define LOAD_PROC "file-dds-load" #define SAVE_PROC "file-dds-save" -#define DECODE_YCOCG_PROC "color-decode-ycocg" -#define DECODE_YCOCG_SCALED_PROC "color-decode-ycocg-scaled" -#define DECODE_ALPHA_EXP_PROC "color-decode-alpha-exp" - typedef struct _Dds Dds; typedef struct _DdsClass DdsClass; @@ -86,15 +82,6 @@ static GimpValueArray * dds_save (GimpProcedure *procedure, GimpMetadata *metadata, GimpProcedureConfig *config, gpointer run_data); -#if 0 -static GimpValueArray * dds_decode (GimpProcedure *procedure, - GimpRunMode run_mode, - GimpImage *image, - gint n_drawables, - GimpDrawable **drawables, - GimpProcedureConfig *config, - gpointer run_data); -#endif G_DEFINE_TYPE (Dds, dds, GIMP_TYPE_PLUG_IN) @@ -125,11 +112,6 @@ dds_query_procedures (GimpPlugIn *plug_in) list = g_list_append (list, g_strdup (LOAD_PROC)); list = g_list_append (list, g_strdup (SAVE_PROC)); -#if 0 - list = g_list_append (list, g_strdup (DECODE_YCOCG_PROC)); - list = g_list_append (list, g_strdup (DECODE_YCOCG_SCALED_PROC)); - list = g_list_append (list, g_strdup (DECODE_ALPHA_EXP_PROC)); -#endif return list; } @@ -183,12 +165,6 @@ dds_create_procedure (GimpPlugIn *plug_in, "to opaque black"), TRUE, G_PARAM_READWRITE); - - GIMP_PROC_ARG_BOOLEAN (procedure, "decode-images", - _("Automatically decode YCoCg/AE_xp images when detected"), - _("Decode YCoCg/AExp images when detected"), - TRUE, - G_PARAM_READWRITE); } else if (! strcmp (name, SAVE_PROC)) { @@ -358,78 +334,6 @@ dds_create_procedure (GimpPlugIn *plug_in, 0.0, 1.0, 0.5, G_PARAM_READWRITE); } -#if 0 - else if (! strcmp (name, DECODE_YCOCG_PROC)) - { - procedure = gimp_image_procedure_new (plug_in, name, - GIMP_PDB_PROC_TYPE_PLUGIN, - dds_decode, NULL, NULL); - - gimp_procedure_set_image_types (procedure, "RGBA"); - gimp_procedure_set_sensitivity_mask (procedure, - GIMP_PROCEDURE_SENSITIVE_DRAWABLE); - - gimp_procedure_set_menu_label (procedure, _("Decode YCoCg")); - /* gimp_procedure_add_menu_path (procedure, "/Filters/Colors"); */ - - gimp_procedure_set_documentation (procedure, - _("Converts YCoCg encoded pixels to RGB"), - _("Converts YCoCg encoded pixels to RGB"), - name); - gimp_procedure_set_attribution (procedure, - "Shawn Kirst", - "Shawn Kirst", - "2008"); - } - else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC)) - { - procedure = gimp_image_procedure_new (plug_in, name, - GIMP_PDB_PROC_TYPE_PLUGIN, - dds_decode, NULL, NULL); - - gimp_procedure_set_image_types (procedure, "RGBA"); - gimp_procedure_set_sensitivity_mask (procedure, - GIMP_PROCEDURE_SENSITIVE_DRAWABLE); - - gimp_procedure_set_menu_label (procedure, _("Decode YCoCg (scaled)")); - /* gimp_procedure_add_menu_path (procedure, "/Filters/Colors"); */ - - gimp_procedure_set_documentation (procedure, - _("Converts YCoCg (scaled) encoded " - "pixels to RGB"), - _("Converts YCoCg (scaled) encoded " - "pixels to RGB"), - name); - gimp_procedure_set_attribution (procedure, - "Shawn Kirst", - "Shawn Kirst", - "2008"); - } - else if (! strcmp (name, DECODE_ALPHA_EXP_PROC)) - { - procedure = gimp_image_procedure_new (plug_in, name, - GIMP_PDB_PROC_TYPE_PLUGIN, - dds_decode, NULL, NULL); - - gimp_procedure_set_image_types (procedure, "RGBA"); - gimp_procedure_set_sensitivity_mask (procedure, - GIMP_PROCEDURE_SENSITIVE_DRAWABLE); - - gimp_procedure_set_menu_label (procedure, _("Decode Alpha exponent")); - /* gimp_procedure_add_menu_path (procedure, "/Filters/Colors"); */ - - gimp_procedure_set_documentation (procedure, - _("Converts alpha exponent encoded " - "pixels to RGB", - _("Converts alpha exponent encoded " - "pixels to RGB"), - name); - gimp_procedure_set_attribution (procedure, - "Shawn Kirst", - "Shawn Kirst", - "2008"); - } -#endif return procedure; } @@ -535,53 +439,3 @@ dds_save (GimpProcedure *procedure, return gimp_procedure_new_return_values (procedure, status, error); } - -#if 0 -static GimpValueArray * -dds_decode (GimpProcedure *procedure, - GimpRunMode run_mode, - GimpImage *image, - gint n_drawables, - GimpDrawable **drawables, - GimpProcedureConfig *config, - gpointer run_data) -{ - const gchar *name = gimp_procedure_get_name (procedure); - GimpDrawable *drawable, - - if (n_drawables != 1) - { - GError *error = NULL; - - g_set_error (&error, GIMP_PLUG_IN_ERROR, 0, - _("Procedure '%s' only works with one drawable."), - name); - - return gimp_procedure_new_return_values (procedure, - GIMP_PDB_EXECUTION_ERROR, - error); - } - else - { - drawable = drawables[0]; - } - - if (! strcmp (name, DECODE_YCOCG_PROC)) - { - decode_ycocg_image (drawable, TRUE); - } - else if (! strcmp (name, DECODE_YCOCG_SCALED_PROC)) - { - decode_ycocg_scaled_image (drawable, TRUE); - } - else if (! strcmp (name, DECODE_ALPHA_EXP_PROC)) - { - decode_alpha_exp_image (drawable, TRUE); - } - - if (run_mode != GIMP_RUN_NONINTERACTIVE) - gimp_displays_flush (); - - return gimp_procedure_new_return_values (procedure, GIMP_PDB_SUCCESS, NULL); -} -#endif diff --git a/plug-ins/file-dds/ddsread.c b/plug-ins/file-dds/ddsread.c index ecd04bfc1a..87dd4ee06b 100644 --- a/plug-ins/file-dds/ddsread.c +++ b/plug-ins/file-dds/ddsread.c @@ -65,19 +65,19 @@ typedef struct } dds_load_info_t; -static gboolean read_header (dds_header_t *hdr, - FILE *fp); -static gboolean read_header_dx10 (dds_header_dx10_t *hdr, - FILE *fp); -static gboolean validate_header (dds_header_t *hdr, - GError **error); -static gboolean setup_dxgi_format (dds_header_t *hdr, - const dds_header_dx10_t *dx10hdr, - dds_load_info_t *load_info, - GError **error); -static gboolean load_layer (FILE *fp, - const dds_header_t *hdr, - const dds_header_dx10_t *dx10hdr, +static gboolean read_header (dds_header_t *hdr, + FILE *fp); +static gboolean read_header_dx10 (dds_header_dx10_t *hdr, + FILE *fp); +static gboolean validate_header (dds_header_t *hdr, + GError **error); +static gboolean setup_dxgi_format (dds_header_t *hdr, + const dds_header_dx10_t *dx10hdr, + dds_load_info_t *load_info, + GError **error); +static gboolean load_layer (FILE *fp, + const dds_header_t *hdr, + const dds_header_dx10_t *dx10hdr, dds_load_info_t *load_info, GimpImage *image, guint level, @@ -85,7 +85,6 @@ static gboolean load_layer (FILE *fp, guint *layer_index, guchar *pixels, guchar *buf, - gboolean decode_images, GError **error); static gboolean load_mipmaps (FILE *fp, const dds_header_t *hdr, @@ -97,24 +96,22 @@ static gboolean load_mipmaps (FILE *fp, guchar *pixels, guchar *buf, gboolean read_mipmaps, - gboolean decode_images, GError **error); static gboolean load_face (FILE *fp, - const dds_header_t *hdr, - const dds_header_dx10_t *dx10hdr, - dds_load_info_t *load_info, - GimpImage *image, - gchar *prefix, - guint *layer_index, - guchar *pixels, - guchar *buf, - gboolean read_mipmaps, - gboolean decode_images, - GError **error); -static guchar color_bits (guint mask); -static guchar color_shift (guint mask); -static gboolean load_dialog (GimpProcedure *procedure, - GimpProcedureConfig *config); + const dds_header_t *hdr, + const dds_header_dx10_t *dx10hdr, + dds_load_info_t *load_info, + GimpImage *image, + gchar *prefix, + guint *layer_index, + guchar *pixels, + guchar *buf, + gboolean read_mipmaps, + GError **error); +static guchar color_bits (guint mask); +static guchar color_shift (guint mask); +static gboolean load_dialog (GimpProcedure *procedure, + GimpProcedureConfig *config); /* Read DDS file */ @@ -138,7 +135,6 @@ read_dds (GFile *file, GimpImageBaseType type; GimpPrecision precision; gboolean read_mipmaps; - gboolean decode_images; gint i, j; guint computed_pitch_or_linsize; gboolean flip_import; @@ -156,7 +152,6 @@ read_dds (GFile *file, "load-mipmaps", &read_mipmaps, "flip-image", &flip_import, "bc1-use-transparency", &bc1_use_transparency, - "decode-images", &decode_images, NULL); fp = g_fopen (g_file_peek_path (file), "rb"); @@ -629,7 +624,7 @@ read_dds (GFile *file, dx10hdr.arraySize <= 1) /* Standard image texture with mipmaps */ { if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, "", &layer_index, - pixels, buf, decode_images, error)) + pixels, buf, error)) { fclose (fp); gimp_image_delete (image); @@ -637,7 +632,7 @@ read_dds (GFile *file, } if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, "", &layer_index, - pixels, buf, read_mipmaps, decode_images, error)) + pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -648,7 +643,7 @@ read_dds (GFile *file, { if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive x)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -657,7 +652,7 @@ read_dds (GFile *file, if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative x)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -666,7 +661,7 @@ read_dds (GFile *file, if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive y)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -675,7 +670,7 @@ read_dds (GFile *file, if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative y)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -684,7 +679,7 @@ read_dds (GFile *file, if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(positive z)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -693,7 +688,7 @@ read_dds (GFile *file, if ((hdr.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) && ! load_face (fp, &hdr, &dx10hdr, &load_info, image, "(negative z)", - &layer_index, pixels, buf, read_mipmaps, decode_images, error)) + &layer_index, pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -711,7 +706,7 @@ read_dds (GFile *file, plane = g_strdup_printf ("(z = %d)", i); if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, plane, - &layer_index, pixels, buf, decode_images, error)) + &layer_index, pixels, buf, error)) { g_free (plane); fclose (fp); @@ -738,7 +733,7 @@ read_dds (GFile *file, plane = g_strdup_printf ("(z = %d)", i); if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, level, plane, - &layer_index, pixels, buf, decode_images, error)) + &layer_index, pixels, buf, error)) { g_free (plane); fclose (fp); @@ -761,7 +756,7 @@ read_dds (GFile *file, elem = g_strdup_printf ("(array element %d)", i); if (! load_layer (fp, &hdr, &dx10hdr, &load_info, image, 0, elem, &layer_index, - pixels, buf, decode_images, error)) + pixels, buf, error)) { fclose (fp); gimp_image_delete (image); @@ -769,7 +764,7 @@ read_dds (GFile *file, } if (! load_mipmaps (fp, &hdr, &dx10hdr, &load_info, image, elem, &layer_index, - pixels, buf, read_mipmaps, decode_images, error)) + pixels, buf, read_mipmaps, error)) { fclose (fp); gimp_image_delete (image); @@ -1309,7 +1304,6 @@ load_layer (FILE *fp, guint *layer_index, guchar *pixels, guchar *buf, - gboolean decode_images, GError **error) { GeglBuffer *buffer; @@ -2025,21 +2019,20 @@ load_layer (FILE *fp, g_object_unref (buffer); - /* gimp dds specific. decode encoded images */ - if (decode_images && - hdr->reserved.gimp_dds_special.magic1 == FOURCC ('G','I','M','P') && + /* Decode files with GIMP-specific encodings */ + if (hdr->reserved.gimp_dds_special.magic1 == FOURCC ('G','I','M','P') && hdr->reserved.gimp_dds_special.magic2 == FOURCC ('-','D','D','S')) { switch (hdr->reserved.gimp_dds_special.extra_fourcc) { case FOURCC ('A','E','X','P'): - decode_alpha_exp_image (GIMP_DRAWABLE (layer), FALSE); + decode_alpha_exponent (GIMP_DRAWABLE (layer)); break; case FOURCC ('Y','C','G','1'): - decode_ycocg_image (GIMP_DRAWABLE (layer), FALSE); + decode_ycocg (GIMP_DRAWABLE (layer)); break; case FOURCC ('Y','C','G','2'): - decode_ycocg_scaled_image (GIMP_DRAWABLE (layer), FALSE); + decode_ycocg_scaled (GIMP_DRAWABLE (layer)); break; default: break; @@ -2060,7 +2053,6 @@ load_mipmaps (FILE *fp, guchar *pixels, guchar *buf, gboolean read_mipmaps, - gboolean decode_images, GError **error) { guint level; @@ -2072,7 +2064,7 @@ load_mipmaps (FILE *fp, for (level = 1; level < hdr->num_mipmaps; ++level) { if (! load_layer (fp, hdr, dx10hdr, load_info, image, level, prefix, layer_index, - pixels, buf, decode_images, error)) + pixels, buf, error)) return FALSE; } } @@ -2091,15 +2083,14 @@ load_face (FILE *fp, guchar *pixels, guchar *buf, gboolean read_mipmaps, - gboolean decode_images, GError **error) { if (! load_layer (fp, hdr, dx10hdr, load_info, image, 0, prefix, - layer_index, pixels, buf, decode_images, error)) + layer_index, pixels, buf, error)) return FALSE; return load_mipmaps (fp, hdr, dx10hdr, load_info, image, prefix, layer_index, - pixels, buf, read_mipmaps, decode_images, error); + pixels, buf, read_mipmaps, error); } static guchar @@ -2124,7 +2115,7 @@ color_shift (guint mask) if (! mask) return 0; - while (!((mask >> i) & 1)) + while (! ((mask >> i) & 1)) ++i; return i; @@ -2147,7 +2138,6 @@ load_dialog (GimpProcedure *procedure, "load-mipmaps", "flip-image", "bc1-use-transparency", - "decode-images", NULL); gtk_box_set_spacing (GTK_BOX (vbox), 8); gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); diff --git a/plug-ins/file-dds/ddswrite.c b/plug-ins/file-dds/ddswrite.c index c29b07a632..4e376889bb 100644 --- a/plug-ins/file-dds/ddswrite.c +++ b/plug-ins/file-dds/ddswrite.c @@ -35,13 +35,13 @@ #include -#include "color.h" #include "dds.h" #include "ddswrite.h" #include "dxt.h" #include "endian_rw.h" #include "imath.h" #include "mipmap.h" +#include "misc.h" static gboolean write_image (FILE *fp, @@ -244,7 +244,7 @@ check_cubemap (GimpImage *image) (gimp_drawable_get_height (drawable) != h)) continue; - layer_name = (char *) gimp_item_get_name (GIMP_ITEM (drawable)); + layer_name = (gchar *) gimp_item_get_name (GIMP_ITEM (drawable)); for (j = 0; j < 6; ++j) { for (k = 0; k < 4; ++k) @@ -608,45 +608,6 @@ swap_rb (guchar *pixels, } } -static void -alpha_exp (guchar *dst, - gint r, - gint g, - gint b, - gint a) -{ - gfloat ar, ag, ab, aa; - - ar = (gfloat) r / 255.0f; - ag = (gfloat) g / 255.0f; - ab = (gfloat) b / 255.0f; - - aa = MAX (ar, MAX (ag, ab)); - - if (aa < 1e-04f) - { - dst[0] = b; - dst[1] = g; - dst[2] = r; - dst[3] = 255; - return; - } - - ar /= aa; - ag /= aa; - ab /= aa; - - r = (gint) floorf (255.0f * ar + 0.5f); - g = (gint) floorf (255.0f * ag + 0.5f); - b = (gint) floorf (255.0f * ab + 0.5f); - a = (gint) floorf (255.0f * aa + 0.5f); - - dst[0] = MAX (0, MIN (255, b)); - dst[1] = MAX (0, MIN (255, g)); - dst[2] = MAX (0, MIN (255, r)); - dst[3] = MAX (0, MIN (255, a)); -} - static void convert_pixels (guchar *dst, guchar *src, @@ -729,36 +690,56 @@ convert_pixels (guchar *dst, dst[4 * i + 3] = a; break; case DDS_FORMAT_R5G6B5: - PUTL16 (&dst[2 * i], pack_r5g6b5 (r, g, b)); + PUTL16 (&dst[2 * i], + (mul8bit (r, 31) << 11) | + (mul8bit (g, 63) << 5) | + (mul8bit (b, 31) )); break; case DDS_FORMAT_RGBA4: - PUTL16 (&dst[2 * i], pack_rgba4 (r, g, b, a)); + PUTL16 (&dst[2 * i], + (mul8bit (a, 15) << 12) | + (mul8bit (r, 15) << 8) | + (mul8bit (g, 15) << 4) | + (mul8bit (b, 15) )); break; case DDS_FORMAT_RGB5A1: - PUTL16 (&dst[2 * i], pack_rgb5a1 (r, g, b, a)); + PUTL16 (&dst[2 * i], + (((a >> 7) & 0x01) << 15) | + (mul8bit (r, 31) << 10) | + (mul8bit (g, 31) << 5) | + (mul8bit (b, 31) )); break; case DDS_FORMAT_RGB10A2: - PUTL32 (&dst[4 * i], pack_rgb10a2 (r, g, b, a)); + PUTL32 (&dst[4 * i], + ((guint) ((a >> 6) & 0x003) << 30) | + ((guint) ((b << 2) & 0x3ff) << 20) | + ((guint) ((g << 2) & 0x3ff) << 10) | + ((guint) ((r << 2) & 0x3ff) )); break; case DDS_FORMAT_R3G3B2: - dst[i] = pack_r3g3b2 (r, g, b); + dst[i] = + (mul8bit (r, 7) << 5) | + (mul8bit (g, 7) << 2) | + (mul8bit (b, 3) ); break; case DDS_FORMAT_A8: dst[i] = a; break; case DDS_FORMAT_L8: - dst[i] = rgb_to_luminance (r, g, b); + dst[i] = + ((r * 54 + g * 182 + b * 20) + 128) >> 8; break; case DDS_FORMAT_L8A8: - dst[2 * i + 0] = rgb_to_luminance (r, g, b); + dst[2 * i + 0] = + ((r * 54 + g * 182 + b * 20) + 128) >> 8; dst[2 * i + 1] = a; break; case DDS_FORMAT_YCOCG: dst[4 * i] = a; - RGB_to_YCoCg (&dst[4 * i], r, g, b); + encode_ycocg (&dst[4 * i], r, g, b); break; case DDS_FORMAT_AEXP: - alpha_exp (&dst[4 * i], r, g, b, a); + encode_alpha_exponent (&dst[4 * i], r, g, b, a); break; default: break; diff --git a/plug-ins/file-dds/dxt.c b/plug-ins/file-dds/dxt.c index e0c214336d..f992944be1 100644 --- a/plug-ins/file-dds/dxt.c +++ b/plug-ins/file-dds/dxt.c @@ -34,11 +34,14 @@ #include #include +#include + #include "dds.h" #include "dxt.h" #include "endian_rw.h" -#include "mipmap.h" #include "imath.h" +#include "mipmap.h" +#include "misc.h" #include "vec.h" #include "dxt_tables.h" @@ -757,181 +760,6 @@ encode_color_block (unsigned char *dst, PUTL32(dst + 4, indices); } -static void -get_min_max_YCoCg (const unsigned char *block, - unsigned char *mincolor, - unsigned char *maxcolor) -{ - int i; - - mincolor[2] = mincolor[1] = 255; - maxcolor[2] = maxcolor[1] = 0; - - for (i = 0; i < 16; ++i) - { - if (block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2]; - if (block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1]; - if (block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2]; - if (block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1]; - } -} - -static void -scale_YCoCg (unsigned char *block, - unsigned char *mincolor, - unsigned char *maxcolor) -{ - const int s0 = 128 / 2 - 1; - const int s1 = 128 / 4 - 1; - int m0, m1, m2, m3; - int mask0, mask1, scale; - int i; - - m0 = abs(mincolor[2] - 128); - m1 = abs(mincolor[1] - 128); - m2 = abs(maxcolor[2] - 128); - m3 = abs(maxcolor[1] - 128); - - if (m1 > m0) m0 = m1; - if (m3 > m2) m2 = m3; - if (m2 > m0) m0 = m2; - - mask0 = -(m0 <= s0); - mask1 = -(m0 <= s1); - scale = 1 + (1 & mask0) + (2 & mask1); - - mincolor[2] = (mincolor[2] - 128) * scale + 128; - mincolor[1] = (mincolor[1] - 128) * scale + 128; - mincolor[0] = (scale - 1) << 3; - - maxcolor[2] = (maxcolor[2] - 128) * scale + 128; - maxcolor[1] = (maxcolor[1] - 128) * scale + 128; - maxcolor[0] = (scale - 1) << 3; - - for (i = 0; i < 16; ++i) - { - block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128; - block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128; - } -} - -#define INSET_SHIFT 4 - -static void -inset_bbox_YCoCg (unsigned char *mincolor, - unsigned char *maxcolor) -{ - int inset[4], mini[4], maxi[4]; - - inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1); - inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1); - - mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT; - mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT; - - maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT; - maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT; - - mini[2] = (mini[2] >= 0) ? mini[2] : 0; - mini[1] = (mini[1] >= 0) ? mini[1] : 0; - - maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255; - maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255; - - mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5); - mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6); - - maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5); - maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6); -} - -static void -select_diagonal_YCoCg (const unsigned char *block, - unsigned char *mincolor, - unsigned char *maxcolor) -{ - unsigned char mid0, mid1, side, mask, b0, b1, c0, c1; - int i; - - mid0 = ((int)mincolor[2] + maxcolor[2] + 1) >> 1; - mid1 = ((int)mincolor[1] + maxcolor[1] + 1) >> 1; - - side = 0; - for (i = 0; i < 16; ++i) - { - b0 = block[i * 4 + 2] >= mid0; - b1 = block[i * 4 + 1] >= mid1; - side += (b0 ^ b1); - } - - mask = -(side > 8); - mask &= -(mincolor[2] != maxcolor[2]); - - c0 = mincolor[1]; - c1 = maxcolor[1]; - - c0 ^= c1; - c1 ^= c0 & mask; - c0 ^= c1; - - mincolor[1] = c0; - maxcolor[1] = c1; -} - -static void -encode_YCoCg_block (unsigned char *dst, - unsigned char *block) -{ - unsigned char colors[4][3], *maxcolor, *mincolor; - unsigned int mask; - int c0, c1, d0, d1, d2, d3; - int b0, b1, b2, b3, b4; - int x0, x1, x2; - int i, idx; - - maxcolor = &colors[0][0]; - mincolor = &colors[1][0]; - - get_min_max_YCoCg(block, mincolor, maxcolor); - scale_YCoCg(block, mincolor, maxcolor); - inset_bbox_YCoCg(mincolor, maxcolor); - select_diagonal_YCoCg(block, mincolor, maxcolor); - - lerp_rgb13(&colors[2][0], maxcolor, mincolor); - lerp_rgb13(&colors[3][0], mincolor, maxcolor); - - mask = 0; - - for (i = 0; i < 16; ++i) - { - c0 = block[4 * i + 2]; - c1 = block[4 * i + 1]; - - d0 = abs(colors[0][2] - c0) + abs(colors[0][1] - c1); - d1 = abs(colors[1][2] - c0) + abs(colors[1][1] - c1); - d2 = abs(colors[2][2] - c0) + abs(colors[2][1] - c1); - d3 = abs(colors[3][2] - c0) + abs(colors[3][1] - c1); - - b0 = d0 > d3; - b1 = d1 > d2; - b2 = d0 > d2; - b3 = d1 > d3; - b4 = d2 > d3; - - x0 = b1 & b2; - x1 = b0 & b3; - x2 = b0 & b4; - - idx = (x2 | ((x0 | x1) << 1)); - - mask |= idx << (2 * i); - } - - PUTL16(dst + 0, pack_rgb565(maxcolor)); - PUTL16(dst + 2, pack_rgb565(mincolor)); - PUTL32(dst + 4, mask); -} - /* write DXT3 alpha block */ static void encode_alpha_block_BC2 (unsigned char *dst, diff --git a/plug-ins/file-dds/meson.build b/plug-ins/file-dds/meson.build index 9a2dd8d27f..41ed7c9e7f 100644 --- a/plug-ins/file-dds/meson.build +++ b/plug-ins/file-dds/meson.build @@ -2,7 +2,6 @@ plugin_name = 'file-dds' plugin_sources = [ 'dds.c', - 'color.c', 'ddsread.c', 'ddswrite.c', 'dxt.c', diff --git a/plug-ins/file-dds/mipmap.c b/plug-ins/file-dds/mipmap.c index ec4c68e311..3a37589fe4 100644 --- a/plug-ins/file-dds/mipmap.c +++ b/plug-ins/file-dds/mipmap.c @@ -36,7 +36,6 @@ #include "dds.h" #include "mipmap.h" #include "imath.h" -#include "color.h" typedef gfloat (*filterfunc_t) (gfloat); @@ -217,6 +216,23 @@ wrap_clamp (gint x, * Gamma-correction */ +static gfloat +linear_to_sRGB (gfloat c) +{ + gfloat v = (gfloat) c; + + if (v < 0.0f) + v = 0.0f; + else if (v > 1.0f) + v = 1.0f; + else if (v <= 0.0031308f) + v = 12.92f * v; + else + v = 1.055f * powf (v, 0.41666f) - 0.055f; + + return v; +} + static gfloat linear_to_gamma (gint gc, gfloat v, @@ -236,6 +252,24 @@ linear_to_gamma (gint gc, return v; } + +static gfloat +sRGB_to_linear (gfloat c) +{ + gfloat v = (gfloat) c; + + if (v < 0.0f) + v = 0.0f; + else if (v > 1.0f) + v = 1.0f; + else if (v <= 0.04045f) + v /= 12.92f; + else + v = powf ((v + 0.055f) / 1.055f, 2.4f); + + return v; +} + static gfloat gamma_to_linear (gint gc, gfloat v, diff --git a/plug-ins/file-dds/misc.c b/plug-ins/file-dds/misc.c index 4b0db80f8d..320f2fb00c 100644 --- a/plug-ins/file-dds/misc.c +++ b/plug-ins/file-dds/misc.c @@ -4,56 +4,53 @@ * Copyright (C) 2004-2012 Shawn Kirst , * with parts (C) 2003 Arne Reuter where specified. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301, USA. + * along with this program. If not, see . */ #include + +#include "endian_rw.h" +#include "imath.h" #include "misc.h" -static inline float -saturate (float a) -{ - if(a < 0) a = 0; - if(a > 1) a = 1; +/* + * Decoding Functions + */ + +static inline gfloat +saturate (gfloat a) +{ + if (a < 0) a = 0; + if (a > 1) a = 1; return a; } void -decode_ycocg_image (GimpDrawable *drawable, - gboolean shadow) +decode_ycocg (GimpDrawable *drawable) { - GeglBuffer *buffer, *sbuffer; - const Babl *format; - unsigned char *data; - unsigned int i, w, h, num_pixels; - - const float offset = 0.5f * 256.0f / 255.0f; - float Y, Co, Cg, R, G, B; + GeglBuffer *buffer; + const Babl *format; + guchar *data; + guint num_pixels; + guint i, w, h; + const gfloat offset = 0.5f * 256.0f / 255.0f; + gfloat Y, Co, Cg; + gfloat R, G, B; buffer = gimp_drawable_get_buffer (drawable); - if (shadow) - { - sbuffer = gimp_drawable_get_shadow_buffer (drawable); - gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL); - g_object_unref (buffer); - buffer = sbuffer; - } - format = babl_format ("R'G'B'A u8"); w = gegl_buffer_get_width (buffer); @@ -62,46 +59,43 @@ decode_ycocg_image (GimpDrawable *drawable, data = g_malloc (num_pixels * 4); - gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data, + gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gimp_progress_init ("Decoding YCoCg pixels..."); for (i = 0; i < num_pixels; ++i) { - Y = (float)data[4 * i + 3] / 255.0f; - Co = (float)data[4 * i + 0] / 255.0f; - Cg = (float)data[4 * i + 1] / 255.0f; + Y = (gfloat) data[4 * i + 3] / 255.0f; + Co = (gfloat) data[4 * i + 0] / 255.0f; + Cg = (gfloat) data[4 * i + 1] / 255.0f; /* convert YCoCg to RGB */ Co -= offset; Cg -= offset; - R = saturate(Y + Co - Cg); - G = saturate(Y + Cg); - B = saturate(Y - Co - Cg); + R = saturate (Y + Co - Cg); + G = saturate (Y + Cg); + B = saturate (Y - Co - Cg); /* copy new alpha from blue */ data[4 * i + 3] = data[4 * i + 2]; - data[4 * i + 0] = (unsigned char)(R * 255.0f); - data[4 * i + 1] = (unsigned char)(G * 255.0f); - data[4 * i + 2] = (unsigned char)(B * 255.0f); + data[4 * i + 0] = (guchar) (R * 255.0f); + data[4 * i + 1] = (guchar) (G * 255.0f); + data[4 * i + 2] = (guchar) (B * 255.0f); if ((i & 0x7fff) == 0) - gimp_progress_update ((float)i / (float)num_pixels); + gimp_progress_update ((gdouble) i / (gdouble) num_pixels); } - gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data, + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data, GEGL_AUTO_ROWSTRIDE); gimp_progress_update (1.0); gegl_buffer_flush (buffer); - if (shadow) - gimp_drawable_merge_shadow (drawable, TRUE); - gimp_drawable_update (drawable, 0, 0, w, h); g_free (data); @@ -110,27 +104,19 @@ decode_ycocg_image (GimpDrawable *drawable, } void -decode_ycocg_scaled_image (GimpDrawable *drawable, - gboolean shadow) +decode_ycocg_scaled (GimpDrawable *drawable) { - GeglBuffer *buffer, *sbuffer; - const Babl *format; - unsigned char *data; - unsigned int i, w, h, num_pixels; - - const float offset = 0.5f * 256.0f / 255.0f; - float Y, Co, Cg, R, G, B, s; + GeglBuffer *buffer; + const Babl *format; + guchar *data; + guint num_pixels; + guint i, w, h; + const gfloat offset = 0.5f * 256.0f / 255.0f; + gfloat Y, Co, Cg; + gfloat R, G, B, s; buffer = gimp_drawable_get_buffer (drawable); - if (shadow) - { - sbuffer = gimp_drawable_get_shadow_buffer (drawable); - gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL); - g_object_unref (buffer); - buffer = sbuffer; - } - format = babl_format ("R'G'B'A u8"); w = gegl_buffer_get_width (buffer); @@ -139,17 +125,17 @@ decode_ycocg_scaled_image (GimpDrawable *drawable, data = g_malloc (num_pixels * 4); - gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data, + gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gimp_progress_init ("Decoding YCoCg (scaled) pixels..."); for (i = 0; i < num_pixels; ++i) { - Y = (float)data[4 * i + 3] / 255.0f; - Co = (float)data[4 * i + 0] / 255.0f; - Cg = (float)data[4 * i + 1] / 255.0f; - s = (float)data[4 * i + 2] / 255.0f; + Y = (gfloat) data[4 * i + 3] / 255.0f; + Co = (gfloat) data[4 * i + 0] / 255.0f; + Cg = (gfloat) data[4 * i + 1] / 255.0f; + s = (gfloat) data[4 * i + 2] / 255.0f; /* convert YCoCg to RGB */ s = 1.0f / ((255.0f / 8.0f) * s + 1.0f); @@ -157,31 +143,28 @@ decode_ycocg_scaled_image (GimpDrawable *drawable, Co = (Co - offset) * s; Cg = (Cg - offset) * s; - R = saturate(Y + Co - Cg); - G = saturate(Y + Cg); - B = saturate(Y - Co - Cg); + R = saturate (Y + Co - Cg); + G = saturate (Y + Cg); + B = saturate (Y - Co - Cg); - data[4 * i + 0] = (unsigned char)(R * 255.0f); - data[4 * i + 1] = (unsigned char)(G * 255.0f); - data[4 * i + 2] = (unsigned char)(B * 255.0f); + data[4 * i + 0] = (guchar) (R * 255.0f); + data[4 * i + 1] = (guchar) (G * 255.0f); + data[4 * i + 2] = (guchar) (B * 255.0f); /* set alpha to 1 */ data[4 * i + 3] = 255; if ((i & 0x7fff) == 0) - gimp_progress_update ((float)i / (float)num_pixels); + gimp_progress_update ((gdouble) i / (gdouble) num_pixels); } - gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data, + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data, GEGL_AUTO_ROWSTRIDE); gimp_progress_update (1.0); gegl_buffer_flush (buffer); - if (shadow) - gimp_drawable_merge_shadow (drawable, TRUE); - gimp_drawable_update (drawable, 0, 0, w, h); g_free (data); @@ -190,25 +173,17 @@ decode_ycocg_scaled_image (GimpDrawable *drawable, } void -decode_alpha_exp_image (GimpDrawable *drawable, - gboolean shadow) +decode_alpha_exponent (GimpDrawable *drawable) { - GeglBuffer *buffer, *sbuffer; + GeglBuffer *buffer; const Babl *format; - unsigned char *data; - unsigned int i, w, h, num_pixels; - int R, G, B, A; + guchar *data; + guint num_pixels; + guint i, w, h; + gint R, G, B, A; buffer = gimp_drawable_get_buffer (drawable); - if (shadow) - { - sbuffer = gimp_drawable_get_shadow_buffer (drawable); - gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, sbuffer, NULL); - g_object_unref (buffer); - buffer = sbuffer; - } - format = babl_format ("R'G'B'A u8"); w = gegl_buffer_get_width (buffer); @@ -217,7 +192,7 @@ decode_alpha_exp_image (GimpDrawable *drawable, data = g_malloc (num_pixels * 4); - gegl_buffer_get (buffer, GEGL_RECTANGLE(0, 0, w, h), 1.0, format, data, + gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, w, h), 1.0, format, data, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); gimp_progress_init ("Decoding Alpha-exponent pixels..."); @@ -240,22 +215,268 @@ decode_alpha_exp_image (GimpDrawable *drawable, data[4 * i + 3] = A; if ((i & 0x7fff) == 0) - gimp_progress_update ((float)i / (float)num_pixels); + gimp_progress_update ((gdouble) i / (gdouble) num_pixels); } - gegl_buffer_set (buffer, GEGL_RECTANGLE(0, 0, w, h), 0, format, data, + gegl_buffer_set (buffer, GEGL_RECTANGLE (0, 0, w, h), 0, format, data, GEGL_AUTO_ROWSTRIDE); gimp_progress_update (1.0); gegl_buffer_flush (buffer); - if (shadow) - gimp_drawable_merge_shadow (drawable, TRUE); - gimp_drawable_update (drawable, 0, 0, w, h); g_free (data); g_object_unref (buffer); } + + +/* + * Encoding Functions + */ + +void +encode_ycocg (guchar *dst, + gint r, + gint g, + gint b) +{ + gint y = ((r + (g << 1) + b) + 2) >> 2; + gint co = ((((r << 1) - (b << 1)) + 2) >> 2) + 128; + gint cg = (((-r + (g << 1) - b) + 2) >> 2) + 128; + + dst[0] = 255; + dst[1] = (cg > 255 ? 255 : (cg < 0 ? 0 : cg)); + dst[2] = (co > 255 ? 255 : (co < 0 ? 0 : co)); + dst[3] = (y > 255 ? 255 : (y < 0 ? 0 : y)); +} + +void +encode_alpha_exponent (guchar *dst, + gint r, + gint g, + gint b, + gint a) +{ + gfloat ar, ag, ab, aa; + + ar = (gfloat) r / 255.0f; + ag = (gfloat) g / 255.0f; + ab = (gfloat) b / 255.0f; + + aa = MAX (ar, MAX (ag, ab)); + + if (aa < 1e-04f) + { + dst[0] = b; + dst[1] = g; + dst[2] = r; + dst[3] = 255; + return; + } + + ar /= aa; + ag /= aa; + ab /= aa; + + r = (gint) floorf (255.0f * ar + 0.5f); + g = (gint) floorf (255.0f * ag + 0.5f); + b = (gint) floorf (255.0f * ab + 0.5f); + a = (gint) floorf (255.0f * aa + 0.5f); + + dst[0] = MAX (0, MIN (255, b)); + dst[1] = MAX (0, MIN (255, g)); + dst[2] = MAX (0, MIN (255, r)); + dst[3] = MAX (0, MIN (255, a)); +} + + +/* + * Compression Functions + */ + +static void +get_min_max_YCoCg (const guchar *block, + guchar *mincolor, + guchar *maxcolor) +{ + gint i; + + mincolor[2] = mincolor[1] = 255; + maxcolor[2] = maxcolor[1] = 0; + + for (i = 0; i < 16; ++i) + { + if (block[4 * i + 2] < mincolor[2]) mincolor[2] = block[4 * i + 2]; + if (block[4 * i + 1] < mincolor[1]) mincolor[1] = block[4 * i + 1]; + if (block[4 * i + 2] > maxcolor[2]) maxcolor[2] = block[4 * i + 2]; + if (block[4 * i + 1] > maxcolor[1]) maxcolor[1] = block[4 * i + 1]; + } +} + +static void +scale_YCoCg (guchar *block, + guchar *mincolor, + guchar *maxcolor) +{ + const gint s0 = 128 / 2 - 1; + const gint s1 = 128 / 4 - 1; + gint m0, m1, m2, m3; + gint mask0, mask1, scale; + gint i; + + m0 = abs (mincolor[2] - 128); + m1 = abs (mincolor[1] - 128); + m2 = abs (maxcolor[2] - 128); + m3 = abs (maxcolor[1] - 128); + + if (m1 > m0) m0 = m1; + if (m3 > m2) m2 = m3; + if (m2 > m0) m0 = m2; + + mask0 = -(m0 <= s0); + mask1 = -(m0 <= s1); + scale = 1 + (1 & mask0) + (2 & mask1); + + mincolor[2] = (mincolor[2] - 128) * scale + 128; + mincolor[1] = (mincolor[1] - 128) * scale + 128; + mincolor[0] = (scale - 1) << 3; + + maxcolor[2] = (maxcolor[2] - 128) * scale + 128; + maxcolor[1] = (maxcolor[1] - 128) * scale + 128; + maxcolor[0] = (scale - 1) << 3; + + for (i = 0; i < 16; ++i) + { + block[i * 4 + 2] = (block[i * 4 + 2] - 128) * scale + 128; + block[i * 4 + 1] = (block[i * 4 + 1] - 128) * scale + 128; + } +} + +#define INSET_SHIFT 4 + +static void +inset_bbox_YCoCg (guchar *mincolor, + guchar *maxcolor) +{ + gint inset[4], mini[4], maxi[4]; + + inset[2] = (maxcolor[2] - mincolor[2]) - ((1 << (INSET_SHIFT - 1)) - 1); + inset[1] = (maxcolor[1] - mincolor[1]) - ((1 << (INSET_SHIFT - 1)) - 1); + + mini[2] = ((mincolor[2] << INSET_SHIFT) + inset[2]) >> INSET_SHIFT; + mini[1] = ((mincolor[1] << INSET_SHIFT) + inset[1]) >> INSET_SHIFT; + + maxi[2] = ((maxcolor[2] << INSET_SHIFT) - inset[2]) >> INSET_SHIFT; + maxi[1] = ((maxcolor[1] << INSET_SHIFT) - inset[1]) >> INSET_SHIFT; + + mini[2] = (mini[2] >= 0) ? mini[2] : 0; + mini[1] = (mini[1] >= 0) ? mini[1] : 0; + + maxi[2] = (maxi[2] <= 255) ? maxi[2] : 255; + maxi[1] = (maxi[1] <= 255) ? maxi[1] : 255; + + mincolor[2] = (mini[2] & 0xf8) | (mini[2] >> 5); + mincolor[1] = (mini[1] & 0xfc) | (mini[1] >> 6); + + maxcolor[2] = (maxi[2] & 0xf8) | (maxi[2] >> 5); + maxcolor[1] = (maxi[1] & 0xfc) | (maxi[1] >> 6); +} + +static void +select_diagonal_YCoCg (const guchar *block, + guchar *mincolor, + guchar *maxcolor) +{ + guchar mid0, mid1, side, mask, b0, b1, c0, c1; + gint i; + + mid0 = ((gint) mincolor[2] + maxcolor[2] + 1) >> 1; + mid1 = ((gint) mincolor[1] + maxcolor[1] + 1) >> 1; + + side = 0; + for (i = 0; i < 16; ++i) + { + b0 = block[i * 4 + 2] >= mid0; + b1 = block[i * 4 + 1] >= mid1; + side += (b0 ^ b1); + } + + mask = -(side > 8); + mask &= -(mincolor[2] != maxcolor[2]); + + c0 = mincolor[1]; + c1 = maxcolor[1]; + + c0 ^= c1; + c1 ^= c0 & mask; + c0 ^= c1; + + mincolor[1] = c0; + maxcolor[1] = c1; +} + +void +encode_YCoCg_block (guchar *dst, + guchar *block) +{ + guchar colors[4][3], *maxcolor, *mincolor; + guint mask; + gint c0, c1, d0, d1, d2, d3; + gint b0, b1, b2, b3, b4; + gint x0, x1, x2; + gint i, idx; + + maxcolor = &colors[0][0]; + mincolor = &colors[1][0]; + + get_min_max_YCoCg (block, mincolor, maxcolor); + scale_YCoCg (block, mincolor, maxcolor); + inset_bbox_YCoCg (mincolor, maxcolor); + select_diagonal_YCoCg (block, mincolor, maxcolor); + + colors[2][0] = (2 * maxcolor[0] + mincolor[0]) / 3; + colors[2][1] = (2 * maxcolor[1] + mincolor[1]) / 3; + colors[2][2] = (2 * maxcolor[2] + mincolor[2]) / 3; + + colors[3][0] = (2 * mincolor[0] + maxcolor[0]) / 3; + colors[3][1] = (2 * mincolor[1] + maxcolor[1]) / 3; + colors[3][2] = (2 * mincolor[2] + maxcolor[2]) / 3; + + mask = 0; + + for (i = 0; i < 16; ++i) + { + c0 = block[4 * i + 2]; + c1 = block[4 * i + 1]; + + d0 = abs (colors[0][2] - c0) + abs (colors[0][1] - c1); + d1 = abs (colors[1][2] - c0) + abs (colors[1][1] - c1); + d2 = abs (colors[2][2] - c0) + abs (colors[2][1] - c1); + d3 = abs (colors[3][2] - c0) + abs (colors[3][1] - c1); + + b0 = d0 > d3; + b1 = d1 > d2; + b2 = d0 > d2; + b3 = d1 > d3; + b4 = d2 > d3; + + x0 = b1 & b2; + x1 = b0 & b3; + x2 = b0 & b4; + + idx = (x2 | ((x0 | x1) << 1)); + + mask |= idx << (2 * i); + } + + PUTL16 (dst + 0, (mul8bit (maxcolor[2], 31) << 11) | + (mul8bit (maxcolor[1], 63) << 5) | + (mul8bit (maxcolor[0], 31) )); + PUTL16 (dst + 2, (mul8bit (mincolor[2], 31) << 11) | + (mul8bit (mincolor[1], 63) << 5) | + (mul8bit (mincolor[0], 31) )); + PUTL32 (dst + 4, mask); +} diff --git a/plug-ins/file-dds/misc.h b/plug-ins/file-dds/misc.h index 02e6b7b7e0..1b4f5eb0e0 100644 --- a/plug-ins/file-dds/misc.h +++ b/plug-ins/file-dds/misc.h @@ -21,11 +21,26 @@ #ifndef __MISC_H__ #define __MISC_H__ -void decode_ycocg_image (GimpDrawable *drawable, - gboolean shadow); -void decode_ycocg_scaled_image (GimpDrawable *drawable, - gboolean shadow); -void decode_alpha_exp_image (GimpDrawable *drawable, - gboolean shadow); + +void decode_ycocg (GimpDrawable *drawable); + +void decode_ycocg_scaled (GimpDrawable *drawable); + +void decode_alpha_exponent (GimpDrawable *drawable); + +void encode_ycocg (guchar *dst, + gint r, + gint g, + gint b); + +void encode_alpha_exponent (guchar *dst, + gint r, + gint g, + gint b, + gint a); + +void encode_YCoCg_block (guchar *dst, + guchar *block); + #endif /* __MISC_H__ */