cmyk jpeg write
This commit is contained in:
parent
775f339360
commit
6a87ea666a
@ -5,6 +5,8 @@
|
|||||||
- revert the dynamic wrapping for Python :-( next version!
|
- revert the dynamic wrapping for Python :-( next version!
|
||||||
- added VImage::convert2disc (thanks Ole)
|
- added VImage::convert2disc (thanks Ole)
|
||||||
- you can now set the jpeg quality factor for tiff pyramids (thanks Joe)
|
- 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
|
12/12/07 started 7.13.3
|
||||||
- added "include <cstring>" to VImage.cc to help gcc 4.3
|
- added "include <cstring>" to VImage.cc to help gcc 4.3
|
||||||
|
12
TODO
12
TODO
@ -1,17 +1,9 @@
|
|||||||
- JPEG write should know about CMYK as well, maybe write all 4 band images as
|
- JPEG write should know about CMYK as well, maybe write all 4 band images as
|
||||||
CMYK?
|
CMYK?
|
||||||
|
|
||||||
- JPEG read could have a "subsample" param and use
|
test CMYK JPEG write, also PNG write with new saveable
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
can we use convert_saveable for PPM and friends as well?
|
||||||
|
|
||||||
- HAVE_HYPOT could define a hypot() macro?
|
- HAVE_HYPOT could define a hypot() macro?
|
||||||
|
|
||||||
|
@ -77,7 +77,13 @@ extern int im__read_test;
|
|||||||
extern int im__mmap_limit;
|
extern int im__mmap_limit;
|
||||||
extern GMutex *im__global_lock;
|
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_make( IMAGE *parent, IMAGE *child );
|
||||||
void im__link_break_all( IMAGE *im );
|
void im__link_break_all( IMAGE *im );
|
||||||
|
@ -52,6 +52,8 @@
|
|||||||
* 2/11/06
|
* 2/11/06
|
||||||
* - moved im__convert_saveable() here so it's always defined (was part
|
* - moved im__convert_saveable() here so it's always defined (was part
|
||||||
* of JPEG write code)
|
* 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 <math.h>
|
||||||
|
|
||||||
#include <vips/vips.h>
|
#include <vips/vips.h>
|
||||||
|
#include <vips/internal.h>
|
||||||
|
|
||||||
#ifdef WITH_DMALLOC
|
#ifdef WITH_DMALLOC
|
||||||
#include <dmalloc.h>
|
#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).
|
/* Convert to a saveable format. im__saveable_t gives the general type of image
|
||||||
* Need to im_close() the return 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 *
|
IMAGE *
|
||||||
im__convert_saveable( IMAGE *in, gboolean allow_alpha )
|
im__convert_saveable( IMAGE *in, im__saveable_t saveable )
|
||||||
{
|
{
|
||||||
IMAGE *out;
|
IMAGE *out;
|
||||||
|
|
||||||
@ -375,11 +379,10 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
|
|||||||
in = t;
|
in = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the bands right. If we have >3, drop down to 3. If we have 2,
|
/* Get the bands right.
|
||||||
* drop down to 1. If allow_alpha is on, we can also have 2/4 bands.
|
|
||||||
*/
|
*/
|
||||||
if( in->Coding == IM_CODING_NONE ) {
|
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" );
|
IMAGE *t = im_open_local( out, "conv:1", "p" );
|
||||||
|
|
||||||
if( !t || im_extract_band( in, t, 0 ) ) {
|
if( !t || im_extract_band( in, t, 0 ) ) {
|
||||||
@ -389,7 +392,7 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
|
|||||||
|
|
||||||
in = t;
|
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" );
|
IMAGE *t = im_open_local( out, "conv:1", "p" );
|
||||||
|
|
||||||
if( !t ||
|
if( !t ||
|
||||||
@ -400,7 +403,8 @@ im__convert_saveable( IMAGE *in, gboolean allow_alpha )
|
|||||||
|
|
||||||
in = t;
|
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" );
|
IMAGE *t = im_open_local( out, "conv:1", "p" );
|
||||||
|
|
||||||
if( !t ||
|
if( !t ||
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
* 11/2/08
|
* 11/2/08
|
||||||
* - spot CMYK jpegs and set Type
|
* - spot CMYK jpegs and set Type
|
||||||
* - spot Adobe CMYK JPEG and invert ink density
|
* - 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
|
static int
|
||||||
read_jpeg_header( struct jpeg_decompress_struct *cinfo,
|
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;
|
jpeg_saved_marker_ptr p;
|
||||||
int type;
|
int type;
|
||||||
@ -448,6 +450,7 @@ read_jpeg_header( struct jpeg_decompress_struct *cinfo,
|
|||||||
* for YUV YCCK etc.
|
* for YUV YCCK etc.
|
||||||
*/
|
*/
|
||||||
jpeg_read_header( cinfo, TRUE );
|
jpeg_read_header( cinfo, TRUE );
|
||||||
|
cinfo->scale_denom = shrink;
|
||||||
jpeg_calc_output_dimensions( cinfo );
|
jpeg_calc_output_dimensions( cinfo );
|
||||||
*invert_pels = FALSE;
|
*invert_pels = FALSE;
|
||||||
switch( cinfo->out_color_space ) {
|
switch( cinfo->out_color_space ) {
|
||||||
@ -611,12 +614,32 @@ read_jpeg_image( struct jpeg_decompress_struct *cinfo, IMAGE *out,
|
|||||||
static int
|
static int
|
||||||
jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
|
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;
|
struct jpeg_decompress_struct cinfo;
|
||||||
ErrorManager eman;
|
ErrorManager eman;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int result;
|
int result;
|
||||||
gboolean invert_pels;
|
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.
|
/* Make jpeg compression object.
|
||||||
*/
|
*/
|
||||||
cinfo.err = jpeg_std_error( &eman.pub );
|
cinfo.err = jpeg_std_error( &eman.pub );
|
||||||
@ -635,12 +658,13 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
/* Make input.
|
/* Make input.
|
||||||
*/
|
*/
|
||||||
#ifdef BINARY_OPEN
|
#ifdef BINARY_OPEN
|
||||||
if( !(fp = fopen( name, "rb" )) ) {
|
if( !(fp = fopen( filename, "rb" )) ) {
|
||||||
#else /*BINARY_OPEN*/
|
#else /*BINARY_OPEN*/
|
||||||
if( !(fp = fopen( name, "r" )) ) {
|
if( !(fp = fopen( filename, "r" )) ) {
|
||||||
#endif /*BINARY_OPEN*/
|
#endif /*BINARY_OPEN*/
|
||||||
jpeg_destroy_decompress( &cinfo );
|
jpeg_destroy_decompress( &cinfo );
|
||||||
im_error( "im_jpeg2vips", _( "unable to open \"%s\"" ), name );
|
im_error( "im_jpeg2vips",
|
||||||
|
_( "unable to open \"%s\"" ), filename );
|
||||||
|
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -654,7 +678,7 @@ jpeg2vips( const char *name, IMAGE *out, gboolean header_only )
|
|||||||
|
|
||||||
/* Convert!
|
/* Convert!
|
||||||
*/
|
*/
|
||||||
result = read_jpeg_header( &cinfo, out, &invert_pels );
|
result = read_jpeg_header( &cinfo, out, &invert_pels, shrink );
|
||||||
if( !header_only && !result )
|
if( !header_only && !result )
|
||||||
result = read_jpeg_image( &cinfo, out, invert_pels );
|
result = read_jpeg_image( &cinfo, out, invert_pels );
|
||||||
|
|
||||||
|
@ -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
|
* 28/11/03 JC
|
||||||
* - better no-overshoot on tile loop
|
* - better no-overshoot on tile loop
|
||||||
@ -23,6 +23,8 @@
|
|||||||
* - oop, libexif confusion
|
* - oop, libexif confusion
|
||||||
* 2/11/07
|
* 2/11/07
|
||||||
* - use im_wbuffer() API for BG writes
|
* - 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 );
|
return( NULL );
|
||||||
memset( write, 0, sizeof( Write ) );
|
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",
|
im_error( "im_vips2jpeg",
|
||||||
_( "unable to convert to RGB for save" ) );
|
_( "unable to convert to saveable format" ) );
|
||||||
write_destroy( write );
|
write_destroy( write );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
@ -541,12 +543,13 @@ static int
|
|||||||
write_vips( Write *write, int qfac, const char *profile )
|
write_vips( Write *write, int qfac, const char *profile )
|
||||||
{
|
{
|
||||||
IMAGE *in = write->in;
|
IMAGE *in = write->in;
|
||||||
|
J_COLOR_SPACE space;
|
||||||
|
|
||||||
/* Should have been converted for save.
|
/* Should have been converted for save.
|
||||||
*/
|
*/
|
||||||
assert( in->BandFmt == IM_BANDFMT_UCHAR );
|
assert( in->BandFmt == IM_BANDFMT_UCHAR );
|
||||||
assert( in->Coding == IM_CODING_NONE );
|
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.
|
/* 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_width = in->Xsize;
|
||||||
write->cinfo.image_height = in->Ysize;
|
write->cinfo.image_height = in->Ysize;
|
||||||
if( in->Bands == 3 ) {
|
write->cinfo.input_components = in->Bands;
|
||||||
write->cinfo.input_components = 3;
|
if( in->Bands == 4 && in->Type == IM_TYPE_CMYK )
|
||||||
write->cinfo.in_color_space = JCS_RGB;
|
space = JCS_CMYK;
|
||||||
}
|
else if( in->Bands == 3 )
|
||||||
else if( in->Bands == 1 ) {
|
space = JCS_RGB;
|
||||||
write->cinfo.input_components = 1;
|
else if( in->Bands == 1 )
|
||||||
write->cinfo.in_color_space = JCS_GRAYSCALE;
|
space = JCS_GRAYSCALE;
|
||||||
}
|
else
|
||||||
|
/* Use luminance compression for all channels.
|
||||||
|
*/
|
||||||
|
space = JCS_UNKNOWN;
|
||||||
|
write->cinfo.in_color_space = space;
|
||||||
|
|
||||||
/* Rest to default.
|
/* Rest to default.
|
||||||
*/
|
*/
|
||||||
|
@ -125,7 +125,7 @@ write_new( IMAGE *in )
|
|||||||
return( NULL );
|
return( NULL );
|
||||||
memset( write, 0, sizeof( Write ) );
|
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",
|
im_error( "im_vips2png",
|
||||||
_( "unable to convert to RGB for save" ) );
|
_( "unable to convert to RGB for save" ) );
|
||||||
write_destroy( write );
|
write_destroy( write );
|
||||||
|
@ -17,8 +17,21 @@ int im_vips2mimejpeg( IMAGE *in )
|
|||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B im_jpeg2vips()
|
.B im_jpeg2vips()
|
||||||
reads the named jpeg file and writes it to the specified
|
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
|
IMAGE. The entire image is read before returning. It can read most 8-bit JPEG
|
||||||
8-bit images only.
|
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
|
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.
|
file. Instead, the embedded profile will be attached to the image as metadata.
|
||||||
|
Loading…
Reference in New Issue
Block a user