diff options
Diffstat (limited to 'coders/jxl.c')
-rw-r--r-- | coders/jxl.c | 120 |
1 files changed, 91 insertions, 29 deletions
diff --git a/coders/jxl.c b/coders/jxl.c index d3450061a..c9c16b3da 100644 --- a/coders/jxl.c +++ b/coders/jxl.c @@ -52,12 +52,14 @@ #include "MagickCore/memory_.h" #include "MagickCore/monitor.h" #include "MagickCore/monitor-private.h" +#include "MagickCore/resource_.h" #include "MagickCore/static.h" #include "MagickCore/string_.h" #include "MagickCore/module.h" #if defined(MAGICKCORE_JXL_DELEGATE) #include <jxl/decode.h> #include <jxl/encode.h> +#include <jxl/thread_parallel_runner.h> #endif /* @@ -205,6 +207,9 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) *input_buffer, *output_buffer; + void + *runner; + /* Open image file. */ @@ -226,52 +231,70 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) decoder=JxlDecoderCreate(&memory_manager); if (decoder == (JxlDecoder *) NULL) ThrowReaderException(CoderError,"MemoryAllocationFailed"); + runner=JxlThreadParallelRunnerCreate(NULL,(size_t) GetMagickResourceLimit( + ThreadResource)); + if (runner == (void *) NULL) + { + JxlDecoderDestroy(decoder); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); + } + decoder_status=JxlDecoderSetParallelRunner(decoder,JxlThreadParallelRunner, + runner); + if (decoder_status != JXL_DEC_SUCCESS) + { + JxlThreadParallelRunnerDestroy(runner); + JxlDecoderDestroy(decoder); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); + } events_wanted=JXL_DEC_BASIC_INFO; if (image_info->ping == MagickFalse) events_wanted|=JXL_DEC_FULL_IMAGE | JXL_DEC_COLOR_ENCODING; if (JxlDecoderSubscribeEvents(decoder,events_wanted) != JXL_DEC_SUCCESS) { + JxlThreadParallelRunnerDestroy(runner); JxlDecoderDestroy(decoder); ThrowReaderException(CoderError,"UnableToReadImageData"); } - input_buffer=AcquireQuantumMemory(MagickMaxBufferExtent, - sizeof(*input_buffer)); + input_size=MagickMaxBufferExtent; + input_buffer=AcquireQuantumMemory(input_size,sizeof(*input_buffer)); if (input_buffer == (unsigned char *) NULL) { + JxlThreadParallelRunnerDestroy(runner); JxlDecoderDestroy(decoder); ThrowReaderException(CoderError,"MemoryAllocationFailed"); } output_buffer=(unsigned char *) NULL; memset(&format,0,sizeof(format)); - input_size=0; decoder_status=JXL_DEC_NEED_MORE_INPUT; while ((decoder_status != JXL_DEC_SUCCESS) && (decoder_status != JXL_DEC_ERROR)) { - const uint8_t - *p; - - size_t - size; - - size=input_size; - p=input_buffer; - decoder_status=JxlDecoderProcessInput(decoder,&p,&input_size); - if ((input_size > 0) && ((size-input_size) > 0)) - (void) memmove(input_buffer,input_buffer+(size-input_size),input_size); + decoder_status=JxlDecoderProcessInput(decoder); switch (decoder_status) { case JXL_DEC_NEED_MORE_INPUT: { - input_size+=ReadBlob(image,MagickMaxBufferExtent-input_size, - input_buffer+input_size); - if (input_size == 0) + size_t + remaining; + + ssize_t + count; + + remaining=JxlDecoderReleaseInput(decoder); + if (remaining > 0) + memmove(input_buffer,input_buffer+input_size-remaining,remaining); + count=ReadBlob(image,input_size-remaining,input_buffer+remaining); + if (count <= 0) { decoder_status=JXL_DEC_SUCCESS; ThrowMagickException(exception,GetMagickModule(),CoderError, "InsufficientImageDataInFile","`%s'",image->filename); break; } + decoder_status=JxlDecoderSetInput(decoder,(const uint8_t *) input_buffer, + (size_t) count); + if (decoder_status == JXL_DEC_SUCCESS) + decoder_status=JXL_DEC_NEED_MORE_INPUT; break; } case JXL_DEC_BASIC_INFO: @@ -315,9 +338,8 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) decoder_status=JxlDecoderGetColorAsICCProfile(decoder,&format, JXL_COLOR_PROFILE_TARGET_ORIGINAL,GetStringInfoDatum(profile), profile_size); - if (decoder_status != JXL_DEC_SUCCESS) - break; - decoder_status=JXL_DEC_COLOR_ENCODING; + if (decoder_status == JXL_DEC_SUCCESS) + decoder_status=JXL_DEC_COLOR_ENCODING; break; } case JXL_DEC_NEED_IMAGE_OUT_BUFFER: @@ -342,11 +364,11 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) } decoder_status=JxlDecoderSetImageOutBuffer(decoder,&format, output_buffer,output_size); - if (decoder_status != JXL_DEC_SUCCESS) - break; - decoder_status=JXL_DEC_NEED_IMAGE_OUT_BUFFER; + if (decoder_status == JXL_DEC_SUCCESS) + decoder_status=JXL_DEC_NEED_IMAGE_OUT_BUFFER; } case JXL_DEC_FULL_IMAGE: + { if (output_buffer == (unsigned char *) NULL) { ThrowMagickException(exception,GetMagickModule(),CorruptImageError, @@ -360,6 +382,7 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) if (status == MagickFalse) decoder_status=JXL_DEC_ERROR; break; + } case JXL_DEC_SUCCESS: case JXL_DEC_ERROR: break; @@ -370,6 +393,7 @@ static Image *ReadJXLImage(const ImageInfo *image_info,ExceptionInfo *exception) } output_buffer=(unsigned char *) RelinquishMagickMemory(output_buffer); input_buffer=(unsigned char *) RelinquishMagickMemory(input_buffer); + JxlThreadParallelRunnerDestroy(runner); JxlDecoderDestroy(decoder); if (decoder_status == JXL_DEC_ERROR) ThrowReaderException(CorruptImageError,"UnableToReadImageData"); @@ -470,6 +494,9 @@ ModuleExport void UnregisterJXLImage(void) static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, ExceptionInfo *exception) { + JxlBasicInfo + basic_info; + JxlEncoder *encoder; @@ -497,6 +524,9 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, unsigned char *input_buffer; + void + *runner; + /* Open output image file. */ @@ -515,19 +545,47 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, encoder=JxlEncoderCreate(&memory_manager); if (encoder == (JxlEncoder *) NULL) ThrowWriterException(CoderError,"MemoryAllocationFailed"); + runner=JxlThreadParallelRunnerCreate(NULL,(size_t) GetMagickResourceLimit( + ThreadResource)); + if (runner == (void *) NULL) + { + JxlEncoderDestroy(encoder); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); + } + encoder_status=JxlEncoderSetParallelRunner(encoder,JxlThreadParallelRunner, + runner); + if (encoder_status != JXL_ENC_SUCCESS) + { + JxlThreadParallelRunnerDestroy(runner); + JxlEncoderDestroy(encoder); + return(MagickFalse); + } memset(&format,0,sizeof(format)); JXLSetFormat(image,&format); - encoder_status=JxlEncoderSetDimensions(encoder,image->columns,image->rows); + memset(&basic_info,0,sizeof(basic_info)); + basic_info.xsize=(uint32_t) image->columns; + basic_info.ysize=(uint32_t) image->rows; + basic_info.bits_per_sample=8; + if (format.data_type == JXL_TYPE_FLOAT) + { + basic_info.bits_per_sample=32; + basic_info.exponent_bits_per_sample=8; + } + if (image->alpha_trait == BlendPixelTrait) + basic_info.alpha_bits=basic_info.bits_per_sample; + encoder_status=JxlEncoderSetBasicInfo(encoder,&basic_info); if (encoder_status != JXL_ENC_SUCCESS) { + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); - return(MagickFalse); + ThrowWriterException(CoderError,"UnableToWriteImageData"); } encoder_options=JxlEncoderOptionsCreate(encoder,(JxlEncoderOptions *) NULL); if (encoder_options == (JxlEncoderOptions *) NULL) { + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); - return(MagickFalse); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); } if (image->quality == 100) JxlEncoderOptionsSetLossless(encoder_options,JXL_TRUE); @@ -538,8 +596,9 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, sizeof(*input_buffer)); if (input_buffer == (unsigned char *) NULL) { + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); - return(MagickFalse); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); } status=ExportImagePixels(image,0,0,image->columns,image->rows, image->alpha_trait == BlendPixelTrait ? "RGBA" : "RGB", @@ -548,8 +607,9 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, if (status == MagickFalse) { input_buffer=(unsigned char *) RelinquishMagickMemory(input_buffer); + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); - return(MagickFalse); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); } encoder_status=JxlEncoderAddImageFrame(encoder_options,&format,input_buffer, bytes_per_row*image->rows); @@ -563,8 +623,9 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, if (output_buffer == (unsigned char *) NULL) { input_buffer=(unsigned char *) RelinquishMagickMemory(input_buffer); + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); - return(MagickFalse); + ThrowWriterException(CoderError,"MemoryAllocationFailed"); } encoder_status=JXL_ENC_NEED_MORE_OUTPUT; while (encoder_status == JXL_ENC_NEED_MORE_OUTPUT) @@ -583,6 +644,7 @@ static MagickBooleanType WriteJXLImage(const ImageInfo *image_info,Image *image, output_buffer=(unsigned char *) RelinquishMagickMemory(output_buffer); } input_buffer=(unsigned char *) RelinquishMagickMemory(input_buffer); + JxlThreadParallelRunnerDestroy(runner); JxlEncoderDestroy(encoder); if (encoder_status != JXL_ENC_SUCCESS) ThrowWriterException(CoderError,"UnableToWriteImageData"); |