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