/* Copyright (C) 2001-2009 Artifex Software, Inc. All Rights Reserved. This software is provided AS-IS with no warranty, either express or implied. This software is distributed under license and may not be copied, modified or distributed except as expressly authorized under the terms of that license. Refer to licensing information at http://www.artifex.com/ or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. */ /* Simple operators and place holding support for doing conversions on buffers of data. These functions perform device (non CIE or ICC color conversions) on buffers of data. Eventually these will be replaced with functions for using the ICC based linked mappings with the external CMS. This is far from efficient at this point, but gets the job done */ #include "string_.h" #include "stdpre.h" #include "gstypes.h" #include "gsmemory.h" #include "gxblend.h" #include "gscolorbuffer.h" #define float_color_to_byte_color(float_color) ( \ (0.0 < (float_color) && (float_color) < 1.0) ? \ ((unsigned char) ((float_color) * 255.0)) : \ (((float_color) <= 0.0) ? 0x00 : 0xFF) \ ) /* We could use the conversions that are defined in gxdcconv.c, however for now we will use something even easier. This is temporary until we get the proper ICC flows in place */ static void rgb_to_cmyk(byte rgb[],byte cmyk[]) { /* Real sleazy min black generation */ cmyk[0] = 255 - rgb[0]; cmyk[1] = 255 - rgb[1]; cmyk[2] = 255 - rgb[2]; cmyk[3] = (cmyk[0] < cmyk[1]) ? min(cmyk[0], cmyk[2]) : min(cmyk[1], cmyk[2]); } static void rgb_to_gray(byte rgb[], byte gray[]) { float temp_value; /* compute a luminance component */ temp_value = rgb[0]*0.3 + rgb[1]*0.59 + rgb[2]*0.11; temp_value = temp_value * (1.0 / 255.0 ); /* May need to be optimized */ gray[0] = float_color_to_byte_color(temp_value); } static void cmyk_to_rgb(byte cmyk[], byte rgb[]) { /* real ugly, but temporary */ rgb[0] = 255 - min(cmyk[0] + cmyk[3],255); rgb[1] = 255 - min(cmyk[1] + cmyk[3],255); rgb[2] = 255 - min(cmyk[2] + cmyk[3],255); } static void cmyk_to_gray(byte cmyk[], byte gray[]) { float temp_value; temp_value = ((255 - cmyk[0])*0.3 + (255 - cmyk[1])*0.59 + (255 - cmyk[2]) * 0.11) * (255 - cmyk[3]); temp_value = temp_value * (1.0 / 65025.0 ); gray[0] = float_color_to_byte_color(temp_value); } static void gray_to_cmyk(byte gray[], byte cmyk[]) { /* Just do black. */ cmyk[0] = 0; cmyk[1] = 0; cmyk[2] = 0; cmyk[3] = 255 - gray[0]; } static void gray_to_rgb(byte gray[], byte rgb[]) { rgb[0] = gray[0]; rgb[1] = gray[0]; rgb[2] = gray[0]; } void gs_transform_color_buffer_generic(byte *inputbuffer, int row_stride, int plane_stride, int input_num_color, gs_int_rect rect, byte *outputbuffer, int output_num_color, int num_noncolor_planes) { int num_rows, num_cols, x, y, z; void (* color_remap)(byte input[],byte output[]) = NULL; byte input_vector[4],output_vector[4]; int plane_offset[PDF14_MAX_PLANES],alpha_offset_in,max_num_channels; num_rows = rect.q.y - rect.p.y; num_cols = rect.q.x - rect.p.x; /* Check for spot + cmyk case */ if (output_num_color > 4) { /* To CMYK always */ switch (input_num_color) { case 1: color_remap = gray_to_cmyk; break; case 3: color_remap = rgb_to_cmyk; break; case 4: color_remap = NULL; /* Copy data */ break; default: /* Should never be here. Groups must be gray, rgb or CMYK. Exception may be ICC with XPS */ break; } } else { /* Pick the mapping to use */ switch (input_num_color) { case 1: if (output_num_color == 3) color_remap = gray_to_rgb; else color_remap = gray_to_cmyk; break; case 3: if (output_num_color == 1) color_remap = rgb_to_gray; else color_remap = rgb_to_cmyk; break; case 4: if (output_num_color == 1) color_remap = cmyk_to_gray; else color_remap = cmyk_to_rgb; break; default: /* Should never be here. Groups must be gray, rgb or CMYK. Until we have ICC working here with XPS */ break; } } /* data is planar */ max_num_channels = max(input_num_color, output_num_color) + num_noncolor_planes; for (z = 0; z < max_num_channels; z++) plane_offset[z] = z * plane_stride; if (color_remap == NULL) { /* Blending group was CMYK, output is CMYK + spot */ memcpy(outputbuffer, inputbuffer, 4*plane_stride); /* Add any data that are beyond the standard color data (e.g. alpha) */ if (num_noncolor_planes > 0) memcpy(&(outputbuffer[plane_offset[output_num_color]]), &(inputbuffer[plane_offset[input_num_color]]), num_noncolor_planes*plane_stride); } else { /* Have to remap */ alpha_offset_in = input_num_color*plane_stride; for (y = 0; y < num_rows; y++) { for (x = 0; x < num_cols; x++) { /* If the source alpha is transparent, then move on */ if (inputbuffer[x + alpha_offset_in] != 0x00) { /* grab the input */ for (z = 0; z