/* * 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 "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); }