heifsave: make it possible to use a specific encoder (#3198)

* heifsave: make it possible to use a specific encoder

* argument label: switch to leading capital letter

Co-authored-by: Kleis Auke Wolthuizen <github@kleisauke.nl>

* add VipsForeignHeifEncoder enum

* correct type

* implement reviewer feedback

Co-authored-by: Kleis Auke Wolthuizen <github@kleisauke.nl>
This commit is contained in:
Daniel Löbl 2022-12-15 12:02:38 +01:00 committed by GitHub
parent 20a4d6029d
commit 6bb0b4dd1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 4 deletions

View File

@ -26,6 +26,7 @@ master
- GIF load supports truncated frames [tlsa]
- EXIF support for PNG load and save
- deprecate gifsave reoptimise, add reuse
- add "encoder" to heifsave [dloebl]
9/11/22 started 8.13.4
- missing include in mosaic_fuzzer [ServOKio]

View File

@ -2250,6 +2250,7 @@ vips_heifload_source( VipsSource *source, VipsImage **out, ... )
* * @compression: #VipsForeignHeifCompression, write with this compression
* * @effort: %gint, encoding effort
* * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
* * @encoder: #VipsForeignHeifEncoder, select encoder to use
*
* Write a VIPS image to a file in HEIF format.
*
@ -2258,7 +2259,7 @@ vips_heifload_source( VipsSource *source, VipsImage **out, ... )
*
* Set @lossless %TRUE to switch to lossless compression.
*
* Use @compression to set the encoder e.g. HEVC, AVC, AV1. It defaults to AV1
* Use @compression to set the compression format e.g. HEVC, AVC, AV1 to use. It defaults to AV1
* if the target filename ends with ".avif", otherwise HEVC.
*
* Use @effort to control the CPU effort spent improving compression.
@ -2271,6 +2272,8 @@ vips_heifload_source( VipsSource *source, VipsImage **out, ... )
* Use @bitdepth to set the bitdepth of the output file. HEIC supports at
* least 8, 10 and 12 bits; other codecs may support more or fewer options.
*
* Use @encoder to set the encode library to use, e.g. aom, SVT-AV1, rav1e etc.
*
* See also: vips_image_write_to_file(), vips_heifload().
*
* Returns: 0 on success, -1 on error.
@ -2303,6 +2306,7 @@ vips_heifsave( VipsImage *in, const char *filename, ... )
* * @compression: #VipsForeignHeifCompression, write with this compression
* * @effort: %gint, encoding effort
* * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
* * @encoder: #VipsForeignHeifEncoder, select encoder to use
*
* As vips_heifsave(), but save to a memory buffer.
*
@ -2356,6 +2360,7 @@ vips_heifsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
* * @compression: #VipsForeignHeifCompression, write with this compression
* * @effort: %gint, encoding effort
* * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
* * @encoder: #VipsForeignHeifEncoder, select encoder to use
*
* As vips_heifsave(), but save to a target.
*

View File

@ -99,6 +99,10 @@ typedef struct _VipsForeignSaveHeif {
*/
VipsForeignSubsample subsample_mode;
/* Encoder to use. For instance: aom, svt etc.
*/
VipsForeignHeifEncoder selected_encoder;
/* The image we save. This is a copy of save->ready since we need to
* be able to update the metadata.
*/
@ -438,6 +442,7 @@ vips_foreign_save_heif_build( VipsObject *object )
struct heif_error error;
struct heif_writer writer;
char *chroma;
const struct heif_encoder_descriptor* out_encoder;
if( VIPS_OBJECT_CLASS( vips_foreign_save_heif_parent_class )->
build( object ) )
@ -465,9 +470,36 @@ vips_foreign_save_heif_build( VipsObject *object )
heif->image->Type == VIPS_INTERPRETATION_GREY16 ?
12 : 8;
/* Try to find the selected encoder.
*/
if( heif->selected_encoder != VIPS_FOREIGN_HEIF_ENCODER_AUTO ) {
const int count = heif_context_get_encoder_descriptors(
heif->ctx,
(enum heif_compression_format) heif->compression,
vips_enum_nick( VIPS_TYPE_FOREIGN_HEIF_ENCODER,
heif->selected_encoder ),
&out_encoder, 1 );
if( count > 0 ) {
error = heif_context_get_encoder( heif->ctx,
out_encoder, &heif->encoder );
}
else {
g_warning(
"heifsave: could not find selected encoder %s",
vips_enum_nick( VIPS_TYPE_FOREIGN_HEIF_ENCODER,
heif->selected_encoder ) );
}
}
/* Fallback to default encoder.
*/
if( !heif->encoder ) {
error = heif_context_get_encoder_for_format( heif->ctx,
(enum heif_compression_format) heif->compression,
&heif->encoder );
}
if( error.code ) {
if( error.code == heif_error_Unsupported_filetype )
vips_error( "heifsave",
@ -654,6 +686,13 @@ vips_foreign_save_heif_class_init( VipsForeignSaveHeifClass *class )
G_STRUCT_OFFSET( VipsForeignSaveHeif, speed ),
0, 9, 5 );
VIPS_ARG_ENUM( class, "encoder", 18,
_( "Encoder" ),
_( "Select encoder to use" ),
VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveHeif, selected_encoder ),
VIPS_TYPE_FOREIGN_HEIF_ENCODER,
VIPS_FOREIGN_HEIF_ENCODER_AUTO );
}
static void

View File

@ -964,6 +964,28 @@ typedef enum {
VIPS_FOREIGN_HEIF_COMPRESSION_LAST
} VipsForeignHeifCompression;
/**
* VipsForeignHeifEncoder:
* @VIPS_FOREIGN_HEIF_ENCODER_AUTO: auto
* @VIPS_FOREIGN_HEIF_ENCODER_AOM: aom
* @VIPS_FOREIGN_HEIF_ENCODER_RAV1E: RAV1E
* @VIPS_FOREIGN_HEIF_ENCODER_SVT: SVT-AV1
* @VIPS_FOREIGN_HEIF_ENCODER_X265: x265
*
* The selected encoder to use.
* If libheif hasn't been compiled with the selected encoder,
* we will fallback to the default encoder for the compression format.
*
*/
typedef enum {
VIPS_FOREIGN_HEIF_ENCODER_AUTO,
VIPS_FOREIGN_HEIF_ENCODER_AOM,
VIPS_FOREIGN_HEIF_ENCODER_RAV1E,
VIPS_FOREIGN_HEIF_ENCODER_SVT,
VIPS_FOREIGN_HEIF_ENCODER_X265,
VIPS_FOREIGN_HEIF_ENCODER_LAST
} VipsForeignHeifEncoder;
#ifdef __cplusplus
}
#endif /*__cplusplus*/