static void fast_cmyk_to_bgr(fz_context *ctx, fz_pixmap *dst, fz_pixmap *src) { unsigned char *s = src->samples; unsigned char *d = dst->samples; int n = src->w * src->h; while (n--) { #ifdef SLOWCMYK float cmyk[4], rgb[3]; cmyk[0] = s[0] / 255.0f; cmyk[1] = s[1] / 255.0f; cmyk[2] = s[2] / 255.0f; cmyk[3] = s[3] / 255.0f; cmyk_to_rgb(ctx, NULL, cmyk, rgb); d[0] = rgb[2] * 255; d[1] = rgb[1] * 255; d[2] = rgb[0] * 255; #else d[0] = 255 - MIN(s[2] + s[3], 255); d[1] = 255 - MIN(s[1] + s[3], 255); d[2] = 255 - MIN(s[0] + s[3], 255); #endif d[3] = s[4]; s += 5; d += 4; } }
bool JpgInput::read_native_scanline(int subimage, int miplevel, int y, int z, void* data) { if (!seek_subimage(subimage, miplevel)) return false; if (m_raw) return false; if (y < 0 || y >= (int)m_cinfo.output_height) // out of range scanline return false; if (m_next_scanline > y) { // User is trying to read an earlier scanline than the one we're // up to. Easy fix: close the file and re-open. ImageSpec dummyspec; int subimage = current_subimage(); if (!close() || !open(m_filename, dummyspec) || !seek_subimage(subimage, 0)) return false; // Somehow, the re-open failed assert(m_next_scanline == 0 && current_subimage() == subimage); } // Set up our custom error handler if (setjmp(m_jerr.setjmp_buffer)) { // Jump to here if there's a libjpeg internal error return false; } void* readdata = data; if (m_cmyk) { // If the file's data is CMYK, read into a 4-channel buffer, then // we'll have to convert. m_cmyk_buf.resize(m_spec.width * 4); readdata = &m_cmyk_buf[0]; ASSERT(m_spec.nchannels == 3); } for (; m_next_scanline <= y; ++m_next_scanline) { // Keep reading until we've read the scanline we really need if (jpeg_read_scanlines(&m_cinfo, (JSAMPLE**)&readdata, 1) != 1 || m_fatalerr) { error("JPEG failed scanline read (\"%s\")", filename().c_str()); return false; } } if (m_cmyk) cmyk_to_rgb(m_spec.width, (unsigned char*)readdata, 4, (unsigned char*)data, 3); return true; }
put_cmyk(j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, JDIMENSION rows_supplied) { ppm_dest_ptr dest = (ppm_dest_ptr)dinfo; register char *bufferptr; register JSAMPROW ptr; register JDIMENSION col; ptr = dest->pub.buffer[0]; bufferptr = dest->iobuffer; for (col = cinfo->output_width; col > 0; col--) { JSAMPLE r, g, b, c = *ptr++, m = *ptr++, y = *ptr++, k = *ptr++; cmyk_to_rgb(c, m, y, k, &r, &g, &b); PUTPPMSAMPLE(bufferptr, r); PUTPPMSAMPLE(bufferptr, g); PUTPPMSAMPLE(bufferptr, b); } (void)JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width); }
int getrgb (char *line, int rgb[], int color_model) { int n, count; count = slash_count (line); if (count == 3) { /* c/m/y/k */ double cmyk[4]; n = sscanf (line, "%lf/%lf/%lf/%lf", &cmyk[0], &cmyk[1], &cmyk[2], &cmyk[3]); if (n != 4 || check_cmyk (cmyk)) return (TRUE); cmyk_to_rgb (rgb, cmyk); return (FALSE); } if (count == 2) { /* r/g/b or h/s/v */ if (color_model == RGB) { /* r/g/b */ n = sscanf (line, "%d/%d/%d", &rgb[0], &rgb[1], &rgb[2]); if (n != 3 || check_rgb (rgb)) return (TRUE); } else { /* h/s/v */ double h, s, v; n = sscanf (line, "%lf/%lf/%lf", &h, &s, &v); if (n != 3 || check_hsv (h, s, v)) return (TRUE); hsv_to_rgb (rgb, h, s, v); } return (FALSE); } if (count == 0) { /* gray */ n = sscanf (line, "%d", &rgb[0]); rgb[1] = rgb[2] = rgb[0]; if (n != 1 || check_rgb (rgb)) return (TRUE); return (FALSE); } /* Get here if there is a problem */ return (TRUE); }
/* Fixes returned data in case they are CMYK or grayscale. */ static inline void fix_data( struct jpg_decoder *deco, int lines_read) { int a; switch (global_cinfo->output_components){ case 1: for (a=0; a<lines_read; a++) gray_to_rgb(deco->scanlines[a], global_cinfo ->output_width); break; case 3: break; case 4: cmyk_to_rgb(deco->scanlines[0], global_cinfo ->output_width*lines_read); break; default: internal("Invalid output_components"); } }
void fz_convert_color(fz_context *ctx, fz_colorspace *ds, float *dv, fz_colorspace *ss, float *sv) { if (ss == fz_device_gray) { if ((ds == fz_device_rgb) || (ds == fz_device_bgr)) { dv[0] = sv[0]; dv[1] = sv[0]; dv[2] = sv[0]; } else if (ds == fz_device_cmyk) { dv[0] = 0; dv[1] = 0; dv[2] = 0; dv[3] = sv[0]; } else fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_rgb) { if (ds == fz_device_gray) { dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f; } else if (ds == fz_device_bgr) { dv[0] = sv[2]; dv[1] = sv[1]; dv[2] = sv[0]; } else if (ds == fz_device_cmyk) { float c = 1 - sv[0]; float m = 1 - sv[1]; float y = 1 - sv[2]; float k = MIN(c, MIN(m, y)); dv[0] = c - k; dv[1] = m - k; dv[2] = y - k; dv[3] = k; } else fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_bgr) { if (ds == fz_device_gray) { dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f; } else if (ds == fz_device_bgr) { dv[0] = sv[2]; dv[1] = sv[1]; dv[2] = sv[0]; } else if (ds == fz_device_cmyk) { float c = 1 - sv[2]; float m = 1 - sv[1]; float y = 1 - sv[0]; float k = MIN(c, MIN(m, y)); dv[0] = c - k; dv[1] = m - k; dv[2] = y - k; dv[3] = k; } else fz_std_conv_color(ctx, ss, sv, ds, dv); } else if (ss == fz_device_cmyk) { if (ds == fz_device_gray) { float c = sv[0] * 0.3f; float m = sv[1] * 0.59f; float y = sv[2] * 0.11f; dv[0] = 1 - MIN(c + m + y + sv[3], 1); } else if (ds == fz_device_rgb) { #ifdef SLOWCMYK cmyk_to_rgb(ctx, NULL, sv, dv); #else dv[0] = 1 - MIN(sv[0] + sv[3], 1); dv[1] = 1 - MIN(sv[1] + sv[3], 1); dv[2] = 1 - MIN(sv[2] + sv[3], 1); #endif } else if (ds == fz_device_bgr) { #ifdef SLOWCMYK float rgb[3]; cmyk_to_rgb(ctx, NULL, sv, rgb); dv[0] = rgb[2]; dv[1] = rgb[1]; dv[2] = rgb[0]; #else dv[0] = 1 - MIN(sv[2] + sv[3], 1); dv[1] = 1 - MIN(sv[1] + sv[3], 1); dv[2] = 1 - MIN(sv[0] + sv[3], 1); #endif } else fz_std_conv_color(ctx, ss, sv, ds, dv); } else fz_std_conv_color(ctx, ss, sv, ds, dv); }