diff options
Diffstat (limited to 'plug-ins/file-dds/misc.c')
-rw-r--r-- | plug-ins/file-dds/misc.c | 261 |
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); +} |