set basic jxl image metadata from vips
This commit is contained in:
parent
e93d0ab83c
commit
b82ca537e7
@ -55,6 +55,15 @@
|
|||||||
|
|
||||||
#include "pforeign.h"
|
#include "pforeign.h"
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
*
|
||||||
|
* - libjxl currently seems to be missing API to attach a profile
|
||||||
|
*
|
||||||
|
* - libjxl seems to only work in one shot mode, so there's no way to write in
|
||||||
|
* chunks
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#define OUTPUT_BUFFER_SIZE (4096)
|
#define OUTPUT_BUFFER_SIZE (4096)
|
||||||
|
|
||||||
typedef struct _VipsForeignSaveJxl {
|
typedef struct _VipsForeignSaveJxl {
|
||||||
@ -68,8 +77,7 @@ typedef struct _VipsForeignSaveJxl {
|
|||||||
*/
|
*/
|
||||||
JxlBasicInfo info;
|
JxlBasicInfo info;
|
||||||
JxlColorEncoding color_encoding;
|
JxlColorEncoding color_encoding;
|
||||||
size_t icc_size;
|
JxlPixelFormat format;
|
||||||
uint8_t *icc_data;
|
|
||||||
|
|
||||||
/* Encoder state.
|
/* Encoder state.
|
||||||
*/
|
*/
|
||||||
@ -109,9 +117,6 @@ vips_foreign_save_jxl_error( VipsForeignSaveJxl *jxl, const char *details )
|
|||||||
vips_error( class->nickname, "%s", details );
|
vips_error( class->nickname, "%s", details );
|
||||||
}
|
}
|
||||||
|
|
||||||
static JxlPixelFormat vips_foreign_save_jxl_format =
|
|
||||||
{3, JXL_TYPE_FLOAT, JXL_NATIVE_ENDIAN, 0};
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
vips_foreign_save_jxl_build( VipsObject *object )
|
vips_foreign_save_jxl_build( VipsObject *object )
|
||||||
{
|
{
|
||||||
@ -136,32 +141,120 @@ vips_foreign_save_jxl_build( VipsObject *object )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch( save->ready->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
jxl->info.bits_per_sample = 8;
|
||||||
|
jxl->info.exponent_bits_per_sample = 0;
|
||||||
|
jxl->format.data_type = JXL_TYPE_UINT8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
jxl->info.bits_per_sample = 16;
|
||||||
|
jxl->info.exponent_bits_per_sample = 0;
|
||||||
|
jxl->format.data_type = JXL_TYPE_UINT16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
jxl->info.bits_per_sample = 32;
|
||||||
|
jxl->info.exponent_bits_per_sample = 0;
|
||||||
|
jxl->format.data_type = JXL_TYPE_UINT32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_FLOAT:
|
||||||
|
jxl->info.bits_per_sample = 32;
|
||||||
|
jxl->info.exponent_bits_per_sample = 8;
|
||||||
|
jxl->format.data_type = JXL_TYPE_FLOAT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch( save->ready->Type ) {
|
||||||
|
case VIPS_INTERPRETATION_B_W:
|
||||||
|
case VIPS_INTERPRETATION_GREY16:
|
||||||
|
jxl->info.num_color_channels = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_INTERPRETATION_sRGB:
|
||||||
|
case VIPS_INTERPRETATION_scRGB:
|
||||||
|
case VIPS_INTERPRETATION_RGB16:
|
||||||
|
jxl->info.num_color_channels = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
jxl->info.num_color_channels = save->ready->Bands;
|
||||||
|
}
|
||||||
|
jxl->info.num_extra_channels = VIPS_MAX( 0,
|
||||||
|
save->ready->Bands - jxl->info.num_color_channels );
|
||||||
|
|
||||||
jxl->info.xsize = save->ready->Xsize;
|
jxl->info.xsize = save->ready->Xsize;
|
||||||
jxl->info.ysize = save->ready->Ysize;
|
jxl->info.ysize = save->ready->Ysize;
|
||||||
jxl->info.bits_per_sample = 32;
|
jxl->format.num_channels = save->ready->Bands;
|
||||||
jxl->info.exponent_bits_per_sample = 8;
|
jxl->format.endianness = JXL_NATIVE_ENDIAN;
|
||||||
jxl->info.alpha_exponent_bits = 0;
|
jxl->format.align = 0;
|
||||||
jxl->info.alpha_bits = 0;
|
|
||||||
|
if( vips_image_hasalpha( save->ready ) ) {
|
||||||
|
jxl->info.alpha_bits = jxl->info.bits_per_sample;
|
||||||
|
jxl->info.alpha_exponent_bits =
|
||||||
|
jxl->info.exponent_bits_per_sample;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
jxl->info.alpha_exponent_bits = 0;
|
||||||
|
jxl->info.alpha_bits = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( vips_image_get_typeof( save->ready, "stonits" ) ) {
|
||||||
|
double stonits;
|
||||||
|
|
||||||
|
if( vips_image_get_double( save->ready, "stonits", &stonits ) )
|
||||||
|
return( -1 );
|
||||||
|
jxl->info.intensity_target = stonits;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME libjxl doesn't seem to have this API yet.
|
||||||
|
*
|
||||||
|
if( vips_image_get_typeof( save->ready, VIPS_META_ICC_NAME ) ) {
|
||||||
|
const void *data;
|
||||||
|
size_t length;
|
||||||
|
|
||||||
|
if( vips_image_get_blob( save->ready,
|
||||||
|
VIPS_META_ICC_NAME, &data, &length ) )
|
||||||
|
return( -1 );
|
||||||
|
|
||||||
|
jxl->info.uses_original_profile = JXL_TRUE;
|
||||||
|
... attach profile
|
||||||
|
}
|
||||||
|
else
|
||||||
|
jxl->info.uses_original_profile = JXL_FALSE;
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Remove this when libjxl gets API to attach an ICC profile.
|
||||||
|
*/
|
||||||
jxl->info.uses_original_profile = JXL_FALSE;
|
jxl->info.uses_original_profile = JXL_FALSE;
|
||||||
|
|
||||||
if( JxlEncoderSetBasicInfo( jxl->encoder, &jxl->info ) ) {
|
if( JxlEncoderSetBasicInfo( jxl->encoder, &jxl->info ) ) {
|
||||||
vips_foreign_save_jxl_error( jxl, "JxlEncoderSetBasicInfo" );
|
vips_foreign_save_jxl_error( jxl, "JxlEncoderSetBasicInfo" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
JxlColorEncodingSetToSRGB( &jxl->color_encoding,
|
JxlColorEncodingSetToSRGB( &jxl->color_encoding,
|
||||||
vips_foreign_save_jxl_format.num_channels < 3 );
|
jxl->format.num_channels < 3 );
|
||||||
if( JxlEncoderSetColorEncoding( jxl->encoder, &jxl->color_encoding ) ) {
|
if( JxlEncoderSetColorEncoding( jxl->encoder, &jxl->color_encoding ) ) {
|
||||||
vips_foreign_save_jxl_error( jxl,
|
vips_foreign_save_jxl_error( jxl,
|
||||||
"JxlEncoderSetColorEncoding" );
|
"JxlEncoderSetColorEncoding" );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Render the entire image in memory. libjxl seems to be missing
|
||||||
|
* tile-based write.
|
||||||
|
*/
|
||||||
if( vips_image_wio_input( save->ready ) )
|
if( vips_image_wio_input( save->ready ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
encoder_options = JxlEncoderOptionsCreate( jxl->encoder, NULL );
|
encoder_options = JxlEncoderOptionsCreate( jxl->encoder, NULL );
|
||||||
if( JxlEncoderAddImageFrame( encoder_options,
|
if( JxlEncoderAddImageFrame( encoder_options, &jxl->format,
|
||||||
&vips_foreign_save_jxl_format,
|
|
||||||
VIPS_IMAGE_ADDR( save->ready, 0, 0 ),
|
VIPS_IMAGE_ADDR( save->ready, 0, 0 ),
|
||||||
VIPS_IMAGE_SIZEOF_IMAGE( save->ready ) ) ) {
|
VIPS_IMAGE_SIZEOF_IMAGE( save->ready ) ) ) {
|
||||||
vips_foreign_save_jxl_error( jxl, "JxlEncoderAddImageFrame" );
|
vips_foreign_save_jxl_error( jxl, "JxlEncoderAddImageFrame" );
|
||||||
@ -197,13 +290,18 @@ vips_foreign_save_jxl_build( VipsObject *object )
|
|||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save a bit of typing.
|
||||||
|
*/
|
||||||
|
#define UC VIPS_FORMAT_UCHAR
|
||||||
|
#define US VIPS_FORMAT_USHORT
|
||||||
|
#define UI VIPS_FORMAT_UINT
|
||||||
#define F VIPS_FORMAT_FLOAT
|
#define F VIPS_FORMAT_FLOAT
|
||||||
|
|
||||||
/* Type promotion for save ... just always go to uchar.
|
/* Type promotion for save ... unsigned ints + float + double.
|
||||||
*/
|
*/
|
||||||
static int bandfmt_jpeg[10] = {
|
static int bandfmt_jpeg[10] = {
|
||||||
/* UC C US S UI I F X D DX */
|
/* UC C US S UI I F X D DX */
|
||||||
F, F, F, F, F, F, F, F, F, F
|
UC, UC, US, US, UI, UI, F, F, F, F
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user