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