summaryrefslogtreecommitdiffstats
path: root/plug-ins/file-dds/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'plug-ins/file-dds/misc.c')
-rw-r--r--plug-ins/file-dds/misc.c261
1 files changed, 261 insertions, 0 deletions
diff --git a/plug-ins/file-dds/misc.c b/plug-ins/file-dds/misc.c
new file mode 100644
index 0000000..c8c3593
--- /dev/null
+++ b/plug-ins/file-dds/misc.c
@@ -0,0 +1,261 @@
+/*
+ * DDS GIMP plugin
+ *
+ * Copyright (C) 2004-2012 Shawn Kirst <skirst@gmail.com>,
+ * with parts (C) 2003 Arne Reuter <homepage@arnereuter.de> 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 <libgimp/gimp.h>
+#include "misc.h"
+
+static inline float
+saturate (float a)
+{
+ if(a < 0) a = 0;
+ if(a > 1) a = 1;
+
+ return a;
+}
+
+void
+decode_ycocg_image (gint32 drawableID,
+ gboolean shadow)
+{
+ 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;
+
+ buffer = gimp_drawable_get_buffer (drawableID);
+
+ if (shadow)
+ {
+ sbuffer = gimp_drawable_get_shadow_buffer (drawableID);
+ 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);
+ h = gegl_buffer_get_height (buffer);
+ num_pixels = w * h;
+
+ data = g_malloc (num_pixels * 4);
+
+ 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;
+
+ /* convert YCoCg to RGB */
+ Co -= offset;
+ Cg -= offset;
+
+ 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);
+
+ if ((i & 0x7fff) == 0)
+ gimp_progress_update ((float)i / (float)num_pixels);
+ }
+
+ 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 (drawableID, TRUE);
+
+ gimp_drawable_update (drawableID, 0, 0, w, h);
+
+ g_free (data);
+
+ g_object_unref (buffer);
+}
+
+void
+decode_ycocg_scaled_image (gint32 drawableID,
+ gboolean shadow)
+{
+ 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;
+
+ buffer = gimp_drawable_get_buffer (drawableID);
+
+ if (shadow)
+ {
+ sbuffer = gimp_drawable_get_shadow_buffer(drawableID);
+ 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);
+ h = gegl_buffer_get_height (buffer);
+ num_pixels = w * h;
+
+ data = g_malloc (num_pixels * 4);
+
+ 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;
+
+ /* convert YCoCg to RGB */
+ s = 1.0f / ((255.0f / 8.0f) * s + 1.0f);
+
+ Co = (Co - offset) * s;
+ Cg = (Cg - offset) * s;
+
+ 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);
+
+ /* set alpha to 1 */
+ data[4 * i + 3] = 255;
+
+ if ((i & 0x7fff) == 0)
+ gimp_progress_update ((float)i / (float)num_pixels);
+ }
+
+ 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 (drawableID, TRUE);
+
+ gimp_drawable_update (drawableID, 0, 0, w, h);
+
+ g_free (data);
+
+ g_object_unref (buffer);
+}
+
+void
+decode_alpha_exp_image (gint32 drawableID,
+ gboolean shadow)
+{
+ GeglBuffer *buffer, *sbuffer;
+ const Babl *format;
+ unsigned char *data;
+ unsigned int i, w, h, num_pixels;
+ int R, G, B, A;
+
+ buffer = gimp_drawable_get_buffer (drawableID);
+
+ if (shadow)
+ {
+ sbuffer = gimp_drawable_get_shadow_buffer (drawableID);
+ 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);
+ h = gegl_buffer_get_height (buffer);
+ num_pixels = w * h;
+
+ data = g_malloc (num_pixels * 4);
+
+ 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...");
+
+ for (i = 0; i < num_pixels; ++i)
+ {
+ R = data[4 * i + 0];
+ G = data[4 * i + 1];
+ B = data[4 * i + 2];
+ A = data[4 * i + 3];
+
+ R = (R * A + 1) >> 8;
+ G = (G * A + 1) >> 8;
+ B = (B * A + 1) >> 8;
+ A = 255;
+
+ data[4 * i + 0] = R;
+ data[4 * i + 1] = G;
+ data[4 * i + 2] = B;
+ data[4 * i + 3] = A;
+
+ if ((i & 0x7fff) == 0)
+ gimp_progress_update ((float)i / (float)num_pixels);
+ }
+
+ 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 (drawableID, TRUE);
+
+ gimp_drawable_update (drawableID, 0, 0, w, h);
+
+ g_free (data);
+
+ g_object_unref (buffer);
+}