Merge pull request #1672 from MathemanFlo/master
Added write functionality for 2 and 4 bit tiff
This commit is contained in:
commit
63b8e162f8
@ -53,7 +53,7 @@ int vips__tiff_write( VipsImage *in, const char *filename,
|
|||||||
char *profile,
|
char *profile,
|
||||||
gboolean tile, int tile_width, int tile_height,
|
gboolean tile, int tile_width, int tile_height,
|
||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
int bitdepth,
|
||||||
gboolean miniswhite,
|
gboolean miniswhite,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff,
|
gboolean bigtiff,
|
||||||
@ -73,7 +73,7 @@ int vips__tiff_write_buf( VipsImage *in,
|
|||||||
char *profile,
|
char *profile,
|
||||||
gboolean tile, int tile_width, int tile_height,
|
gboolean tile, int tile_width, int tile_height,
|
||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
int bitdepth,
|
||||||
gboolean miniswhite,
|
gboolean miniswhite,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff,
|
gboolean bigtiff,
|
||||||
|
@ -199,6 +199,8 @@
|
|||||||
* - better handling of aligned reads in multipage tiffs
|
* - better handling of aligned reads in multipage tiffs
|
||||||
* 28/5/20
|
* 28/5/20
|
||||||
* - add subifd
|
* - add subifd
|
||||||
|
* 06/6/20
|
||||||
|
* - add load functionality for 2 and 4 bit greyscale tiffs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1056,6 +1058,78 @@ rtiff_onebit_line( Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *flg )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Per-scanline process function for 2 bit greyscale images.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
rtiff_twobit_line( Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *flg )
|
||||||
|
{
|
||||||
|
int x, i, z;
|
||||||
|
int minisblack =
|
||||||
|
rtiff->header.photometric_interpretation == PHOTOMETRIC_MINISBLACK;
|
||||||
|
VipsPel twobits, fourbits, bits;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
for( i = 0; i < (n >> 2); i++ ) {
|
||||||
|
bits = (VipsPel) minisblack ? p[i] : ~p[i];
|
||||||
|
|
||||||
|
for( z = 0; z < 4; z++ ) {
|
||||||
|
/* The grey shade is the value four times concatenated */
|
||||||
|
twobits = bits >> 6;
|
||||||
|
fourbits = twobits | (twobits << 2);
|
||||||
|
q[x] = fourbits | (fourbits << 4);
|
||||||
|
bits <<= 2;
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do last byte in line.
|
||||||
|
*/
|
||||||
|
if( n & 3 ) {
|
||||||
|
bits = (VipsPel) minisblack ? p[i] : ~p[i];
|
||||||
|
for( z = 0; z < (n & 3) ; z++ ) {
|
||||||
|
twobits = bits >> 6;
|
||||||
|
fourbits = twobits | (twobits << 2);
|
||||||
|
q[x + z] = fourbits | (fourbits << 4);
|
||||||
|
bits <<= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Per-scanline process function for 4 bit greyscale images.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
rtiff_fourbit_line( Rtiff *rtiff, VipsPel *q, VipsPel *p, int n, void *flg )
|
||||||
|
{
|
||||||
|
int x, i, z;
|
||||||
|
int minisblack =
|
||||||
|
rtiff->header.photometric_interpretation == PHOTOMETRIC_MINISBLACK;
|
||||||
|
VipsPel bits;
|
||||||
|
|
||||||
|
x = 0;
|
||||||
|
|
||||||
|
for( i = 0; i < (n >> 1); i++ ) {
|
||||||
|
bits = (VipsPel) minisblack ? p[i] : ~p[i];
|
||||||
|
|
||||||
|
for( z = 0; z < 2; z++ ) {
|
||||||
|
/* The grey shade is the value two times concatenated */
|
||||||
|
q[x] = (bits & 0xF0) | (bits >> 4);
|
||||||
|
bits <<= 4;
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do last byte in line.
|
||||||
|
*/
|
||||||
|
if( n & 1) {
|
||||||
|
bits = (VipsPel) minisblack ? p[i] : ~p[i];
|
||||||
|
for( z = 0; z < (n & 1) ; z++ ) {
|
||||||
|
q[x + z] = (bits & 0xF0) | (bits >> 4);
|
||||||
|
bits <<= 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read a 1-bit TIFF image.
|
/* Read a 1-bit TIFF image.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -1075,6 +1149,44 @@ rtiff_parse_onebit( Rtiff *rtiff, VipsImage *out )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Read a 2-bit TIFF image.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rtiff_parse_twobit( Rtiff *rtiff, VipsImage *out )
|
||||||
|
{
|
||||||
|
if( rtiff_check_samples( rtiff, 1 ) ||
|
||||||
|
rtiff_check_bits( rtiff, 2 ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
out->Bands = 1;
|
||||||
|
out->BandFmt = VIPS_FORMAT_UCHAR;
|
||||||
|
out->Coding = VIPS_CODING_NONE;
|
||||||
|
out->Type = VIPS_INTERPRETATION_B_W;
|
||||||
|
|
||||||
|
rtiff->sfn = rtiff_twobit_line;
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read a 4-bit TIFF image.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rtiff_parse_fourbit( Rtiff *rtiff, VipsImage *out )
|
||||||
|
{
|
||||||
|
if( rtiff_check_samples( rtiff, 1 ) ||
|
||||||
|
rtiff_check_bits( rtiff, 4 ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
out->Bands = 1;
|
||||||
|
out->BandFmt = VIPS_FORMAT_UCHAR;
|
||||||
|
out->Coding = VIPS_CODING_NONE;
|
||||||
|
out->Type = VIPS_INTERPRETATION_B_W;
|
||||||
|
|
||||||
|
rtiff->sfn = rtiff_fourbit_line;
|
||||||
|
|
||||||
|
return( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap the sense of the first channel, if necessary.
|
/* Swap the sense of the first channel, if necessary.
|
||||||
*/
|
*/
|
||||||
#define GREY_LOOP( TYPE, MAX ) { \
|
#define GREY_LOOP( TYPE, MAX ) { \
|
||||||
@ -1517,8 +1629,13 @@ rtiff_pick_reader( Rtiff *rtiff )
|
|||||||
|
|
||||||
if( photometric_interpretation == PHOTOMETRIC_MINISWHITE ||
|
if( photometric_interpretation == PHOTOMETRIC_MINISWHITE ||
|
||||||
photometric_interpretation == PHOTOMETRIC_MINISBLACK ) {
|
photometric_interpretation == PHOTOMETRIC_MINISBLACK ) {
|
||||||
if( bits_per_sample == 1 )
|
|
||||||
return( rtiff_parse_onebit );
|
if( bits_per_sample == 1)
|
||||||
|
return ( rtiff_parse_onebit );
|
||||||
|
else if ( bits_per_sample == 2 )
|
||||||
|
return ( rtiff_parse_twobit);
|
||||||
|
else if ( bits_per_sample == 4 )
|
||||||
|
return ( rtiff_parse_fourbit);
|
||||||
else
|
else
|
||||||
return( rtiff_parse_greyscale );
|
return( rtiff_parse_greyscale );
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
* - add "depth" to set pyr depth
|
* - add "depth" to set pyr depth
|
||||||
* 12/5/20
|
* 12/5/20
|
||||||
* - add "subifd" to create pyr layers as sub-directories
|
* - add "subifd" to create pyr layers as sub-directories
|
||||||
|
* 8/6/20
|
||||||
|
* - add bitdepth support for 2 and 4 bit greyscale images
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -89,6 +91,7 @@ typedef struct _VipsForeignSaveTiff {
|
|||||||
int tile_height;
|
int tile_height;
|
||||||
gboolean pyramid;
|
gboolean pyramid;
|
||||||
gboolean squash;
|
gboolean squash;
|
||||||
|
int bitdepth;
|
||||||
gboolean miniswhite;
|
gboolean miniswhite;
|
||||||
VipsForeignTiffResunit resunit;
|
VipsForeignTiffResunit resunit;
|
||||||
double xres;
|
double xres;
|
||||||
@ -263,9 +266,16 @@ vips_foreign_save_tiff_class_init( VipsForeignSaveTiffClass *class )
|
|||||||
VIPS_ARG_BOOL( class, "squash", 14,
|
VIPS_ARG_BOOL( class, "squash", 14,
|
||||||
_( "Squash" ),
|
_( "Squash" ),
|
||||||
_( "Squash images down to 1 bit" ),
|
_( "Squash images down to 1 bit" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveTiff, squash ),
|
G_STRUCT_OFFSET( VipsForeignSaveTiff, squash ),
|
||||||
FALSE );
|
FALSE );
|
||||||
|
|
||||||
|
VIPS_ARG_INT( class, "bitdepth", 14,
|
||||||
|
_( "bitdepth" ),
|
||||||
|
_( "Change greyscale image bit depth to 1,2, 4 or 8." ),
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
|
G_STRUCT_OFFSET( VipsForeignSaveTiff, bitdepth ),
|
||||||
|
1,8,8 );
|
||||||
|
|
||||||
VIPS_ARG_BOOL( class, "miniswhite", 14,
|
VIPS_ARG_BOOL( class, "miniswhite", 14,
|
||||||
_( "Miniswhite" ),
|
_( "Miniswhite" ),
|
||||||
@ -368,6 +378,7 @@ vips_foreign_save_tiff_init( VipsForeignSaveTiff *tiff )
|
|||||||
tiff->level = 10;
|
tiff->level = 10;
|
||||||
tiff->lossless = FALSE;
|
tiff->lossless = FALSE;
|
||||||
tiff->depth = VIPS_FOREIGN_DZ_DEPTH_ONETILE;
|
tiff->depth = VIPS_FOREIGN_DZ_DEPTH_ONETILE;
|
||||||
|
tiff->bitdepth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _VipsForeignSaveTiffFile {
|
typedef struct _VipsForeignSaveTiffFile {
|
||||||
@ -392,12 +403,17 @@ vips_foreign_save_tiff_file_build( VipsObject *object )
|
|||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
/* handle the deprecated squash parameter */
|
||||||
|
if( vips_object_argument_isset(object,"squash") ) {
|
||||||
|
tiff->bitdepth = 1; /*we set that even in the case of LAB to LABQ */
|
||||||
|
}
|
||||||
|
|
||||||
if( vips__tiff_write( save->ready, file->filename,
|
if( vips__tiff_write( save->ready, file->filename,
|
||||||
tiff->compression, tiff->Q, tiff->predictor,
|
tiff->compression, tiff->Q, tiff->predictor,
|
||||||
tiff->profile,
|
tiff->profile,
|
||||||
tiff->tile, tiff->tile_width, tiff->tile_height,
|
tiff->tile, tiff->tile_width, tiff->tile_height,
|
||||||
tiff->pyramid,
|
tiff->pyramid,
|
||||||
tiff->squash,
|
tiff->bitdepth,
|
||||||
tiff->miniswhite,
|
tiff->miniswhite,
|
||||||
tiff->resunit, tiff->xres, tiff->yres,
|
tiff->resunit, tiff->xres, tiff->yres,
|
||||||
tiff->bigtiff,
|
tiff->bigtiff,
|
||||||
@ -470,7 +486,7 @@ vips_foreign_save_tiff_buffer_build( VipsObject *object )
|
|||||||
tiff->profile,
|
tiff->profile,
|
||||||
tiff->tile, tiff->tile_width, tiff->tile_height,
|
tiff->tile, tiff->tile_width, tiff->tile_height,
|
||||||
tiff->pyramid,
|
tiff->pyramid,
|
||||||
tiff->squash,
|
tiff->bitdepth,
|
||||||
tiff->miniswhite,
|
tiff->miniswhite,
|
||||||
tiff->resunit, tiff->xres, tiff->yres,
|
tiff->resunit, tiff->xres, tiff->yres,
|
||||||
tiff->bigtiff,
|
tiff->bigtiff,
|
||||||
@ -540,6 +556,7 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
|
|||||||
* * @tile_height: %gint for tile size
|
* * @tile_height: %gint for tile size
|
||||||
* * @pyramid: %gboolean, write an image pyramid
|
* * @pyramid: %gboolean, write an image pyramid
|
||||||
* * @squash: %gboolean, squash 8-bit images down to 1 bit
|
* * @squash: %gboolean, squash 8-bit images down to 1 bit
|
||||||
|
* * @bitdepth: %int, change bit depth to 1,2, or 4 bit
|
||||||
* * @miniswhite: %gboolean, write 1-bit images as MINISWHITE
|
* * @miniswhite: %gboolean, write 1-bit images as MINISWHITE
|
||||||
* * @resunit: #VipsForeignTiffResunit for resolution unit
|
* * @resunit: #VipsForeignTiffResunit for resolution unit
|
||||||
* * @xres: %gdouble horizontal resolution in pixels/mm
|
* * @xres: %gdouble horizontal resolution in pixels/mm
|
||||||
@ -605,10 +622,25 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
|
|||||||
* MINISBLACK TIFFs where black is a 0 bit, but if you set @miniswhite, it
|
* MINISBLACK TIFFs where black is a 0 bit, but if you set @miniswhite, it
|
||||||
* will use 0 for a white bit. Many pre-press applications only work with
|
* will use 0 for a white bit. Many pre-press applications only work with
|
||||||
* images which use this sense. @miniswhite only affects one-bit images, it
|
* images which use this sense. @miniswhite only affects one-bit images, it
|
||||||
* does nothing for greyscale images.
|
* does nothing for greyscale images. Consider @bitdepth for depths 1, 2 and 4.
|
||||||
*
|
*
|
||||||
* Set @squash to squash 3-band float CIELAB images down to 8-bit CIELAB.
|
* Set @squash to squash 3-band float CIELAB images down to 8-bit CIELAB.
|
||||||
*
|
*
|
||||||
|
* Set @bitdepth to make 8-bit uchar images write as 1,2 or 4-bit TIFFs.
|
||||||
|
* In case of depth 1: Values >128 are written as white, values <=128 as black.
|
||||||
|
* Normally vips will write MINISBLACK TIFFs where black is a 0 bit, but if you
|
||||||
|
* set @miniswhite, it will use 0 for a white bit. Many pre-press applications
|
||||||
|
* only work with images which use this sense. @miniswhite only affects one-bit
|
||||||
|
* images, it does nothing for greyscale images.
|
||||||
|
* In case of depth 2: The same holds but values < 64 are written as black.
|
||||||
|
* For 64 <= values < 128 they are written as dark grey, for 128 <= values < 192
|
||||||
|
* they are written as light gray and values above are written as white.
|
||||||
|
* In case @miniswhite is set to true this behavior is inverted.
|
||||||
|
* In case of depth 4: values < 16 are written as black, and so on for the
|
||||||
|
* lighter shades. In case @miniswhite is set to true this behavior is inverted.
|
||||||
|
*
|
||||||
|
* Set @bitdepth to 8 to squash 3-band float CIELAB images down to 8-bit CIELAB.
|
||||||
|
*
|
||||||
* Use @resunit to override the default resolution unit.
|
* Use @resunit to override the default resolution unit.
|
||||||
* The default
|
* The default
|
||||||
* resolution unit is taken from the header field
|
* resolution unit is taken from the header field
|
||||||
@ -673,6 +705,7 @@ vips_tiffsave( VipsImage *in, const char *filename, ... )
|
|||||||
* * @tile_height: %gint for tile size
|
* * @tile_height: %gint for tile size
|
||||||
* * @pyramid: %gboolean, write an image pyramid
|
* * @pyramid: %gboolean, write an image pyramid
|
||||||
* * @squash: %gboolean, squash 8-bit images down to 1 bit
|
* * @squash: %gboolean, squash 8-bit images down to 1 bit
|
||||||
|
* * @bitdepth: %int, change bit depth to 1,2 or 4-bit or squash float to 8 bit
|
||||||
* * @miniswhite: %gboolean, write 1-bit images as MINISWHITE
|
* * @miniswhite: %gboolean, write 1-bit images as MINISWHITE
|
||||||
* * @resunit: #VipsForeignTiffResunit for resolution unit
|
* * @resunit: #VipsForeignTiffResunit for resolution unit
|
||||||
* * @xres: %gdouble horizontal resolution in pixels/mm
|
* * @xres: %gdouble horizontal resolution in pixels/mm
|
||||||
|
@ -195,8 +195,9 @@
|
|||||||
* - add PAGENUMBER support
|
* - add PAGENUMBER support
|
||||||
* 23/5/20
|
* 23/5/20
|
||||||
* - add support for subifd pyramid layers
|
* - add support for subifd pyramid layers
|
||||||
|
* 8/6/20
|
||||||
|
* - add bitdepth support for 2 and 4 bit greyscale images
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
This file is part of VIPS.
|
This file is part of VIPS.
|
||||||
@ -337,7 +338,7 @@ struct _Wtiff {
|
|||||||
int tile; /* Tile or not */
|
int tile; /* Tile or not */
|
||||||
int tilew, tileh; /* Tile size */
|
int tilew, tileh; /* Tile size */
|
||||||
int pyramid; /* Wtiff pyramid */
|
int pyramid; /* Wtiff pyramid */
|
||||||
int squash; /* Write as small format */
|
int bitdepth; /* Write as 1, 2 or 4 bit */
|
||||||
int miniswhite; /* Wtiff as 0 == white */
|
int miniswhite; /* Wtiff as 0 == white */
|
||||||
int resunit; /* Resolution unit (inches or cm) */
|
int resunit; /* Resolution unit (inches or cm) */
|
||||||
double xres; /* Resolution in X */
|
double xres; /* Resolution in X */
|
||||||
@ -694,13 +695,14 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer )
|
|||||||
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 8 );
|
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 8 );
|
||||||
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
|
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_CIELAB );
|
||||||
}
|
}
|
||||||
else if( wtiff->squash ) {
|
else if( wtiff->bitdepth == 1 || wtiff->bitdepth == 2 ||
|
||||||
|
wtiff->bitdepth == 4 ) {
|
||||||
TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 1 );
|
TIFFSetField( tif, TIFFTAG_SAMPLESPERPIXEL, 1 );
|
||||||
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, 1 );
|
TIFFSetField( tif, TIFFTAG_BITSPERSAMPLE, wtiff->bitdepth );
|
||||||
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC,
|
TIFFSetField( tif, TIFFTAG_PHOTOMETRIC,
|
||||||
wtiff->miniswhite ?
|
wtiff->miniswhite ?
|
||||||
PHOTOMETRIC_MINISWHITE :
|
PHOTOMETRIC_MINISWHITE :
|
||||||
PHOTOMETRIC_MINISBLACK );
|
PHOTOMETRIC_MINISBLACK );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int photometric;
|
int photometric;
|
||||||
@ -1039,13 +1041,13 @@ ready_to_write( Wtiff *wtiff )
|
|||||||
|
|
||||||
/* "squash" float LAB down to LABQ.
|
/* "squash" float LAB down to LABQ.
|
||||||
*/
|
*/
|
||||||
if( wtiff->squash &&
|
if( wtiff->bitdepth &&
|
||||||
wtiff->input->Bands == 3 &&
|
wtiff->input->Bands == 3 &&
|
||||||
wtiff->input->BandFmt == VIPS_FORMAT_FLOAT &&
|
wtiff->input->BandFmt == VIPS_FORMAT_FLOAT &&
|
||||||
wtiff->input->Type == VIPS_INTERPRETATION_LAB ) {
|
wtiff->input->Type == VIPS_INTERPRETATION_LAB ) {
|
||||||
if( vips_Lab2LabQ( wtiff->input, &wtiff->ready, NULL ) )
|
if( vips_Lab2LabQ( wtiff->input, &wtiff->ready, NULL ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
wtiff->squash = 0;
|
wtiff->bitdepth = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
wtiff->ready = wtiff->input;
|
wtiff->ready = wtiff->input;
|
||||||
@ -1062,7 +1064,7 @@ wtiff_new( VipsImage *input, const char *filename,
|
|||||||
char *profile,
|
char *profile,
|
||||||
gboolean tile, int tile_width, int tile_height,
|
gboolean tile, int tile_width, int tile_height,
|
||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
int bitdepth,
|
||||||
gboolean miniswhite,
|
gboolean miniswhite,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff,
|
gboolean bigtiff,
|
||||||
@ -1091,7 +1093,7 @@ wtiff_new( VipsImage *input, const char *filename,
|
|||||||
wtiff->tilew = tile_width;
|
wtiff->tilew = tile_width;
|
||||||
wtiff->tileh = tile_height;
|
wtiff->tileh = tile_height;
|
||||||
wtiff->pyramid = pyramid;
|
wtiff->pyramid = pyramid;
|
||||||
wtiff->squash = squash;
|
wtiff->bitdepth = bitdepth;
|
||||||
wtiff->miniswhite = miniswhite;
|
wtiff->miniswhite = miniswhite;
|
||||||
wtiff->resunit = get_resunit( resunit );
|
wtiff->resunit = get_resunit( resunit );
|
||||||
wtiff->xres = xres;
|
wtiff->xres = xres;
|
||||||
@ -1188,23 +1190,30 @@ wtiff_new( VipsImage *input, const char *filename,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Can only squash 8 bit mono. 3-band float should have been squashed
|
if( wtiff->bitdepth && !(wtiff->bitdepth == 1 || wtiff->bitdepth == 2
|
||||||
* above.
|
|| wtiff->bitdepth == 4) ) {
|
||||||
|
g_warning( "%s",
|
||||||
|
_( "allows only bitdepth values 1,2 or 4. "
|
||||||
|
"-- disabling bitdepth") );
|
||||||
|
wtiff->bitdepth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Can only have byte fractional bit depths for 8 bit mono.
|
||||||
|
* 3-band float should have been packed above.
|
||||||
*/
|
*/
|
||||||
if( wtiff->squash &&
|
if( wtiff->bitdepth && !(wtiff->ready->Coding == VIPS_CODING_NONE &&
|
||||||
!(wtiff->ready->Coding == VIPS_CODING_NONE &&
|
wtiff->ready->BandFmt == VIPS_FORMAT_UCHAR &&
|
||||||
wtiff->ready->BandFmt == VIPS_FORMAT_UCHAR &&
|
wtiff->ready->Bands == 1) ) {
|
||||||
wtiff->ready->Bands == 1) ) {
|
|
||||||
g_warning( "%s",
|
g_warning( "%s",
|
||||||
_( "can only squash 1-band uchar and "
|
( "can only set bitdepth for 1-band uchar and "
|
||||||
"3-band float lab -- disabling squash" ) );
|
"3-band float lab -- disabling bitdepth" ) );
|
||||||
wtiff->squash = 0;
|
wtiff->bitdepth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( wtiff->squash &&
|
if( wtiff->bitdepth &&
|
||||||
wtiff->compression == COMPRESSION_JPEG ) {
|
wtiff->compression == COMPRESSION_JPEG ) {
|
||||||
g_warning( "%s",
|
g_warning( "%s",
|
||||||
_( "can't have 1-bit JPEG -- disabling JPEG" ) );
|
_( "can't have 1,2 or 4-bit JPEG -- disabling JPEG" ) );
|
||||||
wtiff->compression = COMPRESSION_NONE;
|
wtiff->compression = COMPRESSION_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1239,8 +1248,12 @@ wtiff_new( VipsImage *input, const char *filename,
|
|||||||
*/
|
*/
|
||||||
if( wtiff->ready->Coding == VIPS_CODING_LABQ )
|
if( wtiff->ready->Coding == VIPS_CODING_LABQ )
|
||||||
wtiff->tls = wtiff->tilew * 3;
|
wtiff->tls = wtiff->tilew * 3;
|
||||||
else if( wtiff->squash )
|
else if( wtiff->bitdepth == 1 )
|
||||||
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 8 ) / 8;
|
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 8 ) / 8;
|
||||||
|
else if( wtiff->bitdepth == 2 )
|
||||||
|
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 4 ) / 4;
|
||||||
|
else if( wtiff->bitdepth == 4 )
|
||||||
|
wtiff->tls = VIPS_ROUND_UP( wtiff->tilew, 2 ) / 2;
|
||||||
else
|
else
|
||||||
wtiff->tls = VIPS_IMAGE_SIZEOF_PEL( wtiff->ready ) *
|
wtiff->tls = VIPS_IMAGE_SIZEOF_PEL( wtiff->ready ) *
|
||||||
wtiff->tilew;
|
wtiff->tilew;
|
||||||
@ -1300,6 +1313,60 @@ eightbit2onebit( Wtiff *wtiff, VipsPel *q, VipsPel *p, int n )
|
|||||||
*q++ = bits << (8 - (x & 0x7));
|
*q++ = bits << (8 - (x & 0x7));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Pack 8 bit VIPS to 2 bit TIFF.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
eightbit2twobit( Wtiff *wtiff, VipsPel *q, VipsPel *p, int n )
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
VipsPel bits;
|
||||||
|
VipsPel mask = wtiff->miniswhite ? 3 : 0;
|
||||||
|
|
||||||
|
bits = 0;
|
||||||
|
|
||||||
|
for( x = 0; x < n; x++ ) {
|
||||||
|
bits <<= 2;
|
||||||
|
bits |= (p[x] >> 6) ^ mask;
|
||||||
|
|
||||||
|
if( (x & 0x3) == 0x3 ) {
|
||||||
|
*q++ = bits;
|
||||||
|
bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Any left-over bits? Need to be left-aligned.
|
||||||
|
*/
|
||||||
|
if( (x & 0x3) != 0 )
|
||||||
|
*q++ = (wtiff->miniswhite ? ~bits : bits) << (8 - ((x & 0x3) << 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pack 8 bit VIPS to 4 bit TIFF.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
eightbit2fourbit( Wtiff *wtiff, VipsPel *q, VipsPel *p, int n )
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
VipsPel bits;
|
||||||
|
VipsPel mask = wtiff->miniswhite ? 15 : 0;
|
||||||
|
bits = 0;
|
||||||
|
|
||||||
|
for( x = 0; x < n; x++ ) {
|
||||||
|
bits <<= 4;
|
||||||
|
bits |= (p[x] >> 4) ^ mask;
|
||||||
|
|
||||||
|
if( (x & 0x1) == 0x1 ) {
|
||||||
|
*q++ = bits;
|
||||||
|
bits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Any left-over bits? Need to be left-aligned.
|
||||||
|
*/
|
||||||
|
if( (x & 0x1) != 0 )
|
||||||
|
*q++ = ((VipsPel)(wtiff->miniswhite ? ~bits : bits))
|
||||||
|
<< (8 - ((x & 0x1) << 2));
|
||||||
|
}
|
||||||
|
|
||||||
/* Swap the sense of the first channel, if necessary.
|
/* Swap the sense of the first channel, if necessary.
|
||||||
*/
|
*/
|
||||||
#define GREY_LOOP( TYPE, MAX ) { \
|
#define GREY_LOOP( TYPE, MAX ) { \
|
||||||
@ -1444,8 +1511,12 @@ wtiff_pack2tiff( Wtiff *wtiff, Layer *layer,
|
|||||||
|
|
||||||
if( wtiff->ready->Coding == VIPS_CODING_LABQ )
|
if( wtiff->ready->Coding == VIPS_CODING_LABQ )
|
||||||
LabQ2LabC( q, p, area->width );
|
LabQ2LabC( q, p, area->width );
|
||||||
else if( wtiff->squash )
|
else if( wtiff->bitdepth == 1 )
|
||||||
eightbit2onebit( wtiff, q, p, area->width );
|
eightbit2onebit( wtiff, q, p, area->width );
|
||||||
|
else if( wtiff->bitdepth == 2 )
|
||||||
|
eightbit2twobit( wtiff, q, p, area->width );
|
||||||
|
else if( wtiff->bitdepth == 4 )
|
||||||
|
eightbit2fourbit( wtiff, q, p, area->width );
|
||||||
else if( wtiff->input->Type == VIPS_INTERPRETATION_XYZ )
|
else if( wtiff->input->Type == VIPS_INTERPRETATION_XYZ )
|
||||||
XYZ2tiffxyz( q, p, area->width, in->im->Bands );
|
XYZ2tiffxyz( q, p, area->width, in->im->Bands );
|
||||||
else if( (in->im->Bands == 1 || in->im->Bands == 2) &&
|
else if( (in->im->Bands == 1 || in->im->Bands == 2) &&
|
||||||
@ -1543,10 +1614,18 @@ wtiff_layer_write_strip( Wtiff *wtiff, Layer *layer, VipsRegion *strip )
|
|||||||
XYZ2tiffxyz( wtiff->tbuf, p, im->Xsize, im->Bands );
|
XYZ2tiffxyz( wtiff->tbuf, p, im->Xsize, im->Bands );
|
||||||
p = wtiff->tbuf;
|
p = wtiff->tbuf;
|
||||||
}
|
}
|
||||||
else if( wtiff->squash ) {
|
else if( wtiff->bitdepth == 1 ) {
|
||||||
eightbit2onebit( wtiff, wtiff->tbuf, p, im->Xsize );
|
eightbit2onebit( wtiff, wtiff->tbuf, p, im->Xsize );
|
||||||
p = wtiff->tbuf;
|
p = wtiff->tbuf;
|
||||||
}
|
}
|
||||||
|
else if( wtiff->bitdepth == 2 ) {
|
||||||
|
eightbit2twobit( wtiff, wtiff->tbuf, p, im->Xsize );
|
||||||
|
p = wtiff->tbuf;
|
||||||
|
}
|
||||||
|
else if( wtiff->bitdepth == 4 ) {
|
||||||
|
eightbit2fourbit( wtiff, wtiff->tbuf, p, im->Xsize );
|
||||||
|
p = wtiff->tbuf;
|
||||||
|
}
|
||||||
else if( (im->Bands == 1 || im->Bands == 2) &&
|
else if( (im->Bands == 1 || im->Bands == 2) &&
|
||||||
wtiff->miniswhite ) {
|
wtiff->miniswhite ) {
|
||||||
invert_band0( wtiff, wtiff->tbuf, p, im->Xsize );
|
invert_band0( wtiff, wtiff->tbuf, p, im->Xsize );
|
||||||
@ -2042,7 +2121,7 @@ vips__tiff_write( VipsImage *input, const char *filename,
|
|||||||
char *profile,
|
char *profile,
|
||||||
gboolean tile, int tile_width, int tile_height,
|
gboolean tile, int tile_width, int tile_height,
|
||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
int bitdepth,
|
||||||
gboolean miniswhite,
|
gboolean miniswhite,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff,
|
gboolean bigtiff,
|
||||||
@ -2064,7 +2143,7 @@ vips__tiff_write( VipsImage *input, const char *filename,
|
|||||||
|
|
||||||
if( !(wtiff = wtiff_new( input, filename,
|
if( !(wtiff = wtiff_new( input, filename,
|
||||||
compression, Q, predictor, profile,
|
compression, Q, predictor, profile,
|
||||||
tile, tile_width, tile_height, pyramid, squash,
|
tile, tile_width, tile_height, pyramid, bitdepth,
|
||||||
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
|
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
|
||||||
properties, strip, region_shrink, level, lossless, depth,
|
properties, strip, region_shrink, level, lossless, depth,
|
||||||
subifd )) )
|
subifd )) )
|
||||||
@ -2088,7 +2167,7 @@ vips__tiff_write_buf( VipsImage *input,
|
|||||||
char *profile,
|
char *profile,
|
||||||
gboolean tile, int tile_width, int tile_height,
|
gboolean tile, int tile_width, int tile_height,
|
||||||
gboolean pyramid,
|
gboolean pyramid,
|
||||||
gboolean squash,
|
int bitdepth,
|
||||||
gboolean miniswhite,
|
gboolean miniswhite,
|
||||||
VipsForeignTiffResunit resunit, double xres, double yres,
|
VipsForeignTiffResunit resunit, double xres, double yres,
|
||||||
gboolean bigtiff,
|
gboolean bigtiff,
|
||||||
@ -2106,7 +2185,7 @@ vips__tiff_write_buf( VipsImage *input,
|
|||||||
|
|
||||||
if( !(wtiff = wtiff_new( input, NULL,
|
if( !(wtiff = wtiff_new( input, NULL,
|
||||||
compression, Q, predictor, profile,
|
compression, Q, predictor, profile,
|
||||||
tile, tile_width, tile_height, pyramid, squash,
|
tile, tile_width, tile_height, pyramid, bitdepth,
|
||||||
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
|
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
|
||||||
properties, strip, region_shrink, level, lossless, depth,
|
properties, strip, region_shrink, level, lossless, depth,
|
||||||
subifd )) )
|
subifd )) )
|
||||||
|
Loading…
Reference in New Issue
Block a user