Bug 791422. Support more flexibiltiy qcms output format. r=BenWa
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Wed, 03 Oct 2012 19:04:25 -0400
changeset 109275 bd16a5d51273ef974bd40eba689e0cd1e60a300c
parent 109274 6967936b81eeda54d974a7438f55b85103624e5f
child 109276 972c376d08b537e30f8495ee420800cb1f3fe520
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersBenWa
bugs791422
milestone18.0a1
Bug 791422. Support more flexibiltiy qcms output format. r=BenWa This will help support Chrome and should also let us output directly to a cairo compatible format.
gfx/qcms/qcmsint.h
gfx/qcms/transform-sse1.c
gfx/qcms/transform-sse2.c
gfx/qcms/transform.c
--- a/gfx/qcms/qcmsint.h
+++ b/gfx/qcms/qcmsint.h
@@ -269,8 +269,31 @@ void qcms_transform_data_rgb_out_lut_sse
                                           unsigned char *dest,
                                           size_t length);
 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
                                           unsigned char *src,
                                           unsigned char *dest,
                                           size_t length);
 
 extern qcms_bool qcms_supports_iccv4;
+
+#ifdef NATIVE_OUTPUT
+# define RGB_OUTPUT_COMPONENTS 4
+# define RGBA_OUTPUT_COMPONENTS 4
+# ifdef IS_LITTLE_ENDIAN
+#  define OUTPUT_INDEX_A 3
+#  define OUTPUT_INDEX_R 2
+#  define OUTPUT_INDEX_G 1
+#  define OUTPUT_INDEX_B 0
+# else
+#  define OUTPUT_INDEX_A 0
+#  define OUTPUT_INDEX_R 1
+#  define OUTPUT_INDEX_G 2
+#  define OUTPUT_INDEX_B 3
+# endif
+#else
+# define RGB_OUTPUT_COMPONENTS 3
+# define RGBA_OUTPUT_COMPONENTS 4
+# define OUTPUT_R_INDEX 0
+# define OUTPUT_G_INDEX 1
+# define OUTPUT_B_INDEX 2
+# define OUTPUT_A_INDEX 3
+#endif
--- a/gfx/qcms/transform-sse1.c
+++ b/gfx/qcms/transform-sse1.c
@@ -90,20 +90,20 @@ void qcms_transform_data_rgb_out_lut_sse
 
         /* load for next loop while store completes */
         vec_r = _mm_load_ss(&igtbl_r[src[0]]);
         vec_g = _mm_load_ss(&igtbl_g[src[1]]);
         vec_b = _mm_load_ss(&igtbl_b[src[2]]);
         src += 3;
 
         /* use calc'd indices to output RGB values */
-        dest[0] = otdata_r[output[0]];
-        dest[1] = otdata_g[output[1]];
-        dest[2] = otdata_b[output[2]];
-        dest += 3;
+        dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+        dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+        dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
+        dest += RGB_OUTPUT_COMPONENTS;
     }
 
     /* handle final (maybe only) pixel */
 
     vec_r = _mm_shuffle_ps(vec_r, vec_r, 0);
     vec_g = _mm_shuffle_ps(vec_g, vec_g, 0);
     vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
@@ -115,19 +115,19 @@ void qcms_transform_data_rgb_out_lut_sse
     vec_r  = _mm_max_ps(min, vec_r);
     vec_r  = _mm_min_ps(max, vec_r);
     result = _mm_mul_ps(vec_r, scale);
 
     *((__m64 *)&output[0]) = _mm_cvtps_pi32(result);
     result = _mm_movehl_ps(result, result);
     *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
 
-    dest[0] = otdata_r[output[0]];
-    dest[1] = otdata_g[output[1]];
-    dest[2] = otdata_b[output[2]];
+    dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+    dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+    dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
 
     _mm_empty();
 }
 
 void qcms_transform_data_rgba_out_lut_sse1(qcms_transform *transform,
                                            unsigned char *src,
                                            unsigned char *dest,
                                            size_t length)
@@ -192,17 +192,17 @@ void qcms_transform_data_rgba_out_lut_ss
         vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
         /* gamma * matrix */
         vec_r = _mm_mul_ps(vec_r, mat0);
         vec_g = _mm_mul_ps(vec_g, mat1);
         vec_b = _mm_mul_ps(vec_b, mat2);
 
         /* store alpha for this pixel; load alpha for next */
-        dest[3] = alpha;
+        dest[OUTPUT_A_INDEX] = alpha;
         alpha   = src[3];
 
         /* crunch, crunch, crunch */
         vec_r  = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b));
         vec_r  = _mm_max_ps(min, vec_r);
         vec_r  = _mm_min_ps(max, vec_r);
         result = _mm_mul_ps(vec_r, scale);
 
@@ -213,41 +213,41 @@ void qcms_transform_data_rgba_out_lut_ss
 
         /* load gamma values for next loop while store completes */
         vec_r = _mm_load_ss(&igtbl_r[src[0]]);
         vec_g = _mm_load_ss(&igtbl_g[src[1]]);
         vec_b = _mm_load_ss(&igtbl_b[src[2]]);
         src += 4;
 
         /* use calc'd indices to output RGB values */
-        dest[0] = otdata_r[output[0]];
-        dest[1] = otdata_g[output[1]];
-        dest[2] = otdata_b[output[2]];
+        dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+        dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+        dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
         dest += 4;
     }
 
     /* handle final (maybe only) pixel */
 
     vec_r = _mm_shuffle_ps(vec_r, vec_r, 0);
     vec_g = _mm_shuffle_ps(vec_g, vec_g, 0);
     vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
     vec_r = _mm_mul_ps(vec_r, mat0);
     vec_g = _mm_mul_ps(vec_g, mat1);
     vec_b = _mm_mul_ps(vec_b, mat2);
 
-    dest[3] = alpha;
+    dest[OUTPUT_A_INDEX] = alpha;
 
     vec_r  = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b));
     vec_r  = _mm_max_ps(min, vec_r);
     vec_r  = _mm_min_ps(max, vec_r);
     result = _mm_mul_ps(vec_r, scale);
 
     *((__m64 *)&output[0]) = _mm_cvtps_pi32(result);
     result = _mm_movehl_ps(result, result);
     *((__m64 *)&output[2]) = _mm_cvtps_pi32(result);
 
-    dest[0] = otdata_r[output[0]];
-    dest[1] = otdata_g[output[1]];
-    dest[2] = otdata_b[output[2]];
+    dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+    dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+    dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
 
     _mm_empty();
 }
--- a/gfx/qcms/transform-sse2.c
+++ b/gfx/qcms/transform-sse2.c
@@ -88,20 +88,20 @@ void qcms_transform_data_rgb_out_lut_sse
 
         /* load for next loop while store completes */
         vec_r = _mm_load_ss(&igtbl_r[src[0]]);
         vec_g = _mm_load_ss(&igtbl_g[src[1]]);
         vec_b = _mm_load_ss(&igtbl_b[src[2]]);
         src += 3;
 
         /* use calc'd indices to output RGB values */
-        dest[0] = otdata_r[output[0]];
-        dest[1] = otdata_g[output[1]];
-        dest[2] = otdata_b[output[2]];
-        dest += 3;
+        dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+        dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+        dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
+        dest += RGB_OUTPUT_COMPONENTS;
     }
 
     /* handle final (maybe only) pixel */
 
     vec_r = _mm_shuffle_ps(vec_r, vec_r, 0);
     vec_g = _mm_shuffle_ps(vec_g, vec_g, 0);
     vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
@@ -111,19 +111,19 @@ void qcms_transform_data_rgb_out_lut_sse
 
     vec_r  = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b));
     vec_r  = _mm_max_ps(min, vec_r);
     vec_r  = _mm_min_ps(max, vec_r);
     result = _mm_mul_ps(vec_r, scale);
 
     _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
 
-    dest[0] = otdata_r[output[0]];
-    dest[1] = otdata_g[output[1]];
-    dest[2] = otdata_b[output[2]];
+    dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+    dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+    dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
 }
 
 void qcms_transform_data_rgba_out_lut_sse2(qcms_transform *transform,
                                            unsigned char *src,
                                            unsigned char *dest,
                                            size_t length)
 {
     unsigned int i;
@@ -186,17 +186,17 @@ void qcms_transform_data_rgba_out_lut_ss
         vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
         /* gamma * matrix */
         vec_r = _mm_mul_ps(vec_r, mat0);
         vec_g = _mm_mul_ps(vec_g, mat1);
         vec_b = _mm_mul_ps(vec_b, mat2);
 
         /* store alpha for this pixel; load alpha for next */
-        dest[3] = alpha;
+        dest[OUTPUT_A_INDEX] = alpha;
         alpha   = src[3];
 
         /* crunch, crunch, crunch */
         vec_r  = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b));
         vec_r  = _mm_max_ps(min, vec_r);
         vec_r  = _mm_min_ps(max, vec_r);
         result = _mm_mul_ps(vec_r, scale);
 
@@ -205,39 +205,39 @@ void qcms_transform_data_rgba_out_lut_ss
 
         /* load gamma values for next loop while store completes */
         vec_r = _mm_load_ss(&igtbl_r[src[0]]);
         vec_g = _mm_load_ss(&igtbl_g[src[1]]);
         vec_b = _mm_load_ss(&igtbl_b[src[2]]);
         src += 4;
 
         /* use calc'd indices to output RGB values */
-        dest[0] = otdata_r[output[0]];
-        dest[1] = otdata_g[output[1]];
-        dest[2] = otdata_b[output[2]];
-        dest += 4;
+        dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+        dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+        dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
+        dest += RGBA_OUTPUT_COMPONENTS;
     }
 
     /* handle final (maybe only) pixel */
 
     vec_r = _mm_shuffle_ps(vec_r, vec_r, 0);
     vec_g = _mm_shuffle_ps(vec_g, vec_g, 0);
     vec_b = _mm_shuffle_ps(vec_b, vec_b, 0);
 
     vec_r = _mm_mul_ps(vec_r, mat0);
     vec_g = _mm_mul_ps(vec_g, mat1);
     vec_b = _mm_mul_ps(vec_b, mat2);
 
-    dest[3] = alpha;
+    dest[OUTPUT_A_INDEX] = alpha;
 
     vec_r  = _mm_add_ps(vec_r, _mm_add_ps(vec_g, vec_b));
     vec_r  = _mm_max_ps(min, vec_r);
     vec_r  = _mm_min_ps(max, vec_r);
     result = _mm_mul_ps(vec_r, scale);
 
     _mm_store_si128((__m128i*)output, _mm_cvtps_epi32(result));
 
-    dest[0] = otdata_r[output[0]];
-    dest[1] = otdata_g[output[1]];
-    dest[2] = otdata_b[output[2]];
+    dest[OUTPUT_R_INDEX] = otdata_r[output[0]];
+    dest[OUTPUT_G_INDEX] = otdata_g[output[1]];
+    dest[OUTPUT_B_INDEX] = otdata_b[output[2]];
 }
 
 
--- a/gfx/qcms/transform.c
+++ b/gfx/qcms/transform.c
@@ -246,19 +246,20 @@ static void qcms_transform_data_rgb_out_
 		float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + mat[2][0]*linear_b;
 		float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + mat[2][1]*linear_b;
 		float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + mat[2][2]*linear_b;
 
 		float out_device_r = pow(out_linear_r, transform->out_gamma_r);
 		float out_device_g = pow(out_linear_g, transform->out_gamma_g);
 		float out_device_b = pow(out_linear_b, transform->out_gamma_b);
 
-		*dest++ = clamp_u8(255*out_device_r);
-		*dest++ = clamp_u8(255*out_device_g);
-		*dest++ = clamp_u8(255*out_device_b);
+		dest[OUTPUT_R_INDEX] = clamp_u8(255*out_device_r);
+		dest[OUTPUT_G_INDEX] = clamp_u8(255*out_device_g);
+		dest[OUTPUT_B_INDEX] = clamp_u8(255*out_device_b);
+		dest += RGB_OUTPUT_COMPONENTS;
 	}
 }
 #endif
 
 static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	for (i = 0; i < length; i++) {
@@ -266,19 +267,20 @@ static void qcms_transform_data_gray_out
 		unsigned char device = *src++;
 
 		float linear = transform->input_gamma_table_gray[device];
 
                 out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
 		out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
 		out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
 
-		*dest++ = clamp_u8(out_device_r*255);
-		*dest++ = clamp_u8(out_device_g*255);
-		*dest++ = clamp_u8(out_device_b*255);
+		dest[OUTPUT_R_INDEX] = clamp_u8(out_device_r*255);
+		dest[OUTPUT_G_INDEX] = clamp_u8(out_device_g*255);
+		dest[OUTPUT_B_INDEX] = clamp_u8(out_device_b*255);
+		dest += RGB_OUTPUT_COMPONENTS;
 	}
 }
 
 /* Alpha is not corrected.
    A rationale for this is found in Alvy Ray's "Should Alpha Be Nonlinear If
    RGB Is?" Tech Memo 17 (December 14, 1998).
 	See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf
 */
@@ -292,59 +294,62 @@ static void qcms_transform_data_graya_ou
 		unsigned char alpha = *src++;
 
 		float linear = transform->input_gamma_table_gray[device];
 
                 out_device_r = lut_interp_linear(linear, transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
 		out_device_g = lut_interp_linear(linear, transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
 		out_device_b = lut_interp_linear(linear, transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
 
-		*dest++ = clamp_u8(out_device_r*255);
-		*dest++ = clamp_u8(out_device_g*255);
-		*dest++ = clamp_u8(out_device_b*255);
-		*dest++ = alpha;
+		dest[OUTPUT_R_INDEX] = clamp_u8(out_device_r*255);
+		dest[OUTPUT_G_INDEX] = clamp_u8(out_device_g*255);
+		dest[OUTPUT_B_INDEX] = clamp_u8(out_device_b*255);
+		dest[OUTPUT_A_INDEX] = alpha;
+		dest += RGBA_OUTPUT_COMPONENTS;
 	}
 }
 
 
 static void qcms_transform_data_gray_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	for (i = 0; i < length; i++) {
 		unsigned char device = *src++;
 		uint16_t gray;
 
 		float linear = transform->input_gamma_table_gray[device];
 
 		/* we could round here... */
 		gray = linear * PRECACHE_OUTPUT_MAX;
 
-		*dest++ = transform->output_table_r->data[gray];
-		*dest++ = transform->output_table_g->data[gray];
-		*dest++ = transform->output_table_b->data[gray];
+		dest[OUTPUT_R_INDEX] = transform->output_table_r->data[gray];
+		dest[OUTPUT_G_INDEX] = transform->output_table_g->data[gray];
+		dest[OUTPUT_B_INDEX] = transform->output_table_b->data[gray];
+		dest += RGB_OUTPUT_COMPONENTS;
 	}
 }
 
 static void qcms_transform_data_graya_out_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	for (i = 0; i < length; i++) {
 		unsigned char device = *src++;
 		unsigned char alpha = *src++;
 		uint16_t gray;
 
 		float linear = transform->input_gamma_table_gray[device];
 
 		/* we could round here... */
 		gray = linear * PRECACHE_OUTPUT_MAX;
 
-		*dest++ = transform->output_table_r->data[gray];
-		*dest++ = transform->output_table_g->data[gray];
-		*dest++ = transform->output_table_b->data[gray];
-		*dest++ = alpha;
+		dest[OUTPUT_R_INDEX] = transform->output_table_r->data[gray];
+		dest[OUTPUT_G_INDEX] = transform->output_table_g->data[gray];
+		dest[OUTPUT_B_INDEX] = transform->output_table_b->data[gray];
+		dest[OUTPUT_A_INDEX] = alpha;
+		dest += RGBA_OUTPUT_COMPONENTS;
 	}
 }
 
 static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
@@ -365,19 +370,20 @@ static void qcms_transform_data_rgb_out_
 		out_linear_g = clamp_float(out_linear_g);
 		out_linear_b = clamp_float(out_linear_b);
 
 		/* we could round here... */
 		r = out_linear_r * PRECACHE_OUTPUT_MAX;
 		g = out_linear_g * PRECACHE_OUTPUT_MAX;
 		b = out_linear_b * PRECACHE_OUTPUT_MAX;
 
-		*dest++ = transform->output_table_r->data[r];
-		*dest++ = transform->output_table_g->data[g];
-		*dest++ = transform->output_table_b->data[b];
+		dest[OUTPUT_R_INDEX] = transform->output_table_r->data[r];
+		dest[OUTPUT_G_INDEX] = transform->output_table_g->data[g];
+		dest[OUTPUT_A_INDEX] = transform->output_table_b->data[b];
+		dest += RGB_OUTPUT_COMPONENTS;
 	}
 }
 
 static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
@@ -399,20 +405,21 @@ static void qcms_transform_data_rgba_out
 		out_linear_g = clamp_float(out_linear_g);
 		out_linear_b = clamp_float(out_linear_b);
 
 		/* we could round here... */
 		r = out_linear_r * PRECACHE_OUTPUT_MAX;
 		g = out_linear_g * PRECACHE_OUTPUT_MAX;
 		b = out_linear_b * PRECACHE_OUTPUT_MAX;
 
-		*dest++ = transform->output_table_r->data[r];
-		*dest++ = transform->output_table_g->data[g];
-		*dest++ = transform->output_table_b->data[b];
-		*dest++ = alpha;
+		dest[OUTPUT_R_INDEX] = transform->output_table_r->data[r];
+		dest[OUTPUT_G_INDEX] = transform->output_table_g->data[g];
+		dest[OUTPUT_B_INDEX] = transform->output_table_b->data[b];
+		dest[OUTPUT_A_INDEX] = alpha;
+		dest += RGBA_OUTPUT_COMPONENTS;
 	}
 }
 
 // Not used
 /* 
 static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
 	unsigned int i;
 	int xy_len = 1;
@@ -572,20 +579,21 @@ static void qcms_transform_data_tetra_cl
 				}
 			}
 		}
 				
 		clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz;
 		clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
 		clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
 
-		*dest++ = clamp_u8(clut_r*255.0f);
-		*dest++ = clamp_u8(clut_g*255.0f);
-		*dest++ = clamp_u8(clut_b*255.0f);
-		*dest++ = in_a;
+		dest[OUTPUT_R_INDEX] = clamp_u8(clut_r*255.0f);
+		dest[OUTPUT_G_INDEX] = clamp_u8(clut_g*255.0f);
+		dest[OUTPUT_B_INDEX] = clamp_u8(clut_b*255.0f);
+		dest[OUTPUT_A_INDEX] = in_a;
+		dest += RGBA_OUTPUT_COMPONENTS;
 	}	
 }
 
 // Using lcms' tetra interpolation code.
 static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length) {
 	unsigned int i;
 	int xy_len = 1;
 	int x_len = transform->grid_size;
@@ -686,19 +694,20 @@ static void qcms_transform_data_tetra_cl
 				}
 			}
 		}
 				
 		clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz;
 		clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz;
 		clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz;
 
-		*dest++ = clamp_u8(clut_r*255.0f);
-		*dest++ = clamp_u8(clut_g*255.0f);
-		*dest++ = clamp_u8(clut_b*255.0f);
+		dest[OUTPUT_R_INDEX] = clamp_u8(clut_r*255.0f);
+		dest[OUTPUT_G_INDEX] = clamp_u8(clut_g*255.0f);
+		dest[OUTPUT_B_INDEX] = clamp_u8(clut_b*255.0f);
+		dest += RGB_OUTPUT_COMPONENTS;
 	}	
 }
 
 static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
@@ -721,19 +730,20 @@ static void qcms_transform_data_rgb_out_
 
 		out_device_r = lut_interp_linear(out_linear_r, 
 				transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
 		out_device_g = lut_interp_linear(out_linear_g, 
 				transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
 		out_device_b = lut_interp_linear(out_linear_b, 
 				transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
 
-		*dest++ = clamp_u8(out_device_r*255);
-		*dest++ = clamp_u8(out_device_g*255);
-		*dest++ = clamp_u8(out_device_b*255);
+		dest[OUTPUT_R_INDEX] = clamp_u8(out_device_r*255);
+		dest[OUTPUT_G_INDEX] = clamp_u8(out_device_g*255);
+		dest[OUTPUT_B_INDEX] = clamp_u8(out_device_b*255);
+		dest += RGB_OUTPUT_COMPONENTS;
 	}
 }
 
 static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	unsigned int i;
 	float (*mat)[4] = transform->matrix;
 	for (i = 0; i < length; i++) {
@@ -757,20 +767,21 @@ static void qcms_transform_data_rgba_out
 
 		out_device_r = lut_interp_linear(out_linear_r, 
 				transform->output_gamma_lut_r, transform->output_gamma_lut_r_length);
 		out_device_g = lut_interp_linear(out_linear_g, 
 				transform->output_gamma_lut_g, transform->output_gamma_lut_g_length);
 		out_device_b = lut_interp_linear(out_linear_b, 
 				transform->output_gamma_lut_b, transform->output_gamma_lut_b_length);
 
-		*dest++ = clamp_u8(out_device_r*255);
-		*dest++ = clamp_u8(out_device_g*255);
-		*dest++ = clamp_u8(out_device_b*255);
-		*dest++ = alpha;
+		dest[OUTPUT_R_INDEX] = clamp_u8(out_device_r*255);
+		dest[OUTPUT_G_INDEX] = clamp_u8(out_device_g*255);
+		dest[OUTPUT_B_INDEX] = clamp_u8(out_device_b*255);
+		dest[OUTPUT_A_INDEX] = alpha;
+		dest += RGBA_OUTPUT_COMPONENTS;
 	}
 }
 
 #if 0
 static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsigned char *src, unsigned char *dest, size_t length)
 {
 	int i;
 	float (*mat)[4] = transform->matrix;