Bug 44781 - "Support CMYK, YCCK JPEGs" [p=alfredkayser@gmail.com (Alfred Kayser) r=stuart a1.9=schrep]
This commit is contained in:
Родитель
5cdca28c96
Коммит
32b02ba0ed
|
@ -439,7 +439,6 @@ ycck_cmyk_convert (j_decompress_ptr cinfo,
|
|||
{
|
||||
my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
|
||||
register int y, cb, cr;
|
||||
JSAMPLE * range_limit_y;
|
||||
register JSAMPROW outptr;
|
||||
register JSAMPROW inptr0, inptr1, inptr2, inptr3;
|
||||
register JDIMENSION col;
|
||||
|
@ -459,13 +458,12 @@ ycck_cmyk_convert (j_decompress_ptr cinfo,
|
|||
y = GETJSAMPLE(inptr0[col]);
|
||||
cb = GETJSAMPLE(inptr1[col]);
|
||||
cr = GETJSAMPLE(inptr2[col]);
|
||||
range_limit_y = range_limit + MAXJSAMPLE - y;
|
||||
/* Range-limiting is essential due to noise introduced by DCT losses. */
|
||||
outptr[0] = range_limit_y + Cr_r_tab[cr]; /* red */
|
||||
outptr[1] = range_limit_y + /* green */
|
||||
((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr],
|
||||
SCALEBITS));
|
||||
outptr[2] = range_limit_y + Cb_b_tab[cb]; /* blue */
|
||||
outptr[0] = range_limit[MAXJSAMPLE - (y + Cr_r_tab[cr])]; /* red */
|
||||
outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */
|
||||
((int) RIGHT_SHIFT(Cb_g_tab[cb] + Cr_g_tab[cr],
|
||||
SCALEBITS)))];
|
||||
outptr[2] = range_limit[MAXJSAMPLE - (y + Cb_b_tab[cb])]; /* blue */
|
||||
/* K passes through unchanged */
|
||||
outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */
|
||||
outptr += 4;
|
||||
|
|
|
@ -90,6 +90,8 @@ METHODDEF(void) skip_input_data (j_decompress_ptr jd, long num_bytes);
|
|||
METHODDEF(void) term_source (j_decompress_ptr jd);
|
||||
METHODDEF(void) my_error_exit (j_common_ptr cinfo);
|
||||
|
||||
static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width);
|
||||
|
||||
/* Normal JFIF markers can't have more bytes than this. */
|
||||
#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1)
|
||||
|
||||
|
@ -422,6 +424,11 @@ nsresult nsJPEGDecoder::ProcessData(const char *data, PRUint32 count, PRUint32 *
|
|||
case JCS_YCbCr:
|
||||
mInfo.out_color_space = JCS_RGB;
|
||||
break;
|
||||
case JCS_CMYK:
|
||||
case JCS_YCCK:
|
||||
/* libjpeg can convert from YCCK to CMYK, but not to RGB */
|
||||
mInfo.out_color_space = JCS_CMYK;
|
||||
break;
|
||||
default:
|
||||
mState = JPEG_ERROR;
|
||||
PR_LOG(gJPEGDecoderAccountingLog, PR_LOG_DEBUG,
|
||||
|
@ -699,8 +706,7 @@ nsJPEGDecoder::OutputScanlines()
|
|||
}
|
||||
|
||||
JSAMPROW sampleRow = (JSAMPROW)imageRow;
|
||||
if (!mTransform || (mInfo.out_color_space != JCS_GRAYSCALE &&
|
||||
mInfo.out_color_space != JCS_CMYK)) {
|
||||
if (mInfo.output_components == 3) {
|
||||
/* Put the pixels at end of row to enable in-place expansion */
|
||||
sampleRow += mInfo.output_width;
|
||||
}
|
||||
|
@ -726,11 +732,20 @@ nsJPEGDecoder::OutputScanlines()
|
|||
3 * mInfo.output_width);
|
||||
sampleRow += mInfo.output_width;
|
||||
}
|
||||
} else if (gfxPlatform::IsCMSEnabled()) {
|
||||
/* No embedded ICC profile - treat as sRGB */
|
||||
cmsHTRANSFORM transform = gfxPlatform::GetCMSRGBTransform();
|
||||
if (transform) {
|
||||
cmsDoTransform(transform, sampleRow, sampleRow, mInfo.output_width);
|
||||
} else {
|
||||
if (mInfo.out_color_space == JCS_CMYK) {
|
||||
/* Convert from CMYK to RGB */
|
||||
/* We cannot convert directly to Cairo, as the CMSRGBTransform may wants to do a RGB transform... */
|
||||
/* Would be better to have platform CMSenabled transformation from CMYK to (A)RGB... */
|
||||
cmyk_convert_rgb((JSAMPROW)imageRow, mInfo.output_width);
|
||||
sampleRow += mInfo.output_width;
|
||||
}
|
||||
if (gfxPlatform::IsCMSEnabled()) {
|
||||
/* No embedded ICC profile - treat as sRGB */
|
||||
cmsHTRANSFORM transform = gfxPlatform::GetCMSRGBTransform();
|
||||
if (transform) {
|
||||
cmsDoTransform(transform, sampleRow, sampleRow, mInfo.output_width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1267,3 +1282,50 @@ ycc_rgb_convert_argb (j_decompress_ptr cinfo,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************** Inverted CMYK -> RGB conversion **************/
|
||||
/*
|
||||
* Input is (Inverted) CMYK stored as 4 bytes per pixel.
|
||||
* Output is RGB stored as 3 bytes per pixel.
|
||||
* @param row Points to row buffer containing the CMYK bytes for each pixel in the row.
|
||||
* @param width Number of pixels in the row.
|
||||
*/
|
||||
static void cmyk_convert_rgb(JSAMPROW row, JDIMENSION width)
|
||||
{
|
||||
/* Work from end to front to shrink from 4 bytes per pixel to 3 */
|
||||
JSAMPROW in = row + width*4;
|
||||
JSAMPROW out = in;
|
||||
|
||||
for (PRUint32 i = width; i > 0; i--) {
|
||||
in -= 4;
|
||||
out -= 3;
|
||||
|
||||
// Source is 'Inverted CMYK', output is RGB.
|
||||
// See: http://www.easyrgb.com/math.php?MATH=M12#text12
|
||||
// Or: http://www.ilkeratalay.com/colorspacesfaq.php#rgb
|
||||
|
||||
// From CMYK to CMY
|
||||
// C = ( C * ( 1 - K ) + K )
|
||||
// M = ( M * ( 1 - K ) + K )
|
||||
// Y = ( Y * ( 1 - K ) + K )
|
||||
|
||||
// From Inverted CMYK to CMY is thus:
|
||||
// C = ( (1-iC) * (1 - (1-iK)) + (1-iK) ) => 1 - iC*iK
|
||||
// Same for M and Y
|
||||
|
||||
// Convert from CMY (0..1) to RGB (0..1)
|
||||
// R = 1 - C => 1 - (1 - iC*iK) => iC*iK
|
||||
// G = 1 - M => 1 - (1 - iM*iK) => iM*iK
|
||||
// B = 1 - Y => 1 - (1 - iY*iK) => iY*iK
|
||||
|
||||
// Convert from Inverted CMYK (0..255) to RGB (0..255)
|
||||
const PRUint32 iC = in[0];
|
||||
const PRUint32 iM = in[1];
|
||||
const PRUint32 iY = in[2];
|
||||
const PRUint32 iK = in[3];
|
||||
out[0] = iC*iK/255; // Red
|
||||
out[1] = iM*iK/255; // Green
|
||||
out[2] = iY*iK/255; // Blue
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче