This commit is contained in:
John Cupitt 2021-04-01 16:54:42 +01:00
parent 2a249a3049
commit 950606406f
5 changed files with 38 additions and 48 deletions

View File

@ -776,7 +776,7 @@ AC_ARG_WITH([libjxl],
[build without libjxl (default: test)])) [build without libjxl (default: test)]))
if test x"$with_libjxl" != x"no"; then if test x"$with_libjxl" != x"no"; then
PKG_CHECK_MODULES(LIBJXL, libjxl >= 0.3.7, PKG_CHECK_MODULES(LIBJXL, libjxl_threads >= 0.3.7 libjxl >= 0.3.7,
[AC_DEFINE(HAVE_LIBJXL,1, [AC_DEFINE(HAVE_LIBJXL,1,
[define if you have libjxl >=2.2 installed.]) [define if you have libjxl >=2.2 installed.])
with_libjxl=yes with_libjxl=yes

View File

@ -19,7 +19,7 @@ libforeign_la_SOURCES = \
foreign.c \ foreign.c \
heifload.c \ heifload.c \
heifsave.c \ heifsave.c \
jxlload.cpp \ jxlload.c \
jp2kload.c \ jp2kload.c \
jp2ksave.c \ jp2ksave.c \
jpeg2vips.c \ jpeg2vips.c \

View File

@ -1396,7 +1396,7 @@ vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
} }
/* If this is something other than CMYK or RAD, and it's not already /* If this is something other than CMYK or RAD, and it's not already
* an RGB image, eg. maybe a LAB or scRGB image, we need to transform * an RGB image, eg. maybe a LAB image, we need to transform
* to RGB. * to RGB.
*/ */
if( !coding[VIPS_CODING_RAD] && if( !coding[VIPS_CODING_RAD] &&
@ -1404,6 +1404,7 @@ vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
in->Type != VIPS_INTERPRETATION_CMYK && in->Type != VIPS_INTERPRETATION_CMYK &&
in->Type != VIPS_INTERPRETATION_sRGB && in->Type != VIPS_INTERPRETATION_sRGB &&
in->Type != VIPS_INTERPRETATION_RGB16 && in->Type != VIPS_INTERPRETATION_RGB16 &&
in->Type != VIPS_INTERPRETATION_scRGB &&
vips_colourspace_issupported( in ) && vips_colourspace_issupported( in ) &&
(saveable == VIPS_SAVEABLE_RGB || (saveable == VIPS_SAVEABLE_RGB ||
saveable == VIPS_SAVEABLE_RGBA || saveable == VIPS_SAVEABLE_RGBA ||

View File

@ -52,9 +52,7 @@
#ifdef HAVE_LIBJXL #ifdef HAVE_LIBJXL
#include <jxl/decode.h> #include <jxl/decode.h>
#include <jxl/decode_cxx.h>
#include <jxl/thread_parallel_runner.h> #include <jxl/thread_parallel_runner.h>
#include <jxl/thread_parallel_runner_cxx.h>
#include "pforeign.h" #include "pforeign.h"
@ -80,7 +78,7 @@ typedef struct _VipsForeignLoadJxl {
/* Decompress state. /* Decompress state.
*/ */
JxlThreadParallelRunner *runner; void *runner;
JxlDecoder *decoder; JxlDecoder *decoder;
/* Our input buffer. /* Our input buffer.
@ -104,12 +102,8 @@ typedef struct _VipsForeignLoadJxl {
typedef VipsForeignLoadClass VipsForeignLoadJxlClass; typedef VipsForeignLoadClass VipsForeignLoadJxlClass;
/* We need C linkage for this.
*/
extern "C" {
G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadJxl, vips_foreign_load_jxl, G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadJxl, vips_foreign_load_jxl,
VIPS_TYPE_FOREIGN_LOAD ); VIPS_TYPE_FOREIGN_LOAD );
}
static void static void
vips_foreign_load_jxl_dispose( GObject *gobject ) vips_foreign_load_jxl_dispose( GObject *gobject )
@ -131,7 +125,7 @@ vips_foreign_load_jxl_dispose( GObject *gobject )
static void static void
vips_foreign_load_jxl_error( VipsForeignLoadJxl *jxl, const char *details ) vips_foreign_load_jxl_error( VipsForeignLoadJxl *jxl, const char *details )
{ {
VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( object ); VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( jxl );
/* TODO ... jxl has no way to get error messages at the moemnt. /* TODO ... jxl has no way to get error messages at the moemnt.
*/ */
@ -143,15 +137,13 @@ vips_foreign_load_jxl_build( VipsObject *object )
{ {
VipsForeignLoadJxl *jxl = (VipsForeignLoadJxl *) object; VipsForeignLoadJxl *jxl = (VipsForeignLoadJxl *) object;
JxlDecoderStatus status;
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_load_jxl_build:\n" ); printf( "vips_foreign_load_jxl_build:\n" );
#endif /*DEBUG*/ #endif /*DEBUG*/
jxl->runner = JxlThreadParallelRunnerCreate( nullptr, jxl->runner = JxlThreadParallelRunnerCreate( NULL,
vips_concurrency_get() ); vips_concurrency_get() );
jxl->decoder = JxlDecoderCreate( nullptr ); jxl->decoder = JxlDecoderCreate( NULL );
/* We are only interested in end of header and end of pixel data. /* We are only interested in end of header and end of pixel data.
*/ */
@ -175,6 +167,22 @@ vips_foreign_load_jxl_build( VipsObject *object )
return( 0 ); return( 0 );
} }
static gboolean
vips_foreign_load_jxl_is_a_source( VipsSource *source )
{
const unsigned char *p;
JxlSignature sig;
return( (p = vips_source_sniff( source, 12 )) &&
(sig = JxlSignatureCheck( p, 12 )) == JXL_SIG_CONTAINER );
}
static VipsForeignFlags
vips_foreign_load_jxl_get_flags( VipsForeignLoad *load )
{
return( VIPS_FOREIGN_PARTIAL );
}
/* Always read as scRGBA. /* Always read as scRGBA.
*/ */
static JxlPixelFormat vips_foreign_load_jxl_format = static JxlPixelFormat vips_foreign_load_jxl_format =
@ -190,14 +198,15 @@ vips_foreign_load_jxl_set_header( VipsForeignLoadJxl *jxl, VipsImage *out )
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ); vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
vips_image_init_fields( out, vips_image_init_fields( out,
jxl->info.width, jxl->info.height, 4, VIPS_FORMAT_FLOAT, jxl->info.xsize, jxl->info.ysize, 4, VIPS_FORMAT_FLOAT,
VIPS_CODING_NONE, VIPS_INTERPRETATION_scRGB, 1.0, 1.0 ); VIPS_CODING_NONE, VIPS_INTERPRETATION_scRGB, 1.0, 1.0 );
if( jxl->icc_data && if( jxl->icc_data &&
jxl->icc_size > 0 ) { jxl->icc_size > 0 ) {
vips_image_set_blob( out, VIPS_META_ICC_NAME, vips_free, vips_image_set_blob( out, VIPS_META_ICC_NAME,
(VipsCallbackFn) vips_area_free_cb,
jxl->icc_data, jxl->icc_size ); jxl->icc_data, jxl->icc_size );
jxl->icc_data = nullptr; jxl->icc_data = NULL;
jxl->icc_size = 0; jxl->icc_size = 0;
} }
@ -297,7 +306,7 @@ vips_foreign_load_jxl_process( VipsForeignLoadJxl *jxl )
{ {
JxlDecoderStatus status; JxlDecoderStatus status;
while( (status = JxlDecoderProcessInput( jx->decoder )) == while( (status = JxlDecoderProcessInput( jxl->decoder )) ==
JXL_DEC_NEED_MORE_INPUT ) { JXL_DEC_NEED_MORE_INPUT ) {
size_t unused; size_t unused;
@ -306,7 +315,7 @@ vips_foreign_load_jxl_process( VipsForeignLoadJxl *jxl )
unused == 0 ) unused == 0 )
return( JXL_DEC_ERROR ); return( JXL_DEC_ERROR );
JxlDecoderSetInput( jxl->decoder, JxlDecoderSetInput( jxl->decoder,
jxl->input_buffer, jxl->bytes_remaining ); jxl->input_buffer, jxl->bytes_in_buffer );
} }
printf( "vips_foreign_load_jxl_process: seen " ); printf( "vips_foreign_load_jxl_process: seen " );
@ -318,7 +327,6 @@ vips_foreign_load_jxl_process( VipsForeignLoadJxl *jxl )
static int static int
vips_foreign_load_jxl_header( VipsForeignLoad *load ) vips_foreign_load_jxl_header( VipsForeignLoad *load )
{ {
VipsObjectClass *klass = VIPS_OBJECT_GET_CLASS( load );
VipsForeignLoadJxl *jxl = (VipsForeignLoadJxl *) load; VipsForeignLoadJxl *jxl = (VipsForeignLoadJxl *) load;
JxlDecoderStatus status; JxlDecoderStatus status;
@ -327,20 +335,10 @@ vips_foreign_load_jxl_header( VipsForeignLoad *load )
printf( "vips_foreign_load_jxl_header:\n" ); printf( "vips_foreign_load_jxl_header:\n" );
#endif /*DEBUG*/ #endif /*DEBUG*/
/* Even though this is a full image reader, we hint thinstrip since
* we are quite happy serving that if anything downstream
* would like it.
*/
vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL );
vips_image_init_fields( out,
jxl->info.width, first->h, jxl->image->numcomps, format,
VIPS_CODING_NONE, interpretation, 1.0, 1.0 );
if( vips_foreign_load_jxl_fill_input( jxl, 0 ) ) if( vips_foreign_load_jxl_fill_input( jxl, 0 ) )
return( -1 ); return( -1 );
JxlDecoderSetInput( jx->decoder, JxlDecoderSetInput( jxl->decoder,
jxl->input_buffer, jxl->bytes_remaining ); jxl->input_buffer, jxl->bytes_in_buffer );
/* Read to the end of the header. /* Read to the end of the header.
*/ */
@ -369,11 +367,13 @@ vips_foreign_load_jxl_header( VipsForeignLoad *load )
"JxlDecoderGetICCProfileSize" ); "JxlDecoderGetICCProfileSize" );
return( -1 ); return( -1 );
} }
if( !(jxl->icc_data = vips_malloc( nullptr, if( !(jxl->icc_data = vips_malloc( NULL,
jxl->icc_size )) ) jxl->icc_size )) )
return( -1 ); return( -1 );
if( JxlDecoderGetColorAsICCProfile(
jxl->decoder,
if( JxlDecoderGetColorAsICCProfile( jxl->decoder,
&vips_foreign_load_jxl_format,
JXL_COLOR_PROFILE_TARGET_DATA, JXL_COLOR_PROFILE_TARGET_DATA,
jxl->icc_data, jxl->icc_size ) ) { jxl->icc_data, jxl->icc_size ) ) {
vips_foreign_load_jxl_error( jxl, vips_foreign_load_jxl_error( jxl,
@ -455,12 +455,8 @@ typedef struct _VipsForeignLoadJxlFile {
typedef VipsForeignLoadJxlClass VipsForeignLoadJxlFileClass; typedef VipsForeignLoadJxlClass VipsForeignLoadJxlFileClass;
/* We need C linkage for this.
*/
extern "C" {
G_DEFINE_TYPE( VipsForeignLoadJxlFile, vips_foreign_load_jxl_file, G_DEFINE_TYPE( VipsForeignLoadJxlFile, vips_foreign_load_jxl_file,
vips_foreign_load_jxl_get_type() ); vips_foreign_load_jxl_get_type() );
}
static int static int
vips_foreign_load_jxl_file_build( VipsObject *object ) vips_foreign_load_jxl_file_build( VipsObject *object )
@ -540,12 +536,8 @@ typedef struct _VipsForeignLoadJxlBuffer {
typedef VipsForeignLoadJxlClass VipsForeignLoadJxlBufferClass; typedef VipsForeignLoadJxlClass VipsForeignLoadJxlBufferClass;
/* We need C linkage for this.
*/
extern "C" {
G_DEFINE_TYPE( VipsForeignLoadJxlBuffer, vips_foreign_load_jxl_buffer, G_DEFINE_TYPE( VipsForeignLoadJxlBuffer, vips_foreign_load_jxl_buffer,
vips_foreign_load_jxl_get_type() ); vips_foreign_load_jxl_get_type() );
}
static int static int
vips_foreign_load_jxl_buffer_build( VipsObject *object ) vips_foreign_load_jxl_buffer_build( VipsObject *object )
@ -622,12 +614,8 @@ typedef struct _VipsForeignLoadJxlSource {
typedef VipsForeignLoadJxlClass VipsForeignLoadJxlSourceClass; typedef VipsForeignLoadJxlClass VipsForeignLoadJxlSourceClass;
/* We need C linkage for this.
*/
extern "C" {
G_DEFINE_TYPE( VipsForeignLoadJxlSource, vips_foreign_load_jxl_source, G_DEFINE_TYPE( VipsForeignLoadJxlSource, vips_foreign_load_jxl_source,
vips_foreign_load_jxl_get_type() ); vips_foreign_load_jxl_get_type() );
}
static int static int
vips_foreign_load_jxl_source_build( VipsObject *object ) vips_foreign_load_jxl_source_build( VipsObject *object )

View File

@ -327,6 +327,7 @@ vips_foreign_save_ppm_build( VipsObject *object )
*/ */
g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, scale ); g_ascii_dtostr( buf, G_ASCII_DTOSTR_BUF_SIZE, scale );
vips_target_writes( ppm->target, buf ); vips_target_writes( ppm->target, buf );
vips_target_writes( ppm->target, "\n" );
} }
break; break;