cmyk jpeg write

This commit is contained in:
John Cupitt 2008-02-15 18:07:39 +00:00
parent 775f339360
commit 6a87ea666a
8 changed files with 87 additions and 39 deletions

View File

@ -5,6 +5,8 @@
- revert the dynamic wrapping for Python :-( next version!
- added VImage::convert2disc (thanks Ole)
- you can now set the jpeg quality factor for tiff pyramids (thanks Joe)
- you can now shrink jpegs during read, see "man im_jpeg2vips"
- added CMYK JPEG write
12/12/07 started 7.13.3
- added "include <cstring>" to VImage.cc to help gcc 4.3

12
TODO
View File

@ -1,17 +1,9 @@
- JPEG write should know about CMYK as well, maybe write all 4 band images as
CMYK?
- JPEG read could have a "subsample" param and use
unsigned int scale_num, scale_denom
Scale the image by the fraction scale_num/scale_denom.
Default is 1/1, or no scaling. Currently, the only supported
scaling ratios are 1/1, 1/2, 1/4, and 1/8. (The library design
allows for arbitrary scaling ratios but this is not likely to
be implemented any time soon.) Smaller scaling ratios permit
significantly faster decoding since fewer pixels need be processed
and a simpler IDCT method can be used.
test CMYK JPEG write, also PNG write with new saveable
can we use convert_saveable for PPM and friends as well?
- HAVE_HYPOT could define a hypot() macro?

View File

@ -77,7 +77,13 @@ extern int im__read_test;
extern int im__mmap_limit;
extern GMutex *im__global_lock;
IMAGE *im__convert_saveable( IMAGE *in, gboolean allow_alpha );
typedef enum {
IM__RGB, /* 1 or 3 bands (like PPM) */
IM__RGBA, /* 1, 2, 3 or 4 bands (like PNG) */
IM__RGB_CMYK /* 1, 3 or 4 bands (like JPEG) */
} im__saveable_t;
IMAGE *im__convert_saveable( IMAGE *in, im__saveable_t saveable );
void im__link_make( IMAGE *parent, IMAGE *child );
void im__link_break_all( IMAGE *im );

View File

@ -52,6 +52,8 @@
* 2/11/06
* - moved im__convert_saveable() here so it's always defined (was part
* of JPEG write code)
* 15/2/08
* - added im__saveable_t ... so we can have CMYK JPEG write
*/
/*
@ -90,6 +92,7 @@
#include <math.h>
#include <vips/vips.h>
#include <vips/internal.h>
#ifdef WITH_DMALLOC
#include <dmalloc.h>
@ -344,11 +347,12 @@ im_copy_from( IMAGE *in, IMAGE *out, im_arch_type architecture )
}
}
/* Convert to 1 or 3 band uchar sRGB (or 2/4 band, if allow_alpha is set).
* Need to im_close() the return IMAGE.
/* Convert to a saveable format. im__saveable_t gives the general type of image
* we make: vanilla 1/3 bands (PPM), with an optional alpha (like PNG), or
* with CMYK as an option (like JPEG). Need to im_close() the return IMAGE.
*/
IMAGE *
im__convert_saveable( IMAGE *in, gboolean allow_alpha )
im__convert_saveable( IMAGE *in, im__saveable_t saveable )
{
IMAGE *out;
@ -375,11 +379,10 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
in = t;
}
/* Get the bands right. If we have >3, drop down to 3. If we have 2,
* drop down to 1. If allow_alpha is on, we can also have 2/4 bands.
/* Get the bands right.
*/
if( in->Coding == IM_CODING_NONE ) {
if( in->Bands == 2 && !allow_alpha ) {
if( in->Bands == 2 && saveable != IM__RGBA ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t || im_extract_band( in, t, 0 ) ) {
@ -389,7 +392,7 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
in = t;
}
else if( in->Bands > 3 && !allow_alpha ) {
else if( in->Bands > 3 && saveable == IM__RGB ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t ||
@ -400,7 +403,8 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
in = t;
}
else if( in->Bands > 4 && allow_alpha ) {
else if( in->Bands > 4 &&
(saveable == IM__RGB_CMYK || saveable == IM__RGBA) ) {
IMAGE *t = im_open_local( out, "conv:1", "p" );
if( !t ||

View File

@ -20,6 +20,8 @@
* 11/2/08
* - spot CMYK jpegs and set Type
* - spot Adobe CMYK JPEG and invert ink density
* 15/2/08
* - added "shrink" parameter
*/
/*
@ -432,7 +434,7 @@ read_exif( IMAGE *im, void *data, int data_length )
*/
static int
read_jpeg_header( struct jpeg_decompress_struct *cinfo,
IMAGE *out, gboolean *invert_pels )
IMAGE *out, gboolean *invert_pels, int shrink )
{
jpeg_saved_marker_ptr p;
int type;
@ -448,6 +450,7 @@ read_jpeg_header( struct jpeg_decompress_struct *cinfo,
* for YUV YCCK etc.
*/
jpeg_read_header( cinfo, TRUE );
cinfo->scale_denom = shrink;
jpeg_calc_output_dimensions( cinfo );
*invert_pels = FALSE;
switch( cinfo->out_color_space ) {
@ -611,12 +614,32 @@ read_jpeg_image( struct jpeg_decompress_struct *cinfo, IMAGE *out,
static int
jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
{
char filename[FILENAME_MAX];
char mode[FILENAME_MAX];
char *p, *q;
int shrink;
struct jpeg_decompress_struct cinfo;
ErrorManager eman;
FILE *fp;
int result;
gboolean invert_pels;
/* Parse the filename.
*/
im_filename_split( name, filename, mode );
p = &mode[0];
shrink = 1;
if( (q = im_getnextoption( &p )) ) {
shrink = atoi( q );
if( shrink != 1 && shrink != 2 &&
shrink != 4 && shrink != 8 ) {
im_error( "im_jpeg2vips",
_( "bad shrink factor %d" ), shrink );
return( -1 );
}
}
/* Make jpeg compression object.
*/
cinfo.err = jpeg_std_error( &eman.pub );
@ -635,12 +658,13 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
/* Make input.
*/
#ifdef BINARY_OPEN
if( !(fp = fopen( name, "rb" )) ) {
if( !(fp = fopen( filename, "rb" )) ) {
#else /*BINARY_OPEN*/
if( !(fp = fopen( name, "r" )) ) {
if( !(fp = fopen( filename, "r" )) ) {
#endif /*BINARY_OPEN*/
jpeg_destroy_decompress( &cinfo );
im_error( "im_jpeg2vips", _( "unable to open \"%s\"" ), name );
im_error( "im_jpeg2vips",
_( "unable to open \"%s\"" ), filename );
return( -1 );
}
@ -654,7 +678,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
/* Convert!
*/
result = read_jpeg_header( &cinfo, out, &invert_pels );
result = read_jpeg_header( &cinfo, out, &invert_pels, shrink );
if( !header_only && !result )
result = read_jpeg_image( &cinfo, out, invert_pels );

View File

@ -1,4 +1,4 @@
/* Convert 1 or 3-band 8-bit VIPS images to/from JPEG.
/* Convert 8-bit VIPS images to/from JPEG.
*
* 28/11/03 JC
* - better no-overshoot on tile loop
@ -23,6 +23,8 @@
* - oop, libexif confusion
* 2/11/07
* - use im_wbuffer() API for BG writes
* 15/2/08
* - write CMYK if Bands == 4 and Type == CMYK
*/
/*
@ -217,9 +219,9 @@ write_new( IMAGE *in )
return( NULL );
memset( write, 0, sizeof( Write ) );
if( !(write->in = im__convert_saveable( in, FALSE )) ) {
if( !(write->in = im__convert_saveable( in, IM__RGB_CMYK )) ) {
im_error( "im_vips2jpeg",
_( "unable to convert to RGB for save" ) );
_( "unable to convert to saveable format" ) );
write_destroy( write );
return( NULL );
}
@ -541,12 +543,13 @@ static int
write_vips( Write *write, int qfac, const char *profile )
{
IMAGE *in = write->in;
J_COLOR_SPACE space;
/* Should have been converted for save.
*/
assert( in->BandFmt == IM_BANDFMT_UCHAR );
assert( in->Coding == IM_CODING_NONE );
assert( in->Bands == 1 || in->Bands == 3 );
assert( in->Bands == 1 || in->Bands == 3 || in->Bands == 4 );
/* Check input image.
*/
@ -561,14 +564,18 @@ write_vips( Write *write, int qfac, const char *profile )
*/
write->cinfo.image_width = in->Xsize;
write->cinfo.image_height = in->Ysize;
if( in->Bands == 3 ) {
write->cinfo.input_components = 3;
write->cinfo.in_color_space = JCS_RGB;
}
else if( in->Bands == 1 ) {
write->cinfo.input_components = 1;
write->cinfo.in_color_space = JCS_GRAYSCALE;
}
write->cinfo.input_components = in->Bands;
if( in->Bands == 4 && in->Type == IM_TYPE_CMYK )
space = JCS_CMYK;
else if( in->Bands == 3 )
space = JCS_RGB;
else if( in->Bands == 1 )
space = JCS_GRAYSCALE;
else
/* Use luminance compression for all channels.
*/
space = JCS_UNKNOWN;
write->cinfo.in_color_space = space;
/* Rest to default.
*/

View File

@ -125,7 +125,7 @@ write_new( IMAGE *in )
return( NULL );
memset( write, 0, sizeof( Write ) );
if( !(write->in = im__convert_saveable( in, TRUE )) ) {
if( !(write->in = im__convert_saveable( in, IM__RGBA )) ) {
im_error( "im_vips2png",
_( "unable to convert to RGB for save" ) );
write_destroy( write );

View File

@ -17,8 +17,21 @@ int im_vips2mimejpeg( IMAGE *in )
.SH DESCRIPTION
.B im_jpeg2vips()
reads the named jpeg file and writes it to the specified
IMAGE. The entire image is read before returning. It will handle 1 and 3 band
8-bit images only.
IMAGE. The entire image is read before returning. It can read most 8-bit JPEG
images, including CMYK.
You can embed options in the filename. They have the form:
filename.jpg:<shrink-factor>
.B shrink-factor
will shrink the image by that factor during read. Allowed values are 1, 2, 4
and 8. Shrinking during read is very much faster than decompressing the whole
image and then shrinking. Example:
fred.jpg:8
will return fred.jpg shrink by a factor of 8.
Any embedded ICC profiles are ignored: you always just get the RGB from the
file. Instead, the embedded profile will be attached to the image as metadata.