better alpha handling for tiff save

the tiff saver was writing all five-band images as CMYKA, even if they
were tagged as srgb ... it now follows the interpretation tag and will
write many alpha channels instead

see https://github.com/jcupitt/libvips/issues/348

thanks sadaqatullahn
This commit is contained in:
John Cupitt 2015-11-11 08:55:42 +00:00
parent aedb174537
commit 66fe338d36
2 changed files with 43 additions and 37 deletions

View File

@ -7,6 +7,7 @@
- only allow [] for filename options - only allow [] for filename options
- add memory.h to Python API .. makes tracked highwater visible - add memory.h to Python API .. makes tracked highwater visible
- added bandjoin_const to add constant bands to an image - added bandjoin_const to add constant bands to an image
- better alpha handling for tiff write, thanks sadaqatullahn
7/5/15 started 8.1.1 7/5/15 started 8.1.1
- oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo - oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo

View File

@ -156,6 +156,8 @@
* 29/9/15 * 29/9/15
* - try to write IPCT metadata * - try to write IPCT metadata
* - try to write photoshop metadata * - try to write photoshop metadata
* 11/11/15
* - better alpha handling, thanks sadaqatullahn
*/ */
/* /*
@ -211,6 +213,10 @@
#include "tiff.h" #include "tiff.h"
/* Max number of alpha channels we allow.
*/
#define MAX_ALPHA (64)
typedef struct _Layer Layer; typedef struct _Layer Layer;
typedef struct _Write Write; typedef struct _Write Write;
@ -510,7 +516,6 @@ write_tiff_header( Write *write, Layer *layer )
{ {
TIFF *tif = layer->tif; TIFF *tif = layer->tif;
uint16 v[1];
int format; int format;
/* Output base header fields. /* Output base header fields.
@ -559,34 +564,39 @@ write_tiff_header( Write *write, Layer *layer )
else { else {
int photometric; int photometric;
/* Number of bands that have colour in .. other bands are saved
* as alpha.
*/
int colour_bands;
int alpha_bands;
TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, write->im->Bands ); TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, write->im->Bands );
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE,
vips_format_sizeof( write->im->BandFmt ) << 3 ); vips_format_sizeof( write->im->BandFmt ) << 3 );
switch( write->im->Bands ) { if( write->im->Bands < 3 ) {
case 1: /* Mono or mono + alpha.
case 2: */
photometric = write->miniswhite ? photometric = write->miniswhite ?
PHOTOMETRIC_MINISWHITE : PHOTOMETRIC_MINISWHITE :
PHOTOMETRIC_MINISBLACK; PHOTOMETRIC_MINISBLACK;
if( write->im->Bands == 2 ) { colour_bands = 1;
v[0] = EXTRASAMPLE_ASSOCALPHA; }
TIFFSetField( tif, TIFFTAG_EXTRASAMPLES, 1, v ); else {
} /* Could be: RGB, CMYK, LAB, perhaps with extra alpha.
break;
case 3:
case 4:
/* could be: RGB, RGBA, CMYK, LAB, LABA, generic
* multi-band image.
*/ */
if( write->im->Type == VIPS_INTERPRETATION_LAB || if( write->im->Type == VIPS_INTERPRETATION_LAB ||
write->im->Type == VIPS_INTERPRETATION_LABS ) write->im->Type == VIPS_INTERPRETATION_LABS ) {
photometric = PHOTOMETRIC_CIELAB; photometric = PHOTOMETRIC_CIELAB;
else if( write->im->Type == VIPS_INTERPRETATION_CMYK ) { colour_bands = 3;
}
else if( write->im->Type == VIPS_INTERPRETATION_CMYK &&
write->im->Bands >= 4 ) {
photometric = PHOTOMETRIC_SEPARATED; photometric = PHOTOMETRIC_SEPARATED;
TIFFSetField( tif, TIFFSetField( tif,
TIFFTAG_INKSET, INKSET_CMYK ); TIFFTAG_INKSET, INKSET_CMYK );
colour_bands = 4;
} }
else if( write->compression == COMPRESSION_JPEG && else if( write->compression == COMPRESSION_JPEG &&
write->im->Bands == 3 && write->im->Bands == 3 &&
@ -599,32 +609,27 @@ write_tiff_header( Write *write, Layer *layer )
photometric = PHOTOMETRIC_YCBCR; photometric = PHOTOMETRIC_YCBCR;
TIFFSetField( tif, TIFFTAG_JPEGCOLORMODE, TIFFSetField( tif, TIFFTAG_JPEGCOLORMODE,
JPEGCOLORMODE_RGB ); JPEGCOLORMODE_RGB );
colour_bands = 3;
} }
else else {
/* Some kind of generic multi-band image ..
* save the first three bands as RGB, the rest
* as alpha.
*/
photometric = PHOTOMETRIC_RGB; photometric = PHOTOMETRIC_RGB;
colour_bands = 3;
if( write->im->Type != VIPS_INTERPRETATION_CMYK &&
write->im->Bands == 4 ) {
v[0] = EXTRASAMPLE_ASSOCALPHA;
TIFFSetField( tif, TIFFTAG_EXTRASAMPLES, 1, v );
} }
}
break; alpha_bands = write->im->Bands - colour_bands;
if( alpha_bands > 0 ) {
uint16 v[MAX_ALPHA];
int i;
case 5: for( i = 0; i < alpha_bands; i++ )
/* Only CMYKA v[i] = EXTRASAMPLE_ASSOCALPHA;
*/ TIFFSetField( tif,
photometric = PHOTOMETRIC_SEPARATED; TIFFTAG_EXTRASAMPLES, alpha_bands, v );
TIFFSetField( tif, TIFFTAG_INKSET, INKSET_CMYK );
v[0] = EXTRASAMPLE_ASSOCALPHA;
TIFFSetField( tif, TIFFTAG_EXTRASAMPLES, 1, v );
break;
default:
/* Who knows. Just call it RGB.
*/
photometric = PHOTOMETRIC_RGB;
break;
} }
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric ); TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, photometric );