Author: post
Date: 2011-04-25 16:40:02 +0200 (Mon, 25 Apr 2011)
New Revision: 4014

Modified:
   trunk/plugins/colorspace-transform/colorspace_transform.c
   trunk/plugins/colorspace-transform/rs-cmm.c
   trunk/plugins/colorspace-transform/rs-cmm.h
Log:
Add 16 to 8 bit LittleCMS convertion to properly support display profiles. Also 
do all LittleCMS transforms multithreaded.

Modified: trunk/plugins/colorspace-transform/colorspace_transform.c
===================================================================
--- trunk/plugins/colorspace-transform/colorspace_transform.c   2011-04-25 
13:01:15 UTC (rev 4013)
+++ trunk/plugins/colorspace-transform/colorspace_transform.c   2011-04-25 
14:40:02 UTC (rev 4014)
@@ -46,7 +46,7 @@
 
 static RSFilterResponse *get_image(RSFilter *filter, const RSFilterRequest 
*request);
 static RSFilterResponse *get_image8(RSFilter *filter, const RSFilterRequest 
*request);
-static gboolean convert_colorspace16(RSColorspaceTransform 
*colorspace_transform, RS_IMAGE16 *input_image, RS_IMAGE16 *output_image, 
RSColorSpace *input_space, RSColorSpace *output_space);
+static gboolean convert_colorspace16(RSColorspaceTransform 
*colorspace_transform, RS_IMAGE16 *input_image, RS_IMAGE16 *output_image, 
RSColorSpace *input_space, RSColorSpace *output_space, GdkRectangle *_roi);
 static void convert_colorspace8(RSColorspaceTransform *colorspace_transform, 
RS_IMAGE16 *input_image, GdkPixbuf *output_image, RSColorSpace *input_space, 
RSColorSpace *output_space, GdkRectangle *roi);
 
 static RSFilterClass *rs_colorspace_transform_parent_class = NULL;
@@ -95,8 +95,10 @@
        RSFilterResponse *response;
        RS_IMAGE16 *input;
        RS_IMAGE16 *output = NULL;
+       GdkRectangle *roi;
        int i;
 
+       roi = rs_filter_request_get_roi(request);
        previous_response = rs_filter_get_image(filter->previous, request);
        input = rs_filter_response_get_image(previous_response);
        if (!RS_IS_IMAGE16(input))
@@ -119,7 +121,7 @@
 
                output = rs_image16_copy(input, FALSE);
 
-               if (convert_colorspace16(colorspace_transform, input, output, 
input_space, output_space))
+               if (convert_colorspace16(colorspace_transform, input, output, 
input_space, output_space, roi))
                {
                        /* Image was converted */
                        response = rs_filter_response_clone(previous_response);
@@ -298,7 +300,7 @@
 }
 
 static gboolean
-convert_colorspace16(RSColorspaceTransform *colorspace_transform, RS_IMAGE16 
*input_image, RS_IMAGE16 *output_image, RSColorSpace *input_space, RSColorSpace 
*output_space)
+convert_colorspace16(RSColorspaceTransform *colorspace_transform, RS_IMAGE16 
*input_image, RS_IMAGE16 *output_image, RSColorSpace *input_space, RSColorSpace 
*output_space, GdkRectangle *_roi)
 {
        g_assert(RS_IS_IMAGE16(input_image));
        g_assert(RS_IS_IMAGE16(output_image));
@@ -309,6 +311,16 @@
        if (input_space == output_space && !colorspace_transform->has_premul)
                return FALSE;
 
+       GdkRectangle *roi = _roi;
+       if (!roi) 
+       {
+               roi = g_new(GdkRectangle, 1);
+               roi->x = 0;
+               roi->y = 0;
+               roi->width = input_image->w;
+               roi->height = input_image->h;
+       }
+
        /* A few sanity checks */
        g_assert(input_image->w == output_image->w);
        g_assert(input_image->h == output_image->h);
@@ -324,7 +336,8 @@
                rs_cmm_set_input_profile(colorspace_transform->cmm, i);
                rs_cmm_set_output_profile(colorspace_transform->cmm, o);
 
-               rs_cmm_transform16(colorspace_transform->cmm, input_image, 
output_image);
+               rs_cmm_set_roi(colorspace_transform->cmm, roi);
+               rs_cmm_transform(colorspace_transform->cmm, input_image, 
output_image, TRUE);
        }
 
        /* If we get here, we can transform using simple vector math */
@@ -458,7 +471,8 @@
                rs_cmm_set_input_profile(colorspace_transform->cmm, i);
                rs_cmm_set_output_profile(colorspace_transform->cmm, o);
 
-               rs_cmm_transform8(colorspace_transform->cmm, input_image, 
output_image);
+               rs_cmm_set_roi(colorspace_transform->cmm, roi);
+               rs_cmm_transform(colorspace_transform->cmm, input_image, 
output_image, FALSE);
        }
 
        /* If we get here, we can transform using simple vector math and a 
lookup table */

Modified: trunk/plugins/colorspace-transform/rs-cmm.c
===================================================================
--- trunk/plugins/colorspace-transform/rs-cmm.c 2011-04-25 13:01:15 UTC (rev 
4013)
+++ trunk/plugins/colorspace-transform/rs-cmm.c 2011-04-25 14:40:02 UTC (rev 
4014)
@@ -40,6 +40,7 @@
 
        cmsHTRANSFORM lcms_transform8;
        cmsHTRANSFORM lcms_transform16;
+       const GdkRectangle *roi;
 };
 
 G_DEFINE_TYPE (RSCmm, rs_cmm, G_TYPE_OBJECT)
@@ -50,6 +51,19 @@
 
 static GMutex *is_profile_gamma_22_corrected_linear_lock = NULL;
 
+typedef struct {
+       RSCmm *cmm;
+       GThread *threadid;
+       gint start_y;
+       gint end_y;
+       gint start_x;
+       gint end_x;
+       RS_IMAGE16 *input;
+       void *output;
+       gboolean sixteen16;
+} ThreadInfo;
+
+
 static void
 rs_cmm_dispose(GObject *object)
 {
@@ -81,6 +95,7 @@
 static void
 rs_cmm_init(RSCmm *cmm)
 {
+       cmm->num_threads = 1;
 }
 
 RSCmm *
@@ -90,6 +105,12 @@
 }
 
 void
+rs_cmm_set_roi(RSCmm *cmm, const GdkRectangle *roi)
+{
+       cmm->roi = roi;
+}
+
+void
 rs_cmm_set_input_profile(RSCmm *cmm, const RSIccProfile *input_profile)
 {
        g_assert(RS_IS_CMM(cmm));
@@ -129,8 +150,8 @@
        cmm->clip[B] = (gushort) 65535.0 / cmm->premul[B];
 }
 
-gboolean
-rs_cmm_transform16(RSCmm *cmm, RS_IMAGE16 *input, RS_IMAGE16 *output)
+void
+rs_cmm_transform16(RSCmm *cmm, RS_IMAGE16 *input, RS_IMAGE16 *output, gint 
start_x, gint end_x, gint start_y, gint end_y)
 {
        gushort *buffer;
        gint y, x;
@@ -138,15 +159,12 @@
        g_assert(RS_IS_IMAGE16(input));
        g_assert(RS_IS_IMAGE16(output));
 
-       g_return_val_if_fail(input->w == output->w, FALSE);
-       g_return_val_if_fail(input->h == output->h, FALSE);
-       g_return_val_if_fail(input->pixelsize == 4, FALSE);
+       g_return_if_fail(input->w == output->w);
+       g_return_if_fail(input->h == output->h);
+       g_return_if_fail(input->pixelsize == 4);
 
-       if (cmm->dirty16)
-               prepare16(cmm);
-
        buffer = g_new(gushort, input->w * 4);
-       for(y=0;y<input->h;y++)
+       for(y=start_y;y<end_y;y++)
        {
                gushort *in = GET_PIXEL(input, 0, y);
                gushort *out = GET_PIXEL(output, 0, y);
@@ -178,29 +196,94 @@
                cmsDoTransform(cmm->lcms_transform16, buffer, out, input->w);
        }
        g_free(buffer);
-       return TRUE;
 }
 
-gboolean
-rs_cmm_transform8(RSCmm *cmm, RS_IMAGE16 *input, GdkPixbuf *output)
+void
+rs_cmm_transform8(RSCmm *cmm, RS_IMAGE16 *input, GdkPixbuf *output, gint 
start_x, gint end_x, gint start_y, gint end_y)
 {
+       gint y,i;
        g_assert(RS_IS_CMM(cmm));
        g_assert(RS_IS_IMAGE16(input));
        g_assert(GDK_IS_PIXBUF(output));
 
-       g_return_val_if_fail(input->w == gdk_pixbuf_get_width(output), FALSE);
-       g_return_val_if_fail(input->h == gdk_pixbuf_get_height(output), FALSE);
-       g_return_val_if_fail(input->pixelsize == 4, FALSE);
+       g_return_if_fail(input->w == gdk_pixbuf_get_width(output));
+       g_return_if_fail(input->h == gdk_pixbuf_get_height(output));
+       g_return_if_fail(input->pixelsize == 4);
 
-       if (cmm->dirty8)
-               prepare8(cmm);
+       for(y=start_y;y<end_y;y++)
+       {
+               gushort *in = GET_PIXEL(input, 0, y);
+               guchar *out = GET_PIXBUF_PIXEL(output, 0, y);
+               cmsDoTransform(cmm->lcms_transform8, in, out, input->w);
+               /* Set alpha */
+               for (i = 0; i < input->w; i++)
+                       out[i*4+3] = 0xff;
+       }
+}
 
-       /* FIXME: Render */
-       g_warning("rs_cmm_transform8() is a stub");
+gpointer
+start_single_transform_thread(gpointer _thread_info)
+{
+       ThreadInfo* t = _thread_info;
 
-       return TRUE;
+       if (t->sixteen16)
+       {
+               rs_cmm_transform16(t->cmm, t->input, t->output, t->start_x, 
t->end_x, t->start_y, t->end_y);
+       }
+       else /* 16 -> 8 bit */
+       {
+               rs_cmm_transform8(t->cmm, t->input, t->output, t->start_x, 
t->end_x, t->start_y, t->end_y);
+       }
+       return NULL;
 }
 
+void
+rs_cmm_transform(RSCmm *cmm, RS_IMAGE16 *input, void *output, gboolean 
sixteen_to_16)
+{
+       gint i;
+       guint y_offset, y_per_thread, threaded_h;
+       gint threads = cmm->num_threads;
+       ThreadInfo *t = g_new(ThreadInfo, threads);
+
+       const GdkRectangle *roi = cmm->roi;
+       threaded_h = roi->height;
+       y_per_thread = (threaded_h + threads-1)/threads;
+       y_offset = roi->y;
+
+       if (sixteen_to_16)
+       {
+               if (cmm->dirty16)
+                       prepare16(cmm);
+       }
+       else
+       {
+               if (cmm->dirty8)
+                       prepare8(cmm);
+       }
+
+       for (i = 0; i < threads; i++)
+       {
+               t[i].cmm = cmm;
+               t[i].sixteen16 = sixteen_to_16;
+               t[i].input = input;
+               t[i].output = output;
+               t[i].start_y = y_offset;
+               t[i].start_x = roi->x;
+               t[i].end_x = roi->x + roi->width;
+               y_offset += y_per_thread;
+               y_offset = MIN(input->h, y_offset);
+               t[i].end_y = y_offset;
+
+               t[i].threadid = g_thread_create(start_single_transform_thread, 
&t[i], TRUE, NULL);
+       }
+
+       /* Wait for threads to finish */
+       for(i = 0; i < threads; i++)
+               g_thread_join(t[i].threadid);
+
+       g_free(t);
+}
+
 static guchar *
 pack_rgb_w4(void *info, register WORD wOut[], register LPBYTE output)
 {
@@ -257,6 +340,19 @@
 static void
 prepare8(RSCmm *cmm)
 {
+       if (!cmm->dirty8)
+               return;
+
+       if (cmm->lcms_transform8)
+               cmsDeleteTransform(cmm->lcms_transform8);
+
+       cmm->lcms_transform8 = cmsCreateTransform(
+               cmm->lcms_input_profile, TYPE_RGBA_16,
+               cmm->lcms_output_profile, TYPE_RGBA_8,
+               INTENT_PERCEPTUAL, 0);
+
+       g_warn_if_fail(cmm->lcms_transform8 != NULL);
+       cmm->dirty8 = FALSE;
 }
 
 static gboolean

Modified: trunk/plugins/colorspace-transform/rs-cmm.h
===================================================================
--- trunk/plugins/colorspace-transform/rs-cmm.h 2011-04-25 13:01:15 UTC (rev 
4013)
+++ trunk/plugins/colorspace-transform/rs-cmm.h 2011-04-25 14:40:02 UTC (rev 
4014)
@@ -48,12 +48,12 @@
 
 void rs_cmm_set_num_threads(RSCmm *cmm, const gint num_threads);
 
+void rs_cmm_set_roi(RSCmm *cmm, const GdkRectangle *roi);
+
 void rs_cmm_set_premul(RSCmm *cmm, const gfloat premul[3]);
 
-gboolean rs_cmm_transform16(RSCmm *cmm, RS_IMAGE16 *input, RS_IMAGE16 *output);
+void rs_cmm_transform(RSCmm *cmm, RS_IMAGE16 *input, void *output, gboolean 
sixteen_to_16);
 
-gboolean rs_cmm_transform8(RSCmm *cmm, RS_IMAGE16 *input, GdkPixbuf *output);
-
 G_END_DECLS
 
 #endif /* RS_CMM_H */


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to