8 and 16-bit paletter TIFFs can have alpha

plus 16-bit palette TIFFs now become 16-bit images
This commit is contained in:
John Cupitt 2014-04-14 12:16:15 +01:00
parent dd35d6ffc7
commit 6d2c4c4d60
2 changed files with 110 additions and 38 deletions

View File

@ -20,6 +20,7 @@
- added "postbuild" signal - added "postbuild" signal
- vips_system() now supports many input images and you can change image - vips_system() now supports many input images and you can change image
argument order argument order
- support 16-bit palette TIFFs, plus palette TIFFs can have an alpha
6/3/14 started 7.38.6 6/3/14 started 7.38.6
- grey ramp minimum was wrong - grey ramp minimum was wrong

View File

@ -141,6 +141,9 @@
* - support separate planes for strip read * - support separate planes for strip read
* - big cleanup * - big cleanup
* - support for many more formats, eg. 32-bit int etc. * - support for many more formats, eg. 32-bit int etc.
* 11/4/14
* - support 16 bits per sample palette images
* - palette images can have an alpha
*/ */
/* /*
@ -683,9 +686,13 @@ parse_greyscale( ReadTiff *rtiff, VipsImage *out )
typedef struct { typedef struct {
/* LUTs mapping image indexes to RGB. /* LUTs mapping image indexes to RGB.
*/ */
VipsPel *red; VipsPel *red8;
VipsPel *green; VipsPel *green8;
VipsPel *blue; VipsPel *blue8;
guint16 *red16;
guint16 *green16;
guint16 *blue16;
/* All maps equal, so we write mono. /* All maps equal, so we write mono.
*/ */
@ -695,7 +702,7 @@ typedef struct {
/* Per-scanline process function for palette images. /* Per-scanline process function for palette images.
*/ */
static void static void
palette_line( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client ) palette_line_bit( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client )
{ {
PaletteRead *read = (PaletteRead *) client; PaletteRead *read = (PaletteRead *) client;
@ -718,82 +725,133 @@ palette_line( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client )
bit -= rtiff->bits_per_sample; bit -= rtiff->bits_per_sample;
if( read->mono ) { if( read->mono ) {
q[0] = read->red[i]; q[0] = read->red8[i];
q += 1; q += 1;
} }
else { else {
q[0] = read->red[i]; q[0] = read->red8[i];
q[1] = read->green[i]; q[1] = read->green8[i];
q[2] = read->blue[i]; q[2] = read->blue8[i];
q += 3; q += 3;
} }
} }
} }
/* The tiff is 8-bit and can have an alpha.
*/
static void static void
palette_line16( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n, void *client ) palette_line8( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n,
void *client )
{ {
PaletteRead *read = (PaletteRead *) client; PaletteRead *read = (PaletteRead *) client;
int samples = rtiff->samples_per_pixel;
guint16 *data = (guint16 *) p;
int x; int x;
int s;
for( x = 0; x < n; x++ ) { for( x = 0; x < n; x++ ) {
int i = data[x]; int i = p[0];
if( read->mono ) { if( read->mono )
q[0] = read->red[i]; q[0] = read->red8[i];
q += 1;
}
else { else {
q[0] = read->red[i]; q[0] = read->red8[i];
q[1] = read->green[i]; q[1] = read->green8[i];
q[2] = read->blue[i]; q[2] = read->blue8[i];
q += 3; q += 2;
} }
for( s = 1; s < samples; s++ )
q[s] = p[s];
q += samples;
p += samples;
} }
} }
/* Read a palette-ised TIFF image. 1/2/4/8/16 bits only. /* 16-bit tiff and can have an alpha.
*/
static void
palette_line16( ReadTiff *rtiff, VipsPel *q, VipsPel *p, int n,
void *client )
{
PaletteRead *read = (PaletteRead *) client;
int samples = rtiff->samples_per_pixel;
guint16 *p16, *q16;
int x;
int s;
q16 = (guint16 *) q;
p16 = (guint16 *) p;
for( x = 0; x < n; x++ ) {
int i = p16[0];
if( read->mono )
q16[0] = read->red16[i];
else {
q16[0] = read->red16[i];
q16[1] = read->green16[i];
q16[2] = read->blue16[i];
q16 += 2;
}
for( s = 1; s < samples; s++ )
q16[s] = p16[s];
q16 += samples;
p16 += samples;
}
}
/* Read a palette-ised TIFF image.
*/ */
static int static int
parse_palette( ReadTiff *rtiff, VipsImage *out ) parse_palette( ReadTiff *rtiff, VipsImage *out )
{ {
int len; int len;
PaletteRead *read; PaletteRead *read;
uint16 *tred, *tgreen, *tblue;
int i; int i;
if( check_bits_palette( rtiff ) || if( check_bits_palette( rtiff ) ||
check_samples( rtiff, 1 ) ) check_min_samples( rtiff, 1 ) )
return( -1 ); return( -1 );
len = 1 << rtiff->bits_per_sample; len = 1 << rtiff->bits_per_sample;
if( rtiff->bits_per_sample < 8 &&
rtiff->samples_per_pixel > 1 ) {
vips_error( "tiff2vips", "%s", _( "can't have an alpha for "
"palette images less than 8 bits per sample" ) );
return( -1 );
}
if( !(read = VIPS_NEW( out, PaletteRead )) || if( !(read = VIPS_NEW( out, PaletteRead )) ||
!(read->red = VIPS_ARRAY( out, len, VipsPel )) || !(read->red8 = VIPS_ARRAY( out, len, VipsPel )) ||
!(read->green = VIPS_ARRAY( out, len, VipsPel )) || !(read->green8 = VIPS_ARRAY( out, len, VipsPel )) ||
!(read->blue = VIPS_ARRAY( out, len, VipsPel )) ) !(read->blue8 = VIPS_ARRAY( out, len, VipsPel )) )
return( -1 ); return( -1 );
/* Get maps, convert to 8-bit data. /* Get maps, convert to 8-bit data.
*/ */
if( !TIFFGetField( rtiff->tiff, if( !TIFFGetField( rtiff->tiff,
TIFFTAG_COLORMAP, &tred, &tgreen, &tblue ) ) { TIFFTAG_COLORMAP,
&read->red16, &read->green16, &read->blue16 ) ) {
vips_error( "tiff2vips", "%s", _( "bad colormap" ) ); vips_error( "tiff2vips", "%s", _( "bad colormap" ) );
return( -1 ); return( -1 );
} }
for( i = 0; i < len; i++ ) { for( i = 0; i < len; i++ ) {
read->red[i] = tred[i] >> 8; read->red8[i] = read->red16[i] >> 8;
read->green[i] = tgreen[i] >> 8; read->green8[i] = read->green16[i] >> 8;
read->blue[i] = tblue[i] >> 8; read->blue8[i] = read->blue16[i] >> 8;
} }
/* Are all the maps equal? We have a mono image. /* Are all the maps equal? We have a mono image.
*/ */
read->mono = TRUE; read->mono = TRUE;
for( i = 0; i < len; i++ ) for( i = 0; i < len; i++ )
if( read->red[i] != read->green[i] || if( read->red16[i] != read->green16[i] ||
read->green[i] != read->blue[i] ) { read->green16[i] != read->blue16[i] ) {
read->mono = FALSE; read->mono = FALSE;
break; break;
} }
@ -803,23 +861,36 @@ parse_palette( ReadTiff *rtiff, VipsImage *out )
* just search the colormap. * just search the colormap.
*/ */
out->BandFmt = VIPS_FORMAT_UCHAR; if( rtiff->bits_per_sample <= 8 )
out->BandFmt = VIPS_FORMAT_UCHAR;
else
out->BandFmt = VIPS_FORMAT_USHORT;
out->Coding = VIPS_CODING_NONE; out->Coding = VIPS_CODING_NONE;
if( read->mono ) { if( read->mono ) {
out->Bands = 1; out->Bands = rtiff->samples_per_pixel;
out->Type = VIPS_INTERPRETATION_B_W; if( rtiff->bits_per_sample <= 8 )
out->Type = VIPS_INTERPRETATION_B_W;
else
out->Type = VIPS_INTERPRETATION_GREY16;
} }
else { else {
out->Bands = 3; out->Bands = rtiff->samples_per_pixel + 2;
out->Type = VIPS_INTERPRETATION_sRGB; if( rtiff->bits_per_sample <= 8 )
out->Type = VIPS_INTERPRETATION_sRGB;
else
out->Type = VIPS_INTERPRETATION_RGB16;
} }
rtiff->client = read; rtiff->client = read;
if( rtiff->bits_per_sample == 16 ) if( rtiff->bits_per_sample < 8 )
rtiff->sfn = palette_line_bit;
else if( rtiff->bits_per_sample == 8 )
rtiff->sfn = palette_line8;
else if( rtiff->bits_per_sample == 16 )
rtiff->sfn = palette_line16; rtiff->sfn = palette_line16;
else else
rtiff->sfn = palette_line; g_assert( 0 );
return( 0 ); return( 0 );
} }