diff options
author | Pixel <pixel@nobis-crew.org> | 2009-11-04 11:56:41 -0800 |
---|---|---|
committer | Pixel <pixel@nobis-crew.org> | 2009-11-04 11:59:33 -0800 |
commit | d577d991b97ae2b5ee1af23641bcffc3f83af5b2 (patch) | |
tree | 590639d50205d1bcfaff2a7d2dc6ebf3f373c7ed /im/src/im_convertcolor.cpp |
Initial import. Contains the im, cd and iup librairies, and a "working" Makefile for them under linux.
Diffstat (limited to 'im/src/im_convertcolor.cpp')
-rwxr-xr-x | im/src/im_convertcolor.cpp | 985 |
1 files changed, 985 insertions, 0 deletions
diff --git a/im/src/im_convertcolor.cpp b/im/src/im_convertcolor.cpp new file mode 100755 index 0000000..e68730f --- /dev/null +++ b/im/src/im_convertcolor.cpp @@ -0,0 +1,985 @@ +/** \file + * \brief Image Conversion + * + * See Copyright Notice in im_lib.h + * $Id: im_convertcolor.cpp,v 1.3 2009/08/18 05:13:18 scuri Exp $ + */ + +#include "im.h" +#include "im_util.h" +#include "im_complex.h" +#include "im_image.h" +#include "im_convert.h" +#include "im_color.h" +#include "im_counter.h" + +#include <stdlib.h> +#include <assert.h> +#include <memory.h> + +void imConvertMapToRGB(unsigned char* data, int count, int depth, int packed, long* palette, int palette_count) +{ + int c, i, delta; + unsigned char r[256], g[256], b[256]; + unsigned char *r_data, *g_data, *b_data; + + unsigned char* src_data = data + count-1; + if (packed) + { + r_data = data + depth*(count-1); + g_data = r_data + 1; + b_data = r_data + 2; + delta = depth; + } + else + { + r_data = data + count - 1; + g_data = data + 2*count - 1; + b_data = data + 3*count - 1; + delta = 1; + } + + for (c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (i = 0; i < count; i++) + { + int index = *src_data; + *r_data = r[index]; + *g_data = g[index]; + *b_data = b[index]; + + r_data -= delta; + g_data -= delta; + b_data -= delta; + src_data--; + } +} + +static void iConvertSetTranspMap(imbyte *src_map, imbyte *dst_alpha, int count, imbyte *transp_map, int transp_count) +{ + for(int i = 0; i < count; i++) + { + if (*src_map < transp_count) + *dst_alpha = transp_map[*src_map]; + else + *dst_alpha = 255; /* opaque */ + + src_map++; + dst_alpha++; + } +} + +static void iConvertSetTranspIndex(imbyte *src_map, imbyte *dst_alpha, int count, imbyte index) +{ + for(int i = 0; i < count; i++) + { + if (*src_map == index) + *dst_alpha = 0; /* full transparent */ + else + *dst_alpha = 255; /* opaque */ + + src_map++; + dst_alpha++; + } +} + +static void iConvertSetTranspColor(imbyte **dst_data, int count, imbyte r, imbyte g, imbyte b) +{ + imbyte *pr = dst_data[0]; + imbyte *pg = dst_data[1]; + imbyte *pb = dst_data[2]; + imbyte *pa = dst_data[3]; + + for(int i = 0; i < count; i++) + { + if (*pr == r && + *pg == g && + *pb == b) + *pa = 0; /* transparent */ + else + *pa = 255; /* opaque */ + + pr++; + pg++; + pb++; + pa++; + } +} + +// convert bin2gray and gray2bin +inline void iConvertBinary(imbyte* map, int count, imbyte value) +{ + imbyte thres = (value == 255)? 1: 128; + + // if gray2bin, check for invalid gray that already is binary + if (value != 255) + { + imbyte vmax = 0, *pmap = map; + for (int i = 0; i < count; i++) + { + if (*pmap > vmax) + vmax = *pmap; + + pmap++; + } + + if (vmax == 1) + thres = 1; + else + thres = vmax / 2; + } + + for (int i = 0; i < count; i++) + { + if (*map >= thres) + *map = value; + else + *map = 0; + + map++; + } +} + +static void iConvertMap2Gray(const imbyte* src_map, imbyte* dst_map, int count, const long* palette, const int palette_count) +{ + imbyte r, g, b; + imbyte remap[256]; + + for (int c = 0; c < palette_count; c++) + { + imColorDecode(&r, &g, &b, palette[c]); + remap[c] = imColorRGB2Luma(r, g, b); + } + + for (int i = 0; i < count; i++) + { + *dst_map++ = remap[*src_map++]; + } +} + +static void iConvertMapToRGB(const imbyte* src_map, imbyte* red, imbyte* green, imbyte* blue, int count, const long* palette, const int palette_count) +{ + imbyte r[256], g[256], b[256]; + for (int c = 0; c < palette_count; c++) + imColorDecode(&r[c], &g[c], &b[c], palette[c]); + + for (int i = 0; i < count; i++) + { + int index = *src_map++; + *red++ = r[index]; + *green++ = g[index]; + *blue++ = b[index]; + } +} + +template <class T> +int iDoConvert2Gray(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + const T* src_map3 = (src_color_space == IM_CMYK)? src_data[3]: 0; + T* dst_map = dst_data[0]; + + imCounterTotal(counter, count, "Converting To Gray..."); + + switch(src_color_space) + { + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c1 = imColorReconstruct(*src_map1++, max); // use only Y component + + // do gamma correction then scale back to 0-max + *dst_map++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_CMYK: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + T r, g, b; + // result is still 0-max + imColorCMYK2RGB(*src_map0++, *src_map1++, *src_map2++, *src_map3++, r, g, b, max); + *dst_map++ = imColorRGB2Luma(r, g, b); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + for (i = 0; i < count; i++) + { + *dst_map++ = imColorRGB2Luma(*src_map0++, *src_map1++, *src_map2++); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + float c0 = imColorReconstruct(*src_map0++, max); // scale to 0-1 + c0 = imColorLightness2Luminance(c0); // do the convertion + + // do gamma correction then scale back to 0-max + *dst_map++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvert2RGB(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max, zero; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + const T* src_map3 = (src_color_space == IM_CMYK)? src_data[3]: 0; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To RGB..."); + + switch(src_color_space) + { + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // result is still 0-1 + imColorXYZ2RGB(c0, c1, c2, + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + *dst_map0++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + *dst_map1++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + *dst_map2++ = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_YCBCR: + max = (T)imColorMax(data_type); + zero = (T)imColorZero(data_type); + for (i = 0; i < count; i++) + { + imColorYCbCr2RGB(*src_map0++, *src_map1++, *src_map2++, + *dst_map0++, *dst_map1++, *dst_map2++, zero, max); + } + break; + case IM_CMYK: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // result is still 0-max + imColorCMYK2RGB(*src_map0++, *src_map1++, *src_map2++, *src_map3++, + *dst_map0++, *dst_map1++, *dst_map2++, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + if (src_color_space == IM_LUV) + imColorLuv2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + else + imColorLab2XYZ(c0, c1, c2, // conversion in-place + c0, c1, c2); + + imColorXYZ2RGB(c0, c1, c2, // conversion in-place + c0, c1, c2, 1.0f); + + // do gamma correction then scale back to 0-max + *dst_map0++ = imColorQuantize(imColorTransfer2Nonlinear(c0), max); + *dst_map1++ = imColorQuantize(imColorTransfer2Nonlinear(c1), max); + *dst_map2++ = imColorQuantize(imColorTransfer2Nonlinear(c2), max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvert2YCbCr(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T zero; + + const T* src_map0 = src_data[0]; + const T* src_map1 = src_data[1]; + const T* src_map2 = src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To YCbCr..."); + + switch(src_color_space) + { + case IM_RGB: + zero = (T)imColorZero(data_type); + for (i = 0; i < count; i++) + { + imColorRGB2YCbCr(*src_map0++, *src_map1++, *src_map2++, + *dst_map0++, *dst_map1++, *dst_map2++, zero); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvert2XYZ(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To XYZ..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0*0.9505f, max); // Compensate D65 white point + *dst_map1++ = imColorQuantize(c0, max); + *dst_map2++ = imColorQuantize(c0*1.0890f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + // result is still 0-1 + imColorRGB2XYZ(c0, c1, c2, + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1, max); + *dst_map2++ = imColorQuantize(c2, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + if (src_color_space == IM_LUV) + imColorLuv2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + else + imColorLab2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1, max); + *dst_map2++ = imColorQuantize(c2, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvert2Lab(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To Lab..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // do conversion + c0 = imColorLuminance2Lightness(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); // update only the L component + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + imColorRGB2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LUV: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + imColorLuv2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + imColorXYZ2Lab(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvert2Luv(int count, int data_type, + const T** src_data, int src_color_space, T** dst_data, int counter) +{ + int i; + T max; + + const T* src_map0 = src_data[0]; + const T* src_map1 = (src_color_space == IM_GRAY)? 0: src_data[1]; + const T* src_map2 = (src_color_space == IM_GRAY)? 0: src_data[2]; + T* dst_map0 = dst_data[0]; + T* dst_map1 = dst_data[1]; + T* dst_map2 = dst_data[2]; + + imCounterTotal(counter, count, "Converting To Luv..."); + + switch(src_color_space) + { + case IM_GRAY: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + + // do conversion + c0 = imColorLuminance2Lightness(c0); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); // update only the L component + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_RGB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + + // scale to 0-1 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + // do gamma correction + c0 = imColorTransfer2Linear(c0); + c1 = imColorTransfer2Linear(c1); + c2 = imColorTransfer2Linear(c2); + + imColorRGB2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // then scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_XYZ: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max); + float c2 = imColorReconstruct(*src_map2++, max); + + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + case IM_LAB: + max = (T)imColorMax(data_type); + for (i = 0; i < count; i++) + { + // to increase precision do intermediate conversions in float + // scale to 0-1 and -0.5/+0.5 + float c0 = imColorReconstruct(*src_map0++, max); + float c1 = imColorReconstruct(*src_map1++, max) - 0.5f; + float c2 = imColorReconstruct(*src_map2++, max) - 0.5f; + + imColorLab2XYZ(c0, c1, c2, // convertion in-place + c0, c1, c2); + imColorXYZ2Luv(c0, c1, c2, // convertion in-place + c0, c1, c2); + + // scale back to 0-max + *dst_map0++ = imColorQuantize(c0, max); + *dst_map1++ = imColorQuantize(c1 + 0.5f, max); + *dst_map2++ = imColorQuantize(c2 + 0.5f, max); + + if (!imCounterInc(counter)) + return IM_ERR_COUNTER; + } + break; + default: + return IM_ERR_DATA; + } + + return IM_ERR_NONE; +} + +template <class T> +int iDoConvertColorSpace(int count, int data_type, + const T** src_data, int src_color_space, + T** dst_data, int dst_color_space) +{ + int ret = IM_ERR_DATA, + convert2rgb = 0; + + if ((dst_color_space == IM_XYZ || + dst_color_space == IM_LAB || + dst_color_space == IM_LUV) && + (src_color_space == IM_CMYK || + src_color_space == IM_YCBCR)) + { + convert2rgb = 1; + } + + if (dst_color_space == IM_YCBCR && src_color_space != IM_RGB) + convert2rgb = 1; + + int counter = imCounterBegin("Convert Color Space"); + + if (convert2rgb) + { + ret = iDoConvert2RGB(count, data_type, src_data, src_color_space, dst_data, counter); + + if (ret != IM_ERR_NONE) + { + imCounterEnd(counter); + return ret; + } + + src_data = (const T**)dst_data; + src_color_space = IM_RGB; + } + + switch(dst_color_space) + { + case IM_GRAY: + ret = iDoConvert2Gray(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_RGB: + ret = iDoConvert2RGB(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_YCBCR: + ret = iDoConvert2YCbCr(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_XYZ: + ret = iDoConvert2XYZ(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_LAB: + ret = iDoConvert2Lab(count, data_type, src_data, src_color_space, dst_data, counter); + break; + case IM_LUV: + ret = iDoConvert2Luv(count, data_type, src_data, src_color_space, dst_data, counter); + break; + default: + ret = IM_ERR_DATA; + break; + } + + imCounterEnd(counter); + + return ret; +} + +static int iConvertColorSpace(const imImage* src_image, imImage* dst_image) +{ + switch(src_image->data_type) + { + case IM_BYTE: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const imbyte**)src_image->data, src_image->color_space, + (imbyte**)dst_image->data, dst_image->color_space); + case IM_USHORT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const imushort**)src_image->data, src_image->color_space, + (imushort**)dst_image->data, dst_image->color_space); + case IM_INT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const int**)src_image->data, src_image->color_space, + (int**)dst_image->data, dst_image->color_space); + case IM_FLOAT: + return iDoConvertColorSpace(src_image->count, src_image->data_type, + (const float**)src_image->data, src_image->color_space, + (float**)dst_image->data, dst_image->color_space); + case IM_CFLOAT: + /* treat complex as two real values */ + return iDoConvertColorSpace(2*src_image->count, src_image->data_type, + (const float**)src_image->data, src_image->color_space, + (float**)dst_image->data, dst_image->color_space); + } + + return IM_ERR_DATA; +} + +int imConvertColorSpace(const imImage* src_image, imImage* dst_image) +{ + int ret = IM_ERR_NONE; + assert(src_image); + assert(dst_image); + + if (!imImageMatchDataType(src_image, dst_image)) + return IM_ERR_DATA; + + if (src_image->color_space != dst_image->color_space) + { + switch(dst_image->color_space) + { + case IM_RGB: + switch(src_image->color_space) + { + case IM_BINARY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 255); + memcpy(dst_image->data[1], dst_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[2], dst_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + case IM_MAP: + iConvertMapToRGB((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], (imbyte*)dst_image->data[1], (imbyte*)dst_image->data[2], dst_image->count, src_image->palette, src_image->palette_count); + ret = IM_ERR_NONE; + break; + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[1], src_image->data[0], dst_image->plane_size); + memcpy(dst_image->data[2], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + case IM_GRAY: + switch(src_image->color_space) + { + case IM_BINARY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 255); + ret = IM_ERR_NONE; + break; + case IM_MAP: + iConvertMap2Gray((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], dst_image->count, src_image->palette, src_image->palette_count); + ret = IM_ERR_NONE; + break; + case IM_YCBCR: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + case IM_MAP: + switch(src_image->color_space) + { + case IM_BINARY: // no break, same procedure as gray + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + dst_image->palette_count = src_image->palette_count; + memcpy(dst_image->palette, src_image->palette, dst_image->palette_count*sizeof(long)); + ret = IM_ERR_NONE; + break; + case IM_RGB: + dst_image->palette_count = 256; + ret = imConvertRGB2Map(src_image->width, src_image->height, + (imbyte*)src_image->data[0], (imbyte*)src_image->data[1], (imbyte*)src_image->data[2], + (imbyte*)dst_image->data[0], dst_image->palette, &dst_image->palette_count); + break; + default: + ret = IM_ERR_DATA; + break; + } + break; + case IM_BINARY: + switch(src_image->color_space) + { + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + case IM_MAP: // convert to gray, then convert to binary + iConvertMap2Gray((imbyte*)src_image->data[0], (imbyte*)dst_image->data[0], dst_image->count, src_image->palette, src_image->palette_count); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + case IM_YCBCR: // convert to gray, then convert to binary + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + default: // convert to gray, then convert to binary + dst_image->color_space = IM_GRAY; + ret = iConvertColorSpace(src_image, dst_image); + dst_image->color_space = IM_BINARY; + if (ret == IM_ERR_NONE) + iConvertBinary((imbyte*)dst_image->data[0], dst_image->count, 1); + ret = IM_ERR_NONE; + break; + } + break; + case IM_YCBCR: + switch(src_image->color_space) + { + case IM_GRAY: + memcpy(dst_image->data[0], src_image->data[0], dst_image->plane_size); + ret = IM_ERR_NONE; + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + break; + default: + ret = iConvertColorSpace(src_image, dst_image); + break; + } + } + + if (src_image->has_alpha && dst_image->has_alpha) + memcpy(dst_image->data[dst_image->depth], src_image->data[src_image->depth], src_image->plane_size); + else if (dst_image->color_space == IM_RGB && dst_image->data_type == IM_BYTE && dst_image->has_alpha) + { + if (src_image->color_space == IM_RGB) + { + imbyte* transp_color = (imbyte*)imImageGetAttribute(src_image, "TransparencyColor", NULL, NULL); + if (transp_color) + iConvertSetTranspColor((imbyte**)dst_image->data, dst_image->count, *(transp_color+0), *(transp_color+1), *(transp_color+2)); + else + memset(dst_image->data[3], 255, dst_image->count); + } + else + { + int transp_count; + imbyte* transp_index = (imbyte*)imImageGetAttribute(src_image, "TransparencyIndex", NULL, NULL); + imbyte* transp_map = (imbyte*)imImageGetAttribute(src_image, "TransparencyMap", NULL, &transp_count); + if (transp_map) + iConvertSetTranspMap((imbyte*)src_image->data[0], (imbyte*)dst_image->data[3], dst_image->count, transp_map, transp_count); + else if (transp_index) + iConvertSetTranspIndex((imbyte*)src_image->data[0], (imbyte*)dst_image->data[3], dst_image->count, *transp_index); + else + memset(dst_image->data[3], 255, dst_image->count); + } + } + + return ret; +} + |