+static int are_comps_same_dimensions(opj_image_t * image)
+{
+ unsigned int i;
+ for (i = 1; i < image->numcomps; i++) {
+ if (image->comps[0].dx != image->comps[i].dx ||
+ image->comps[0].dy != image->comps[i].dy) {
+ return OPJ_FALSE;
+ }
+ }
+ return OPJ_TRUE;
+}
+
+void color_cielab_to_rgb(opj_image_t *image)
+{
+ int *row;
+ int enumcs, numcomps;
+ OPJ_COLOR_SPACE new_space;
+
+ numcomps = (int)image->numcomps;
+
+ if (numcomps != 3) {
+ fprintf(stderr, "%s:%d:\n\tnumcomps %d not handled. Quitting.\n",
+ __FILE__, __LINE__, numcomps);
+ return;
+ }
+ if (!are_comps_same_dimensions(image)) {
+ fprintf(stderr,
+ "%s:%d:\n\tcomponents are not all of the same dimension. Quitting.\n",
+ __FILE__, __LINE__);
+ return;
+ }
+
+ row = (int*)image->icc_profile_buf;
+ enumcs = row[0];
+
+ if (enumcs == 14) { /* CIELab */
+ int *L, *a, *b, *red, *green, *blue;
+ int *src0, *src1, *src2, *dst0, *dst1, *dst2;
+ double rl, ol, ra, oa, rb, ob, prec0, prec1, prec2;
+ double minL, maxL, mina, maxa, minb, maxb;
+ unsigned int default_type;
+ unsigned int i, max;
+ cmsHPROFILE in, out;
+ cmsHTRANSFORM transform;
+ cmsUInt16Number RGB[3];
+ cmsCIELab Lab;
+
+ in = cmsCreateLab4Profile(NULL);
+ if (in == NULL) {
+ return;
+ }
+ out = cmsCreate_sRGBProfile();
+ if (out == NULL) {
+ cmsCloseProfile(in);
+ return;
+ }
+ transform = cmsCreateTransform(in, TYPE_Lab_DBL, out, TYPE_RGB_16,
+ INTENT_PERCEPTUAL, 0);
+
+#ifdef OPJ_HAVE_LIBLCMS2
+ cmsCloseProfile(in);
+ cmsCloseProfile(out);
+#endif
+ if (transform == NULL) {
+#ifdef OPJ_HAVE_LIBLCMS1
+ cmsCloseProfile(in);
+ cmsCloseProfile(out);
+#endif
+ return;
+ }
+ new_space = OPJ_CLRSPC_SRGB;
+
+ prec0 = (double)image->comps[0].prec;
+ prec1 = (double)image->comps[1].prec;
+ prec2 = (double)image->comps[2].prec;
+
+ default_type = (unsigned int)row[1];
+
+ if (default_type == 0x44454600) { /* DEF : default */
+ rl = 100;
+ ra = 170;
+ rb = 200;
+ ol = 0;
+ oa = pow(2, prec1 - 1);
+ ob = pow(2, prec2 - 2) + pow(2, prec2 - 3);
+ } else {
+ rl = row[2];
+ ra = row[4];
+ rb = row[6];
+ ol = row[3];
+ oa = row[5];
+ ob = row[7];
+ }
+
+ L = src0 = image->comps[0].data;
+ a = src1 = image->comps[1].data;
+ b = src2 = image->comps[2].data;
+
+ max = image->comps[0].w * image->comps[0].h;
+
+ red = dst0 = (int*)opj_image_data_alloc(max * sizeof(int));
+ green = dst1 = (int*)opj_image_data_alloc(max * sizeof(int));
+ blue = dst2 = (int*)opj_image_data_alloc(max * sizeof(int));
+
+ if (red == NULL || green == NULL || blue == NULL) {
+ goto fails;
+ }
+
+ minL = -(rl * ol) / (pow(2, prec0) - 1);
+ maxL = minL + rl;
+
+ mina = -(ra * oa) / (pow(2, prec1) - 1);
+ maxa = mina + ra;
+
+ minb = -(rb * ob) / (pow(2, prec2) - 1);
+ maxb = minb + rb;
+
+ for (i = 0; i < max; ++i) {
+ Lab.L = minL + (double)(*L) * (maxL - minL) / (pow(2, prec0) - 1);
+ ++L;
+ Lab.a = mina + (double)(*a) * (maxa - mina) / (pow(2, prec1) - 1);
+ ++a;
+ Lab.b = minb + (double)(*b) * (maxb - minb) / (pow(2, prec2) - 1);
+ ++b;
+
+ cmsDoTransform(transform, &Lab, RGB, 1);
+
+ *red++ = RGB[0];
+ *green++ = RGB[1];
+ *blue++ = RGB[2];
+ }
+ cmsDeleteTransform(transform);
+#ifdef OPJ_HAVE_LIBLCMS1
+ cmsCloseProfile(in);
+ cmsCloseProfile(out);
+#endif
+ opj_image_data_free(src0);
+ image->comps[0].data = dst0;
+ opj_image_data_free(src1);
+ image->comps[1].data = dst1;
+ opj_image_data_free(src2);
+ image->comps[2].data = dst2;
+
+ image->color_space = new_space;
+ image->comps[0].prec = 16;
+ image->comps[1].prec = 16;
+ image->comps[2].prec = 16;
+
+ return;
+
+fails:
+ cmsDeleteTransform(transform);
+#ifdef OPJ_HAVE_LIBLCMS1
+ cmsCloseProfile(in);
+ cmsCloseProfile(out);
+#endif
+ if (red) {
+ opj_image_data_free(red);
+ }
+ if (green) {
+ opj_image_data_free(green);
+ }
+ if (blue) {
+ opj_image_data_free(blue);
+ }
+ return;
+ }
+
+ fprintf(stderr, "%s:%d:\n\tenumCS %d not handled. Ignoring.\n", __FILE__,
+ __LINE__, enumcs);
+}/* color_cielab_to_rgb() */
+
+#endif /* OPJ_HAVE_LIBLCMS2 || OPJ_HAVE_LIBLCMS1 */
+
+void color_cmyk_to_rgb(opj_image_t *image)
+{
+ float C, M, Y, K;
+ float sC, sM, sY, sK;
+ unsigned int w, h, max, i;
+
+ w = image->comps[0].w;
+ h = image->comps[0].h;
+
+ if (
+ (image->numcomps < 4)
+ || (image->comps[0].dx != image->comps[1].dx) ||
+ (image->comps[0].dx != image->comps[2].dx) ||
+ (image->comps[0].dx != image->comps[3].dx)
+ || (image->comps[0].dy != image->comps[1].dy) ||
+ (image->comps[0].dy != image->comps[2].dy) ||
+ (image->comps[0].dy != image->comps[3].dy)
+ ) {
+ fprintf(stderr, "%s:%d:color_cmyk_to_rgb\n\tCAN NOT CONVERT\n", __FILE__,
+ __LINE__);
+ return;
+ }
+
+ max = w * h;
+
+ sC = 1.0F / (float)((1 << image->comps[0].prec) - 1);
+ sM = 1.0F / (float)((1 << image->comps[1].prec) - 1);
+ sY = 1.0F / (float)((1 << image->comps[2].prec) - 1);
+ sK = 1.0F / (float)((1 << image->comps[3].prec) - 1);
+
+ for (i = 0; i < max; ++i) {
+ /* CMYK values from 0 to 1 */
+ C = (float)(image->comps[0].data[i]) * sC;
+ M = (float)(image->comps[1].data[i]) * sM;
+ Y = (float)(image->comps[2].data[i]) * sY;
+ K = (float)(image->comps[3].data[i]) * sK;
+
+ /* Invert all CMYK values */
+ C = 1.0F - C;
+ M = 1.0F - M;
+ Y = 1.0F - Y;
+ K = 1.0F - K;
+
+ /* CMYK -> RGB : RGB results from 0 to 255 */
+ image->comps[0].data[i] = (int)(255.0F * C * K); /* R */
+ image->comps[1].data[i] = (int)(255.0F * M * K); /* G */
+ image->comps[2].data[i] = (int)(255.0F * Y * K); /* B */
+ }
+
+ opj_image_data_free(image->comps[3].data);
+ image->comps[3].data = NULL;
+ image->comps[0].prec = 8;
+ image->comps[1].prec = 8;
+ image->comps[2].prec = 8;
+ image->numcomps -= 1;
+ image->color_space = OPJ_CLRSPC_SRGB;
+
+ for (i = 3; i < image->numcomps; ++i) {
+ memcpy(&(image->comps[i]), &(image->comps[i + 1]), sizeof(image->comps[i]));
+ }
+
+}/* color_cmyk_to_rgb() */