From e077beee2df94e47501ab707779d974f4bf50a09 Mon Sep 17 00:00:00 2001 From: Dirk Lemstra Date: Fri, 14 Jun 2019 11:53:45 +0200 Subject: [PATCH] Refactored the code to prepare for reading all images from a HEIC image. --- coders/heic.c | 268 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 159 insertions(+), 109 deletions(-) diff --git a/coders/heic.c b/coders/heic.c index a0c0c2547..5b16a9ef3 100644 --- a/coders/heic.c +++ b/coders/heic.c @@ -136,102 +136,12 @@ static MagickBooleanType IsHeifSuccess(struct heif_error *error,Image *image, ThrowBinaryException(CorruptImageError,error->message,image->filename); } -static Image *ReadHEICImage(const ImageInfo *image_info, - ExceptionInfo *exception) +static MagickBooleanType ReadHEICColorProfile(Image *image, + struct heif_image_handle *image_handle,ExceptionInfo *exception) { - const char - *option; - - const StringInfo - *profile; - - heif_item_id - exif_id; - - Image - *image; - - int - count, - stride_y, - stride_cb, - stride_cr; - - MagickBooleanType - status; - size_t length; - ssize_t - y; - - struct heif_context - *heif_context; - - struct heif_decoding_options - *decode_options; - - struct heif_error - error; - - struct heif_image - *heif_image; - - struct heif_image_handle - *image_handle; - - uint8_t - *p_y, - *p_cb, - *p_cr; - - void - *file_data; - - /* - Open image file. - */ - assert(image_info != (const ImageInfo *) NULL); - assert(image_info->signature == MagickCoreSignature); - if (image_info->debug != MagickFalse) - (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", - image_info->filename); - assert(exception != (ExceptionInfo *) NULL); - assert(exception->signature == MagickCoreSignature); - image=AcquireImage(image_info,exception); - status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); - if (status == MagickFalse) - return(DestroyImageList(image)); - if (GetBlobSize(image) > (MagickSizeType) SSIZE_MAX) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - length=(size_t) GetBlobSize(image); - file_data=AcquireMagickMemory(length); - if (file_data == (void *) NULL) - ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); - if (ReadBlob(image,length,file_data) != (ssize_t) length) - { - file_data=RelinquishMagickMemory(file_data); - ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); - } - /* - Decode HEIF file - */ - heif_context=heif_context_alloc(); - error=heif_context_read_from_memory(heif_context,file_data,length,NULL); - file_data=RelinquishMagickMemory(file_data); - if (IsHeifSuccess(&error,image,exception) == MagickFalse) - { - heif_context_free(heif_context); - return(DestroyImageList(image)); - } - image_handle=(struct heif_image_handle *) NULL; - error=heif_context_get_primary_image_handle(heif_context,&image_handle); - if (IsHeifSuccess(&error,image,exception) == MagickFalse) - { - heif_context_free(heif_context); - return(DestroyImageList(image)); - } #if LIBHEIF_NUMERIC_VERSION >= 0x01040000 length=heif_image_handle_get_raw_color_profile_size(image_handle); if (length > 0) @@ -243,14 +153,14 @@ static Image *ReadHEICImage(const ImageInfo *image_info, Read color profile. */ if ((MagickSizeType) length > GetBlobSize(image)) - { - heif_image_handle_release(image_handle); - heif_context_free(heif_context); - ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); - } + ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile", + image->filename); color_buffer=(unsigned char *) AcquireMagickMemory(length); if (color_buffer != (unsigned char *) NULL) { + struct heif_error + error; + error=heif_image_handle_get_raw_color_profile(image_handle, color_buffer); if (error.code == 0) @@ -269,6 +179,18 @@ static Image *ReadHEICImage(const ImageInfo *image_info, color_buffer=(unsigned char *) RelinquishMagickMemory(color_buffer); } #endif + return(MagickTrue); +} + +static MagickBooleanType ReadHEICExifProfile(Image *image, + struct heif_image_handle *image_handle,ExceptionInfo *exception) +{ + heif_item_id + exif_id; + + int + count; + count=heif_image_handle_get_list_of_metadata_block_IDs(image_handle,"Exif", &exif_id,1); if (count > 0) @@ -284,14 +206,14 @@ static Image *ReadHEICImage(const ImageInfo *image_info, */ exif_size=heif_image_handle_get_metadata_size(image_handle,exif_id); if ((MagickSizeType) exif_size > GetBlobSize(image)) - { - heif_image_handle_release(image_handle); - heif_context_free(heif_context); - ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); - } + ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile", + image->filename); exif_buffer=(unsigned char *) AcquireMagickMemory(exif_size); if (exif_buffer != (unsigned char *) NULL) { + struct heif_error + error; + error=heif_image_handle_get_metadata(image_handle, exif_id,exif_buffer); if (error.code == 0) @@ -315,6 +237,60 @@ static Image *ReadHEICImage(const ImageInfo *image_info, } exif_buffer=(unsigned char *) RelinquishMagickMemory(exif_buffer); } + return(MagickTrue); +} + +static MagickBooleanType ReadHEICImageByID(const ImageInfo *image_info, + Image *image,struct heif_context *heif_context,heif_item_id image_id, + ExceptionInfo *exception) +{ + const char + *option; + + const StringInfo + *profile; + + int + stride_y, + stride_cb, + stride_cr; + + MagickBooleanType + status; + + ssize_t + y; + + struct heif_decoding_options + *decode_options; + + struct heif_error + error; + + struct heif_image + *heif_image; + + struct heif_image_handle + *image_handle; + + uint8_t + *p_y, + *p_cb, + *p_cr; + + error=heif_context_get_image_handle(heif_context,image_id,&image_handle); + if (IsHeifSuccess(&error,image,exception) == MagickFalse) + return(MagickFalse); + if (ReadHEICColorProfile(image,image_handle,exception) == MagickFalse) + { + heif_image_handle_release(image_handle); + return(MagickFalse); + } + if (ReadHEICExifProfile(image,image_handle,exception) == MagickFalse) + { + heif_image_handle_release(image_handle); + return(MagickFalse); + } /* Set image size. */ @@ -324,16 +300,17 @@ static Image *ReadHEICImage(const ImageInfo *image_info, if (image_info->ping != MagickFalse) { image->colorspace=YCbCrColorspace; + profile=GetImageProfile(image,"icc"); + if (profile != (const StringInfo *) NULL) + image->colorspace=sRGBColorspace; heif_image_handle_release(image_handle); - heif_context_free(heif_context); - return(GetFirstImageInList(image)); + return(MagickTrue); } status=SetImageExtent(image,image->columns,image->rows,exception); if (status == MagickFalse) { heif_image_handle_release(image_handle); - heif_context_free(heif_context); - return(DestroyImageList(image)); + return(MagickFalse); } /* Copy HEIF image into ImageMagick data structures. @@ -363,9 +340,9 @@ static Image *ReadHEICImage(const ImageInfo *image_info, if ((IsHeifSuccess(&error,image,exception) == MagickFalse) || (status == MagickFalse)) { + heif_image_release(heif_image); heif_image_handle_release(image_handle); - heif_context_free(heif_context); - return(DestroyImageList(image)); + return(MagickFalse); } p_y=heif_image_get_plane(heif_image,heif_channel_Y,&stride_y); p_cb=heif_image_get_plane(heif_image,heif_channel_Cb,&stride_cb); @@ -396,10 +373,83 @@ static Image *ReadHEICImage(const ImageInfo *image_info, } heif_image_release(heif_image); heif_image_handle_release(image_handle); - heif_context_free(heif_context); profile=GetImageProfile(image,"icc"); if (profile != (const StringInfo *) NULL) (void) TransformImageColorspace(image,sRGBColorspace,exception); + return(MagickTrue); +} + +static Image *ReadHEICImage(const ImageInfo *image_info, + ExceptionInfo *exception) +{ + heif_item_id + primary_image_id; + + Image + *image; + + MagickBooleanType + status; + + size_t + length; + + struct heif_context + *heif_context; + + struct heif_error + error; + + void + *file_data; + + /* + Open image file. + */ + assert(image_info != (const ImageInfo *) NULL); + assert(image_info->signature == MagickCoreSignature); + if (image_info->debug != MagickFalse) + (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", + image_info->filename); + assert(exception != (ExceptionInfo *) NULL); + assert(exception->signature == MagickCoreSignature); + image=AcquireImage(image_info,exception); + status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); + if (status == MagickFalse) + return(DestroyImageList(image)); + if (GetBlobSize(image) > (MagickSizeType) SSIZE_MAX) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + length=(size_t) GetBlobSize(image); + file_data=AcquireMagickMemory(length); + if (file_data == (void *) NULL) + ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); + if (ReadBlob(image,length,file_data) != (ssize_t) length) + { + file_data=RelinquishMagickMemory(file_data); + ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile"); + } + /* + Decode HEIF file + */ + heif_context=heif_context_alloc(); + error=heif_context_read_from_memory(heif_context,file_data,length,NULL); + file_data=RelinquishMagickMemory(file_data); + if (IsHeifSuccess(&error,image,exception) == MagickFalse) + { + heif_context_free(heif_context); + return(DestroyImageList(image)); + } + error=heif_context_get_primary_image_ID(heif_context,&primary_image_id); + if (IsHeifSuccess(&error,image,exception) == MagickFalse) + { + heif_context_free(heif_context); + return(DestroyImageList(image)); + } + status=ReadHEICImageByID(image_info,image,heif_context,primary_image_id, + exception); + heif_context_free(heif_context); + if (status == MagickFalse) + return(DestroyImageList(image)); return(GetFirstImageInList(image)); } #endif -- 2.40.0