From 6df26bfc9b818b44354d6d916df7d79f65d26788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Angel=20S=C3=A1nchez?= Date: Thu, 25 Jul 2019 10:40:52 +0200 Subject: [PATCH] load lab 8bit with alpha to labS --- libvips/foreign/tiff2vips.c | 62 +++++++++++++++++++++++++++++++++++-- libvips/foreign/vips2tiff.c | 41 ++++++++++++------------ 2 files changed, 81 insertions(+), 22 deletions(-) diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 245f9807..9482f22c 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -787,6 +787,57 @@ rtiff_parse_labpack( Rtiff *rtiff, VipsImage *out ) return( 0 ); } + +/* Per-scanline process function for 8-bit VIPS_CODING_LAB to 16-bit LabS with + * alpha. + */ +static void +rtiff_lab_with_alpha_line( Rtiff *rtiff, + VipsPel *q, VipsPel *p, int n, void *dummy ) +{ + int samples_per_pixel = rtiff->header.samples_per_pixel; + + unsigned char *p1; + short *q1; + int x; + + p1 = (unsigned char *) p; + q1 = (short *) q; + for( x = 0; x < n; x++ ) { + int i; + + q1[0] = ((unsigned int) p1[0]) * 32767 / 255; + q1[1] = ((short) p1[1]) << 8; + q1[2] = ((short) p1[2]) << 8; + + for( i = 3; i < samples_per_pixel; i++ ) + q1[i] = (p1[i] << 8) + p1[i]; + + q1 += samples_per_pixel; + p1 += samples_per_pixel; + } +} + +/* Read an 8-bit LAB image with alpha bands into 16-bit LabS. + */ +static int +rtiff_parse_lab_with_alpha( Rtiff *rtiff, VipsImage *out ) +{ + if( rtiff_check_min_samples( rtiff, 4 ) || + rtiff_check_bits( rtiff, 8 ) || + rtiff_check_interpretation( rtiff, PHOTOMETRIC_CIELAB ) ) + return( -1 ); + + out->Bands = rtiff->header.samples_per_pixel; + out->BandFmt = VIPS_FORMAT_SHORT; + out->Coding = VIPS_CODING_NONE; + out->Type = VIPS_INTERPRETATION_LABS; + + rtiff->sfn = rtiff_lab_with_alpha_line; + + return( 0 ); +} + /* Per-scanline process function for LABS. */ static void @@ -802,7 +853,7 @@ rtiff_labs_line( Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *dummy ) p1 = (unsigned short *) p; q1 = (short *) q; for( x = 0; x < n; x++ ) { - /* We use a signed int16 for L. + /* We use signed int16 for L. */ q1[0] = p1[0] >> 1; @@ -1314,10 +1365,15 @@ rtiff_pick_reader( Rtiff *rtiff ) int bits_per_sample = rtiff->header.bits_per_sample; int photometric_interpretation = rtiff->header.photometric_interpretation; + int samples_per_pixel = rtiff->header.samples_per_pixel; if( photometric_interpretation == PHOTOMETRIC_CIELAB ) { - if( bits_per_sample == 8 ) - return( rtiff_parse_labpack ); + if( bits_per_sample == 8 ) { + if( samples_per_pixel > 3 ) + return( rtiff_parse_lab_with_alpha ); + else + return( rtiff_parse_labpack ); + } if( bits_per_sample == 16 ) return( rtiff_parse_labs ); } diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index fca3d64e..ed534d50 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -1117,18 +1117,18 @@ wtiff_new( VipsImage *im, const char *filename, static void LabQ2LabC( VipsPel *q, VipsPel *p, int n ) { - int x; + int x; - for( x = 0; x < n; x++ ) { - /* Get most significant 8 bits of lab. - */ - q[0] = p[0]; - q[1] = p[1]; - q[2] = p[2]; + for( x = 0; x < n; x++ ) { + /* Get most significant 8 bits of lab. + */ + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; - p += 4; - q += 3; - } + p += 4; + q += 3; + } } /* Pack 8 bit VIPS to 1 bit TIFF. @@ -1236,22 +1236,25 @@ invert_band0( Wtiff *wtiff, VipsPel *q, VipsPel *p, int n ) /* Convert VIPS LABS to TIFF 16 bit LAB. */ static void -LabS2Lab16( VipsPel *q, VipsPel *p, int n ) +LabS2Lab16( VipsPel *q, VipsPel *p, int n, int samples_per_pixel ) { - int x; + int x; short *p1 = (short *) p; unsigned short *q1 = (unsigned short *) q; for( x = 0; x < n; x++ ) { + int i; + /* TIFF uses unsigned 16 bit ... move zero, scale up L. */ q1[0] = VIPS_LSHIFT_INT( (int) p1[0], 1 ); - q1[1] = p1[1]; - q1[2] = p1[2]; - p1 += 3; - q1 += 3; - } + for( i = 1; i < samples_per_pixel; i++ ) + q1[i] = p1[i]; + + q1 += samples_per_pixel; + p1 += samples_per_pixel; + } } /* Pack the pixels in @area from @in into a TIFF tile buffer. @@ -1286,7 +1289,7 @@ wtiff_pack2tiff( Wtiff *wtiff, Layer *layer, invert_band0( wtiff, q, p, area->width ); else if( wtiff->im->BandFmt == VIPS_FORMAT_SHORT && wtiff->im->Type == VIPS_INTERPRETATION_LABS ) - LabS2Lab16( q, p, area->width ); + LabS2Lab16( q, p, area->width, in->im->Bands ); else memcpy( q, p, area->width * @@ -1369,7 +1372,7 @@ wtiff_layer_write_strip( Wtiff *wtiff, Layer *layer, VipsRegion *strip ) } else if( im->BandFmt == VIPS_FORMAT_SHORT && im->Type == VIPS_INTERPRETATION_LABS ) { - LabS2Lab16( wtiff->tbuf, p, im->Xsize ); + LabS2Lab16( wtiff->tbuf, p, im->Xsize, im->Bands ); p = wtiff->tbuf; } else if( wtiff->onebit ) {