diff --git a/ChangeLog.txt b/ChangeLog.txt index 15b403dc..9593f179 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -61,6 +61,8 @@ worst-case JPEG size based on the level of chrominance subsampling. [16] Fixed 32-bit supplementary package for amd64 Debian systems which was broken by enhancements to the packaging system in 1.1. +[17] Support for decoding JPEG images that use the YMCK or YCCK colorspaces. + 1.1.1 ===== diff --git a/jdcolor.c b/jdcolor.c index 0af024cc..5d5c377d 100644 --- a/jdcolor.c +++ b/jdcolor.c @@ -107,6 +107,103 @@ build_ycc_rgb_table (j_decompress_ptr cinfo) } } +/* + * Convert inverted CMYK to RGB + */ +METHODDEF(void) +cmyk_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + double cyan, magenta, yellow, black; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + int rindex = rgb_red[cinfo->out_color_space]; + int gindex = rgb_green[cinfo->out_color_space]; + int bindex = rgb_blue[cinfo->out_color_space]; + int rgbstride = rgb_pixelsize[cinfo->out_color_space]; + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + cyan = (double) GETJSAMPLE(inptr0[col]); + magenta = (double) GETJSAMPLE(inptr1[col]); + yellow = (double) GETJSAMPLE(inptr2[col]); + black = (double) GETJSAMPLE(inptr3[col]); + + outptr[rindex] = (JSAMPLE)(cyan * black / (double)MAXJSAMPLE); + outptr[gindex] = (JSAMPLE)(magenta * black / (double)MAXJSAMPLE); + outptr[bindex] = (JSAMPLE)(yellow * black / (double)MAXJSAMPLE); + outptr += rgbstride; + } + } +} + +/* + * Convert YCCK to RGB + */ +METHODDEF(void) +ycck_rgb_convert (j_decompress_ptr cinfo, + JSAMPIMAGE input_buf, JDIMENSION input_row, + JSAMPARRAY output_buf, int num_rows) +{ + my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; + double cyan, magenta, yellow, black; + register int y, cb, cr; + register JSAMPROW outptr; + register JSAMPROW inptr0, inptr1, inptr2, inptr3; + register JDIMENSION col; + JDIMENSION num_cols = cinfo->output_width; + int rindex = rgb_red[cinfo->out_color_space]; + int gindex = rgb_green[cinfo->out_color_space]; + int bindex = rgb_blue[cinfo->out_color_space]; + int rgbstride = rgb_pixelsize[cinfo->out_color_space]; + + /* copy these pointers into registers if possible */ + register JSAMPLE * range_limit = cinfo->sample_range_limit; + register int * Crrtab = cconvert->Cr_r_tab; + register int * Cbbtab = cconvert->Cb_b_tab; + register INT32 * Crgtab = cconvert->Cr_g_tab; + register INT32 * Cbgtab = cconvert->Cb_g_tab; + SHIFT_TEMPS + + while (--num_rows >= 0) { + inptr0 = input_buf[0][input_row]; + inptr1 = input_buf[1][input_row]; + inptr2 = input_buf[2][input_row]; + inptr3 = input_buf[3][input_row]; + input_row++; + outptr = *output_buf++; + for (col = 0; col < num_cols; col++) { + + /********* Read YCCK Pixel **********/ + y = GETJSAMPLE(inptr0[col]); + cb = GETJSAMPLE(inptr1[col]); + cr = GETJSAMPLE(inptr2[col]); + black = (double)GETJSAMPLE(inptr3[col]); + + /********* Convert YCCK to CMYK **********/ + /* Range-limiting is essential due to noise introduced by DCT losses. */ + cyan = (double)range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; + magenta = (double)range_limit[MAXJSAMPLE - + (y + ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS)))]; + yellow = (double)range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; + + /********* Convert CMYK to RGB **********/ + outptr[rindex] = (JSAMPLE)(cyan * black / (double)MAXJSAMPLE); + outptr[gindex] = (JSAMPLE)(magenta * black / (double)MAXJSAMPLE); + outptr[bindex] = (JSAMPLE)(yellow * black / (double)MAXJSAMPLE); + outptr += rgbstride; + } + } +} /* * Convert some rows of samples to the output colorspace. @@ -386,6 +483,11 @@ jinit_color_deconverter (j_decompress_ptr cinfo) } else if (cinfo->jpeg_color_space == cinfo->out_color_space && rgb_pixelsize[cinfo->out_color_space] == 3) { cconvert->pub.color_convert = null_convert; + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + cconvert->pub.color_convert = cmyk_rgb_convert; + } else if (cinfo->jpeg_color_space == JCS_YCCK) { + cconvert->pub.color_convert = ycck_rgb_convert; + build_ycc_rgb_table(cinfo); } else ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); break;