add webp and zstd support to tiffsave

needs some tests still
This commit is contained in:
John Cupitt 2019-07-08 10:39:44 +01:00
parent 063234fde1
commit 52ee3b083f
7 changed files with 134 additions and 27 deletions

View File

@ -5,6 +5,7 @@
- add "unlimited" flag to svgload - add "unlimited" flag to svgload
- disable webp alpha output if all frames fill the canvas and are solid - disable webp alpha output if all frames fill the canvas and are solid
- add "compression" option to heifsave [lovell] - add "compression" option to heifsave [lovell]
- support webp and zstd compression in tiff
24/5/19 started 8.8.1 24/5/19 started 8.8.1
- improve realpath() use on older libc - improve realpath() use on older libc

View File

@ -1250,6 +1250,20 @@ if test x"$with_tiff" != x"no"; then
) )
fi fi
# WEBP in TIFF added in libtiff 4.0.10
if test x"$with_tiff" != x"no"; then
save_INCLUDES="$INCLUDES"
INCLUDES="$INCLUDES $TIFF_INCLUDES"
AC_CHECK_DECL(COMPRESSION_WEBP,[
AC_DEFINE(HAVE_TIFF_COMPRESSION_WEBP,1,[define if your libtiff has webp.])
],[
],[
[#include <tiffio.h>]
]
)
INCLUDES="$save_INCLUDES"
fi
# giflib # giflib
FIND_GIFLIB( FIND_GIFLIB(
[with_giflib="yes (found by search)" [with_giflib="yes (found by search)"

View File

@ -28,8 +28,8 @@
*/ */
#ifndef VIPS_PARITHMETIC_H #ifndef VIPS_PFOREIGN_H
#define VIPS_PARITHMETIC_H #define VIPS_PFOREIGN_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -60,7 +60,8 @@ int vips__tiff_write( VipsImage *in, const char *filename,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean properties,
gboolean strip, gboolean strip,
VipsRegionShrink region_shrink ); VipsRegionShrink region_shrink,
int level, gboolean lossless );
int vips__tiff_write_buf( VipsImage *in, int vips__tiff_write_buf( VipsImage *in,
void **obuf, size_t *olen, void **obuf, size_t *olen,
@ -75,7 +76,8 @@ int vips__tiff_write_buf( VipsImage *in,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean strip, gboolean properties, gboolean strip,
VipsRegionShrink region_shrink ); VipsRegionShrink region_shrink,
int level, gboolean lossless );
int vips__tiff_read_header( const char *filename, VipsImage *out, int vips__tiff_read_header( const char *filename, VipsImage *out,
int page, int n, gboolean autorotate ); int page, int n, gboolean autorotate );
@ -281,6 +283,6 @@ void vips__heif_error( struct heif_error *error );
} }
#endif /*__cplusplus*/ #endif /*__cplusplus*/
#endif /*VIPS_PARITHMETIC_H*/ #endif /*VIPS_PFOREIGN_H*/

View File

@ -14,6 +14,9 @@
* - predictor defaults to horizontal, reducing file size, usually * - predictor defaults to horizontal, reducing file size, usually
* 13/6/18 * 13/6/18
* - add region_shrink * - add region_shrink
* 8/7/19
* - add webp and zstd support
* - add @level and @lossless
*/ */
/* /*
@ -88,6 +91,8 @@ typedef struct _VipsForeignSaveTiff {
gboolean rgbjpeg; gboolean rgbjpeg;
gboolean properties; gboolean properties;
VipsRegionShrink region_shrink; VipsRegionShrink region_shrink;
int level;
gboolean lossless;
} VipsForeignSaveTiff; } VipsForeignSaveTiff;
typedef VipsForeignSaveClass VipsForeignSaveTiffClass; typedef VipsForeignSaveClass VipsForeignSaveTiffClass;
@ -303,6 +308,20 @@ vips_foreign_save_tiff_class_init( VipsForeignSaveTiffClass *class )
G_STRUCT_OFFSET( VipsForeignSaveTiff, region_shrink ), G_STRUCT_OFFSET( VipsForeignSaveTiff, region_shrink ),
VIPS_TYPE_REGION_SHRINK, VIPS_REGION_SHRINK_MEAN ); VIPS_TYPE_REGION_SHRINK, VIPS_REGION_SHRINK_MEAN );
VIPS_ARG_INT( class, "level", 23,
_( "Level" ),
_( "ZSTD compression level" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveTiff, level ),
1, 22, 10 );
VIPS_ARG_BOOL( class, "lossless", 24,
_( "lossless" ),
_( "Enable WEBP lossless mode" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveTiff, lossless ),
FALSE );
} }
static void static void
@ -317,6 +336,8 @@ vips_foreign_save_tiff_init( VipsForeignSaveTiff *tiff )
tiff->xres = 1.0; tiff->xres = 1.0;
tiff->yres = 1.0; tiff->yres = 1.0;
tiff->region_shrink = VIPS_REGION_SHRINK_MEAN; tiff->region_shrink = VIPS_REGION_SHRINK_MEAN;
tiff->level = 10;
tiff->lossless = FALSE;
} }
typedef struct _VipsForeignSaveTiffFile { typedef struct _VipsForeignSaveTiffFile {
@ -353,7 +374,9 @@ vips_foreign_save_tiff_file_build( VipsObject *object )
tiff->rgbjpeg, tiff->rgbjpeg,
tiff->properties, tiff->properties,
save->strip, save->strip,
tiff->region_shrink ) ) tiff->region_shrink,
tiff->level,
tiff->lossless ) )
return( -1 ); return( -1 );
return( 0 ); return( 0 );
@ -422,7 +445,9 @@ vips_foreign_save_tiff_buffer_build( VipsObject *object )
tiff->rgbjpeg, tiff->rgbjpeg,
tiff->properties, tiff->properties,
save->strip, save->strip,
tiff->region_shrink ) ) tiff->region_shrink,
tiff->level,
tiff->lossless ) )
return( -1 ); return( -1 );
/* vips__tiff_write_buf() makes a buffer that needs g_free(), not /* vips__tiff_write_buf() makes a buffer that needs g_free(), not
@ -488,7 +513,9 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
* * @properties: set %TRUE to write an IMAGEDESCRIPTION tag * * @properties: set %TRUE to write an IMAGEDESCRIPTION tag
* * @strip: set %TRUE to block metadata save * * @strip: set %TRUE to block metadata save
* * @page_height: %gint for page height for multi-page save * * @page_height: %gint for page height for multi-page save
* * @shrink_region: #VipsRegionShrink How to shrink each 2x2 region. * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region.
* * @level: %gint, Zstd compression level
* * @lossless: set %TRUE for WebP losssless mode
* *
* Write a VIPS image to a file as TIFF. * Write a VIPS image to a file as TIFF.
* *
@ -497,13 +524,17 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
* written as series of pages, each #VIPS_META_PAGE_HEIGHT pixels high. * written as series of pages, each #VIPS_META_PAGE_HEIGHT pixels high.
* *
* Use @compression to set the tiff compression. Currently jpeg, packbits, * Use @compression to set the tiff compression. Currently jpeg, packbits,
* fax4, lzw, none and deflate are supported. The default is no compression. * fax4, lzw, none, deflate, webp and zstd are supported. The default is no
* compression.
* JPEG compression is a good lossy compressor for photographs, packbits is * JPEG compression is a good lossy compressor for photographs, packbits is
* good for 1-bit images, and deflate is the best lossless compression TIFF * good for 1-bit images, and deflate is the best lossless compression TIFF
* can do. * can do.
* *
* Use @Q to set the JPEG compression factor. Default 75. * Use @Q to set the JPEG compression factor. Default 75.
* *
* User @level to set the ZSTD compression level. Use @lossless to
* set WEBP lossless mode on. Use @Q to set the WEBP compression level.
*
* Use @predictor to set the predictor for lzw and deflate compression. It * Use @predictor to set the predictor for lzw and deflate compression. It
* defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal * defaults to #VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL, meaning horizontal
* differencing. Please refer to the libtiff * differencing. Please refer to the libtiff
@ -522,7 +553,7 @@ vips_foreign_save_tiff_buffer_init( VipsForeignSaveTiffBuffer *buffer )
* is 128 by 128. * is 128 by 128.
* *
* Set @pyramid to write the image as a set of images, one per page, of * Set @pyramid to write the image as a set of images, one per page, of
* decreasing size. Use @shrink_region to set how images will be shrunk: by * decreasing size. Use @region_shrink to set how images will be shrunk: by
* default each 2x2 block is just averaged, but you can set MODE or MEDIAN as * default each 2x2 block is just averaged, but you can set MODE or MEDIAN as
* well. * well.
* *
@ -601,7 +632,9 @@ vips_tiffsave( VipsImage *in, const char *filename, ... )
* * @properties: set %TRUE to write an IMAGEDESCRIPTION tag * * @properties: set %TRUE to write an IMAGEDESCRIPTION tag
* * @strip: set %TRUE to block metadata save * * @strip: set %TRUE to block metadata save
* * @page_height: %gint for page height for multi-page save * * @page_height: %gint for page height for multi-page save
* * @shrink_region: #VipsRegionShrink How to shrink each 2x2 region. * * @region_shrink: #VipsRegionShrink How to shrink each 2x2 region.
* * @level: %gint, Zstd compression level
* * @lossless: set %TRUE for WebP losssless mode
* *
* As vips_tiffsave(), but save to a memory buffer. * As vips_tiffsave(), but save to a memory buffer.
* *

View File

@ -182,6 +182,9 @@
* - copy EXTRASAMPLES to pyramid layers * - copy EXTRASAMPLES to pyramid layers
* 21/12/18 * 21/12/18
* - stop pyr layers if width or height drop to 1 * - stop pyr layers if width or height drop to 1
* 8/7/19
* - add webp and zstd support
* - add @level and @lossless
*/ */
/* /*
@ -300,7 +303,7 @@ struct _Wtiff {
int tls; /* Tile line size */ int tls; /* Tile line size */
int compression; /* Compression type */ int compression; /* Compression type */
int jpqual; /* JPEG q-factor */ int Q; /* JPEG q-factor, webp level */
int predictor; /* Predictor value */ int predictor; /* Predictor value */
int tile; /* Tile or not */ int tile; /* Tile or not */
int tilew, tileh; /* Tile size */ int tilew, tileh; /* Tile size */
@ -316,6 +319,8 @@ struct _Wtiff {
int properties; /* Set to save XML props */ int properties; /* Set to save XML props */
int strip; /* Don't write metadata */ int strip; /* Don't write metadata */
VipsRegionShrink region_shrink; /* How to shrink regions */ VipsRegionShrink region_shrink; /* How to shrink regions */
int level; /* zstd compression level */
gboolean lossless; /* webp lossless mode */
/* True if we've detected a toilet-roll image, plus the page height, /* True if we've detected a toilet-roll image, plus the page height,
* which has been checked to be a factor of im->Ysize. * which has been checked to be a factor of im->Ysize.
@ -583,7 +588,16 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer )
TIFFSetField( tif, TIFFTAG_COMPRESSION, wtiff->compression ); TIFFSetField( tif, TIFFTAG_COMPRESSION, wtiff->compression );
if( wtiff->compression == COMPRESSION_JPEG ) if( wtiff->compression == COMPRESSION_JPEG )
TIFFSetField( tif, TIFFTAG_JPEGQUALITY, wtiff->jpqual ); TIFFSetField( tif, TIFFTAG_JPEGQUALITY, wtiff->Q );
#ifdef HAVE_TIFF_COMPRESSION_WEBP
if( wtiff->compression == COMPRESSION_WEBP ) {
TIFFSetField( tif, TIFFTAG_WEBP_LEVEL, wtiff->Q );
TIFFSetField( tif, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
}
if( wtiff->compression == COMPRESSION_ZSTD )
TIFFSetField( tif, TIFFTAG_ZSTD_LEVEL, wtiff->level );
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
if( (wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE || if( (wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_DEFLATE ||
wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_LZW) && wtiff->compression == VIPS_FOREIGN_TIFF_COMPRESSION_LZW) &&
@ -666,7 +680,7 @@ wtiff_write_header( Wtiff *wtiff, Layer *layer )
else if( wtiff->compression == COMPRESSION_JPEG && else if( wtiff->compression == COMPRESSION_JPEG &&
wtiff->im->Bands == 3 && wtiff->im->Bands == 3 &&
wtiff->im->BandFmt == VIPS_FORMAT_UCHAR && wtiff->im->BandFmt == VIPS_FORMAT_UCHAR &&
(!wtiff->rgbjpeg && wtiff->jpqual < 90) ) { (!wtiff->rgbjpeg && wtiff->Q < 90) ) {
/* This signals to libjpeg that it can do /* This signals to libjpeg that it can do
* YCbCr chrominance subsampling from RGB, not * YCbCr chrominance subsampling from RGB, not
* that we will supply the image as YCbCr. * that we will supply the image as YCbCr.
@ -876,14 +890,16 @@ get_compression( VipsForeignTiffCompression compression )
return( COMPRESSION_CCITTFAX4 ); return( COMPRESSION_CCITTFAX4 );
case VIPS_FOREIGN_TIFF_COMPRESSION_LZW: case VIPS_FOREIGN_TIFF_COMPRESSION_LZW:
return( COMPRESSION_LZW ); return( COMPRESSION_LZW );
#ifdef HAVE_TIFF_COMPRESSION_WEBP
case VIPS_FOREIGN_TIFF_COMPRESSION_WEBP:
return( COMPRESSION_WEBP );
case VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD:
return( COMPRESSION_ZSTD );
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
default: default:
g_assert_not_reached(); return( COMPRESSION_NONE );
} }
/* Keep -Wall happy.
*/
return( -1 );
} }
static int static int
@ -918,7 +934,8 @@ wtiff_new( VipsImage *im, const char *filename,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean properties,
gboolean strip, gboolean strip,
VipsRegionShrink region_shrink ) VipsRegionShrink region_shrink,
int level, gboolean lossless )
{ {
Wtiff *wtiff; Wtiff *wtiff;
@ -930,7 +947,7 @@ wtiff_new( VipsImage *im, const char *filename,
wtiff->layer = NULL; wtiff->layer = NULL;
wtiff->tbuf = NULL; wtiff->tbuf = NULL;
wtiff->compression = get_compression( compression ); wtiff->compression = get_compression( compression );
wtiff->jpqual = Q; wtiff->Q = Q;
wtiff->predictor = predictor; wtiff->predictor = predictor;
wtiff->tile = tile; wtiff->tile = tile;
wtiff->tilew = tile_width; wtiff->tilew = tile_width;
@ -947,6 +964,8 @@ wtiff_new( VipsImage *im, const char *filename,
wtiff->properties = properties; wtiff->properties = properties;
wtiff->strip = strip; wtiff->strip = strip;
wtiff->region_shrink = region_shrink; wtiff->region_shrink = region_shrink;
wtiff->level = level;
wtiff->lossless = lossless;
wtiff->toilet_roll = FALSE; wtiff->toilet_roll = FALSE;
wtiff->page_height = vips_image_get_page_height( im ); wtiff->page_height = vips_image_get_page_height( im );
wtiff->image_height = im->Ysize; wtiff->image_height = im->Ysize;
@ -1030,6 +1049,21 @@ wtiff_new( VipsImage *im, const char *filename,
wtiff->miniswhite = FALSE; wtiff->miniswhite = FALSE;
} }
/* lossless is for webp only.
*/
#ifdef HAVE_TIFF_COMPRESSION_WEBP
if( wtiff->lossless ) {
if( wtiff->compression == COMPRESSION_NONE )
wtiff->compression = COMPRESSION_WEBP;
if( wtiff->compression != COMPRESSION_WEBP ) {
g_warning( "%s",
_( "lossless is for WEBP compression only" ) );
wtiff->lossless = FALSE;
}
}
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
/* Sizeof a line of bytes in the TIFF tile. /* Sizeof a line of bytes in the TIFF tile.
*/ */
if( im->Coding == VIPS_CODING_LABQ ) if( im->Coding == VIPS_CODING_LABQ )
@ -1603,7 +1637,7 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
* Set explicitly from Wtiff. * Set explicitly from Wtiff.
*/ */
if( wtiff->compression == COMPRESSION_JPEG ) { if( wtiff->compression == COMPRESSION_JPEG ) {
TIFFSetField( out, TIFFTAG_JPEGQUALITY, wtiff->jpqual ); TIFFSetField( out, TIFFTAG_JPEGQUALITY, wtiff->Q );
/* Only for three-band, 8-bit images. /* Only for three-band, 8-bit images.
*/ */
@ -1612,7 +1646,7 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
/* Enable rgb->ycbcr conversion in the jpeg write. /* Enable rgb->ycbcr conversion in the jpeg write.
*/ */
if( !wtiff->rgbjpeg && if( !wtiff->rgbjpeg &&
wtiff->jpqual < 90 ) wtiff->Q < 90 )
TIFFSetField( out, TIFFSetField( out,
TIFFTAG_JPEGCOLORMODE, TIFFTAG_JPEGCOLORMODE,
JPEGCOLORMODE_RGB ); JPEGCOLORMODE_RGB );
@ -1626,6 +1660,17 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in )
} }
} }
#ifdef HAVE_TIFF_COMPRESSION_WEBP
/* More pseudotags we can't copy.
*/
if( wtiff->compression == COMPRESSION_WEBP ) {
TIFFSetField( out, TIFFTAG_WEBP_LEVEL, wtiff->Q );
TIFFSetField( out, TIFFTAG_WEBP_LOSSLESS, wtiff->lossless );
}
if( wtiff->compression == COMPRESSION_ZSTD )
TIFFSetField( out, TIFFTAG_ZSTD_LEVEL, wtiff->level );
#endif /*HAVE_TIFF_COMPRESSION_WEBP*/
/* We can't copy profiles or xmp :( Set again from Wtiff. /* We can't copy profiles or xmp :( Set again from Wtiff.
*/ */
if( !wtiff->strip ) if( !wtiff->strip )
@ -1785,7 +1830,8 @@ vips__tiff_write( VipsImage *in, const char *filename,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean strip, gboolean properties, gboolean strip,
VipsRegionShrink region_shrink ) VipsRegionShrink region_shrink,
int level, gboolean lossless )
{ {
Wtiff *wtiff; Wtiff *wtiff;
@ -1802,7 +1848,7 @@ vips__tiff_write( VipsImage *in, const char *filename,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash, tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink )) ) properties, strip, region_shrink, level, lossless )) )
return( -1 ); return( -1 );
if( wtiff_write_image( wtiff ) ) { if( wtiff_write_image( wtiff ) ) {
@ -1829,7 +1875,8 @@ vips__tiff_write_buf( VipsImage *in,
gboolean bigtiff, gboolean bigtiff,
gboolean rgbjpeg, gboolean rgbjpeg,
gboolean properties, gboolean strip, gboolean properties, gboolean strip,
VipsRegionShrink region_shrink ) VipsRegionShrink region_shrink,
int level, gboolean lossless )
{ {
Wtiff *wtiff; Wtiff *wtiff;
@ -1842,7 +1889,7 @@ vips__tiff_write_buf( VipsImage *in,
compression, Q, predictor, profile, compression, Q, predictor, profile,
tile, tile_width, tile_height, pyramid, squash, tile, tile_width, tile_height, pyramid, squash,
miniswhite, resunit, xres, yres, bigtiff, rgbjpeg, miniswhite, resunit, xres, yres, bigtiff, rgbjpeg,
properties, strip, region_shrink )) ) properties, strip, region_shrink, level, lossless )) )
return( -1 ); return( -1 );
wtiff->obuf = obuf; wtiff->obuf = obuf;

View File

@ -406,12 +406,18 @@ int vips_webpsave_mime( VipsImage *in, ... )
* @VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS: packbits compression * @VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS: packbits compression
* @VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4: fax4 compression * @VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4: fax4 compression
* @VIPS_FOREIGN_TIFF_COMPRESSION_LZW: LZW compression * @VIPS_FOREIGN_TIFF_COMPRESSION_LZW: LZW compression
* @VIPS_FOREIGN_TIFF_COMPRESSION_WEBP: WEBP compression
* @VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD: ZSTD compression
* *
* The compression types supported by the tiff writer. * The compression types supported by the tiff writer.
* *
* Use @Q to set the jpeg compression level, default 75. * Use @Q to set the jpeg compression level, default 75.
* *
* Use @prediction to set the lzw or deflate prediction, default none. * Use @prediction to set the lzw or deflate prediction, default none.
*
* Use @lossless to set WEBP lossless compression.
*
* Use @level to set webp and zstd compression level.
*/ */
typedef enum { typedef enum {
VIPS_FOREIGN_TIFF_COMPRESSION_NONE, VIPS_FOREIGN_TIFF_COMPRESSION_NONE,
@ -420,6 +426,8 @@ typedef enum {
VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS, VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS,
VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4, VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4,
VIPS_FOREIGN_TIFF_COMPRESSION_LZW, VIPS_FOREIGN_TIFF_COMPRESSION_LZW,
VIPS_FOREIGN_TIFF_COMPRESSION_WEBP,
VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD,
VIPS_FOREIGN_TIFF_COMPRESSION_LAST VIPS_FOREIGN_TIFF_COMPRESSION_LAST
} VipsForeignTiffCompression; } VipsForeignTiffCompression;

View File

@ -533,6 +533,8 @@ vips_foreign_tiff_compression_get_type( void )
{VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS, "VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS", "packbits"}, {VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS, "VIPS_FOREIGN_TIFF_COMPRESSION_PACKBITS", "packbits"},
{VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4, "VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4", "ccittfax4"}, {VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4, "VIPS_FOREIGN_TIFF_COMPRESSION_CCITTFAX4", "ccittfax4"},
{VIPS_FOREIGN_TIFF_COMPRESSION_LZW, "VIPS_FOREIGN_TIFF_COMPRESSION_LZW", "lzw"}, {VIPS_FOREIGN_TIFF_COMPRESSION_LZW, "VIPS_FOREIGN_TIFF_COMPRESSION_LZW", "lzw"},
{VIPS_FOREIGN_TIFF_COMPRESSION_WEBP, "VIPS_FOREIGN_TIFF_COMPRESSION_WEBP", "webp"},
{VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD, "VIPS_FOREIGN_TIFF_COMPRESSION_ZSTD", "zstd"},
{VIPS_FOREIGN_TIFF_COMPRESSION_LAST, "VIPS_FOREIGN_TIFF_COMPRESSION_LAST", "last"}, {VIPS_FOREIGN_TIFF_COMPRESSION_LAST, "VIPS_FOREIGN_TIFF_COMPRESSION_LAST", "last"},
{0, NULL, NULL} {0, NULL, NULL}
}; };