summaryrefslogtreecommitdiffstats
path: root/heif.patch
diff options
context:
space:
mode:
Diffstat (limited to 'heif.patch')
-rw-r--r--heif.patch1031
1 files changed, 45 insertions, 986 deletions
diff --git a/heif.patch b/heif.patch
index 315a301..086f28c 100644
--- a/heif.patch
+++ b/heif.patch
@@ -1,1005 +1,64 @@
-From 418e3f40dc7302dae664eaaf0ea4cd4b7b59f852 Mon Sep 17 00:00:00 2001
+From ffc2aaae543dcd60c6cc7e5a426f66dbc51df560 Mon Sep 17 00:00:00 2001
From: Cristy <urban-warrior@imagemagick.org>
-Date: Sat, 19 Mar 2022 11:26:52 -0400
-Subject: [PATCH] Coders: support 10-bit AVIF per
- https://github.com/ImageMagick/ImageMagick/discussions/4932
+Date: Mon, 21 Mar 2022 21:53:40 -0400
+Subject: [PATCH] https://github.com/ImageMagick/ImageMagick/issues/4972
---
- coders/heic.c | 606 ++++++++++++++++++++++++++++++++------------------
- 1 file changed, 388 insertions(+), 218 deletions(-)
+ coders/heic.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
diff --git a/coders/heic.c b/coders/heic.c
-index f7961b3a62..c85c214189 100644
+index 96b4e218fc..846f5c7575 100644
--- a/coders/heic.c
+++ b/coders/heic.c
-@@ -80,13 +80,13 @@
- #include <libheif/heif.h>
- #endif
- #endif
--
-+
- #if defined(MAGICKCORE_HEIC_DELEGATE)
- /*
- Define declarations.
- */
- #define XmpNamespaceExtent 28
--
-+
- /*
- Const declarations.
- */
-@@ -127,12 +127,14 @@ static MagickBooleanType
- %
- */
-
--static MagickBooleanType IsHeifSuccess(Image *image,struct heif_error *error,
-- ExceptionInfo *exception)
-+static inline MagickBooleanType IsHEIFSuccess(Image *image,
-+ struct heif_error *error,ExceptionInfo *exception)
- {
- if (error->code == 0)
- return(MagickTrue);
-- ThrowBinaryException(CorruptImageError,error->message,image->filename);
-+ (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError,
-+ error->message,"(%d.%d) `%s'",error->code,error->subcode,image->filename);
-+ return(MagickFalse);
- }
-
- static MagickBooleanType ReadHEICColorProfile(Image *image,
-@@ -142,41 +144,38 @@ static MagickBooleanType ReadHEICColorProfile(Image *image,
- size_t
- length;
-
-+ struct heif_error
-+ error;
-+
-+ unsigned char
-+ *color_profile;
-+
- /*
- Read color profile.
- */
- length=heif_image_handle_get_raw_color_profile_size(image_handle);
-- if (length > 0)
-+ if (length == 0)
-+ return(MagickTrue);
-+ if ((MagickSizeType) length > GetBlobSize(image))
-+ ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
-+ image->filename);
-+ color_profile=(unsigned char *) AcquireQuantumMemory(1,length);
-+ if (color_profile == (unsigned char *) NULL)
-+ return(MagickFalse);
-+ error=heif_image_handle_get_raw_color_profile(image_handle,color_profile);
-+ if (IsHEIFSuccess(image,&error,exception) != MagickFalse)
- {
-- unsigned char
-- *color_buffer;
--
-- if ((MagickSizeType) length > GetBlobSize(image))
-- ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
-- image->filename);
-- color_buffer=(unsigned char *) AcquireQuantumMemory(1,length);
-- if (color_buffer != (unsigned char *) NULL)
-- {
-- struct heif_error
-- error;
-+ StringInfo
-+ *profile;
-
-- error=heif_image_handle_get_raw_color_profile(image_handle,
-- color_buffer);
-- if (error.code == 0)
-- {
-- StringInfo
-- *profile;
--
-- profile=BlobToStringInfo(color_buffer,length);
-- if (profile != (StringInfo*) NULL)
-- {
-- (void) SetImageProfile(image,"icc",profile,exception);
-- profile=DestroyStringInfo(profile);
-- }
-- }
-+ profile=BlobToStringInfo(color_profile,length);
-+ if (profile != (StringInfo*) NULL)
-+ {
-+ (void) SetImageProfile(image,"icc",profile,exception);
-+ profile=DestroyStringInfo(profile);
- }
-- color_buffer=(unsigned char *) RelinquishMagickMemory(color_buffer);
- }
-+ color_profile=(unsigned char *) RelinquishMagickMemory(color_profile);
- #endif
- return(MagickTrue);
- }
-@@ -185,56 +184,53 @@ static MagickBooleanType ReadHEICExifProfile(Image *image,
- struct heif_image_handle *image_handle,ExceptionInfo *exception)
- {
- heif_item_id
-- exif_id;
-+ id;
-
- int
- count;
-
-+ size_t
-+ extent;
-+
-+ struct heif_error
-+ error;
-+
-+ unsigned char
-+ *exif_profile;
-+
- /*
- Read Exif profile.
- */
- count=heif_image_handle_get_list_of_metadata_block_IDs(image_handle,"Exif",
-- &exif_id,1);
-- if (count > 0)
-+ &id,1);
-+ if (count != 1)
-+ return(MagickTrue);
-+ extent=heif_image_handle_get_metadata_size(image_handle,id);
-+ if ((MagickSizeType) extent > GetBlobSize(image))
-+ ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
-+ image->filename);
-+ exif_profile=(unsigned char *) AcquireQuantumMemory(1,extent);
-+ if (exif_profile == (unsigned char *) NULL)
-+ return(MagickFalse);
-+ error=heif_image_handle_get_metadata(image_handle,id,exif_profile);
-+ if (IsHEIFSuccess(image,&error,exception) != MagickFalse)
- {
-- size_t
-- exif_size;
--
-- unsigned char
-- *exif_buffer;
--
-- exif_size=heif_image_handle_get_metadata_size(image_handle,exif_id);
-- if ((MagickSizeType) exif_size > GetBlobSize(image))
-- ThrowBinaryException(CorruptImageError,"InsufficientImageDataInFile",
-- image->filename);
-- exif_buffer=(unsigned char *) AcquireQuantumMemory(1,exif_size);
-- if (exif_buffer != (unsigned char *) NULL)
-+ StringInfo
-+ *profile;
-+
-+ /*
-+ Skip first 4 bytes, the offset to the TIFF header.
-+ */
-+ profile=(StringInfo*) NULL;
-+ if (extent > 8)
-+ profile=BlobToStringInfo(exif_profile+4,(size_t) extent-4);
-+ if (profile != (StringInfo*) NULL)
- {
-- struct heif_error
-- error;
--
-- error=heif_image_handle_get_metadata(image_handle,
-- exif_id,exif_buffer);
-- if (error.code == 0)
-- {
-- StringInfo
-- *profile;
--
-- /*
-- Skip first 4 bytes, the offset to the TIFF header.
-- */
-- profile=(StringInfo*) NULL;
-- if (exif_size > 8)
-- profile=BlobToStringInfo(exif_buffer+4,(size_t) exif_size-4);
-- if (profile != (StringInfo*) NULL)
-- {
-- (void) SetImageProfile(image,"exif",profile,exception);
-- profile=DestroyStringInfo(profile);
-- }
-- }
-+ (void) SetImageProfile(image,"exif",profile,exception);
-+ profile=DestroyStringInfo(profile);
- }
-- exif_buffer=(unsigned char *) RelinquishMagickMemory(exif_buffer);
-- }
-+ }
-+ exif_profile=(unsigned char *) RelinquishMagickMemory(exif_profile);
- return(MagickTrue);
- }
-
-@@ -253,13 +249,20 @@ static inline MagickBooleanType HEICSkipImage(const ImageInfo *image_info,
- }
-
- static MagickBooleanType ReadHEICImageHandle(const ImageInfo *image_info,
-- Image *image,struct heif_image_handle *image_handle,
-- ExceptionInfo *exception)
-+ Image *image,struct heif_image_handle *image_handle,ExceptionInfo *exception)
- {
- const uint8_t
-- *p;
-+ *p,
-+ *pixels;
-+
-+ enum heif_channel
-+ channel;
-+
-+ enum heif_chroma
-+ chroma;
-
- int
-+ shift,
- stride = 0;
-
- MagickBooleanType
-@@ -312,54 +315,102 @@ static MagickBooleanType ReadHEICImageHandle(const ImageInfo *image_info,
- if (status == MagickFalse)
- return(MagickFalse);
- decode_options=heif_decoding_options_alloc();
--#if LIBHEIF_NUMERIC_VERSION > 0x01070000
-- decode_options->convert_hdr_to_8bit=1;
--#endif
+@@ -318,13 +318,17 @@ static MagickBooleanType ReadHEICImageHandle(const ImageInfo *image_info,
if (preserve_orientation == MagickTrue)
decode_options->ignore_transformations=1;
-- error=heif_decode_image(image_handle,&heif_image,heif_colorspace_RGB,
-- image->alpha_trait != UndefinedPixelTrait ? heif_chroma_interleaved_RGBA :
-- heif_chroma_interleaved_RGB,decode_options);
-+ chroma=heif_chroma_interleaved_RGB;
-+ if (image->depth > 8)
-+ chroma=heif_chroma_interleaved_RRGGBB_LE;
-+ if (image->alpha_trait != UndefinedPixelTrait)
-+ {
-+ chroma=heif_chroma_interleaved_RGBA;
-+ if (image->depth > 8)
-+ chroma=heif_chroma_interleaved_RRGGBBAA_LE;
-+ }
-+ error=heif_decode_image(image_handle,&heif_image,heif_colorspace_RGB,chroma,
-+ decode_options);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ return(MagickFalse);
- heif_decoding_options_free(decode_options);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- return(MagickFalse);
-- image->columns=(size_t) heif_image_get_width(heif_image,
-- heif_channel_interleaved);
-- image->rows=(size_t) heif_image_get_height(heif_image,
-- heif_channel_interleaved);
-+ channel=heif_channel_interleaved;
-+ image->columns=(size_t) heif_image_get_width(heif_image,channel);
-+ image->rows=(size_t) heif_image_get_height(heif_image,channel);
- status=SetImageExtent(image,image->columns,image->rows,exception);
- if (status == MagickFalse)
- {
- heif_image_release(heif_image);
- return(MagickFalse);
- }
-- p=heif_image_get_plane_readonly(heif_image,heif_channel_interleaved,&stride);
-- stride-=(int) (image->columns * (image->alpha_trait != UndefinedPixelTrait ?
-- 4 : 3));
-- for (y=0; y < (ssize_t) image->rows; y++)
-- {
-- Quantum
-- *q;
-+ pixels=heif_image_get_plane_readonly(heif_image,channel,&stride);
-+ if (pixels == (const uint8_t *) NULL)
-+ {
-+ heif_image_release(heif_image);
-+ return(MagickFalse);
-+ }
-+ shift=(int) (16-image->depth);
-+ if (image->depth <= 8)
-+ for (y=0; y < (ssize_t) image->rows; y++)
-+ {
-+ Quantum
-+ *q;
-
-- ssize_t
-- x;
-+ ssize_t
-+ x;
-
-- q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-- if (q == (Quantum *) NULL)
-- break;
-- for (x=0; x < (ssize_t) image->columns; x++)
-+ /*
-+ Transform 8-bit image.
-+ */
-+ q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-+ if (q == (Quantum *) NULL)
-+ break;
-+ p=pixels+(y*stride);
-+ for (x=0; x < (ssize_t) image->columns; x++)
-+ {
-+ SetPixelRed(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-+ SetPixelGreen(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-+ SetPixelBlue(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-+ if (image->alpha_trait != UndefinedPixelTrait)
-+ SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-+ q+=GetPixelChannels(image);
-+ }
-+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
-+ break;
-+ }
-+ else
-+ for (y=0; y < (ssize_t) image->rows; y++)
- {
-- SetPixelRed(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-- SetPixelGreen(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-- SetPixelBlue(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-- if (image->alpha_trait != UndefinedPixelTrait)
-- SetPixelAlpha(image,ScaleCharToQuantum((unsigned char) *(p++)),q);
-- q+=GetPixelChannels(image);
-+ Quantum
-+ *q;
-+
-+ ssize_t
-+ x;
-+
-+ /*
-+ Transform 10-bit or 12-bit image.
-+ */
-+ q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
-+ if (q == (Quantum *) NULL)
-+ break;
-+ p=pixels+(y*stride);
-+ for (x=0; x < (ssize_t) image->columns; x++)
-+ {
-+ unsigned short pixel = ((*(p+1) << 8) | (*(p+0))) << shift; p+=2;
-+ SetPixelRed(image,ScaleShortToQuantum(pixel),q);
-+ pixel=((*(p+1) << 8) | (*(p+0))) << shift; p+=2;
-+ SetPixelGreen(image,ScaleShortToQuantum(pixel),q);
-+ pixel=((*(p+1) << 8) | (*(p+0))) << shift; p+=2;
-+ SetPixelBlue(image,ScaleShortToQuantum(pixel),q);
-+ if (image->alpha_trait != UndefinedPixelTrait)
-+ {
-+ pixel=((*(p+1) << 8) | (*(p+0))) << shift; p+=2;
-+ SetPixelAlpha(image,ScaleShortToQuantum(pixel),q);
-+ }
-+ q+=GetPixelChannels(image);
-+ }
-+ if (SyncAuthenticPixels(image,exception) == MagickFalse)
-+ break;
- }
-- p+=stride;
-- if (SyncAuthenticPixels(image,exception) == MagickFalse)
-- break;
-- }
- heif_image_release(heif_image);
- return(MagickTrue);
- }
-@@ -382,6 +433,9 @@ static void ReadHEICDepthImage(const ImageInfo *image_info,Image *image,
- struct heif_image_handle
- *depth_handle;
-
-+ /*
-+ Read HEIF depth image.
-+ */
- option=GetImageOption(image_info,"heic:depth-image");
- if (IsStringTrue(option) == MagickFalse)
- return;
-@@ -393,7 +447,7 @@ static void ReadHEICDepthImage(const ImageInfo *image_info,Image *image,
- return;
- error=heif_image_handle_get_depth_image_handle(image_handle,depth_id,
- &depth_handle);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- return;
- AcquireNextImage(image_info,image,exception);
- if (GetNextImageInList(image) != (Image *) NULL)
-@@ -430,7 +484,7 @@ static Image *ReadHEICImage(const ImageInfo *image_info,
- *image_handle;
-
- void
-- *file_data;
-+ *container;
-
- /*
- Open image file.
-@@ -449,43 +503,43 @@ static Image *ReadHEICImage(const ImageInfo *image_info,
- if (GetBlobSize(image) > (MagickSizeType) MAGICK_SSIZE_MAX)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
- length=(size_t) GetBlobSize(image);
-- file_data=AcquireMagickMemory(length);
-- if (file_data == (void *) NULL)
-+ container=AcquireMagickMemory(length);
-+ if (container == (void *) NULL)
- ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
-- if (ReadBlob(image,length,file_data) != (ssize_t) length)
-+ if (ReadBlob(image,length,container) != (ssize_t) length)
- {
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
- }
- #if LIBHEIF_NUMERIC_VERSION >= 0x010b0000
-- if (heif_has_compatible_brand((unsigned char *) file_data,(int) length,"avif") != MagickFalse)
-+ if (heif_has_compatible_brand((unsigned char *) container,(int) length,"avif") != MagickFalse)
- (void) CopyMagickString(image->magick,"AVIF",MagickPathExtent);
- #endif
- /*
- Decode HEIF image.
- */
- heif_context=heif_context_alloc();
-- error=heif_context_read_from_memory_without_copy(heif_context,file_data,
-+ error=heif_context_read_from_memory_without_copy(heif_context,container,
- length,NULL);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- {
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- return(DestroyImageList(image));
- }
- error=heif_context_get_primary_image_ID(heif_context,&primary_image_id);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- {
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- return(DestroyImageList(image));
- }
- error=heif_context_get_image_handle(heif_context,primary_image_id,
- &image_handle);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- {
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- return(DestroyImageList(image));
- }
- status=ReadHEICImageHandle(image_info,image,image_handle,exception);
-@@ -494,24 +548,23 @@ static Image *ReadHEICImage(const ImageInfo *image_info,
- if ((status != MagickFalse) && (count > 1))
- {
- heif_item_id
-- *image_ids;
-+ *ids;
-
- size_t
- i;
-
-- image_ids=(heif_item_id *) AcquireQuantumMemory((size_t) count,
-- sizeof(*image_ids));
-- if (image_ids == (heif_item_id *) NULL)
-+ ids=(heif_item_id *) AcquireQuantumMemory((size_t) count,sizeof(*ids));
-+ if (ids == (heif_item_id *) NULL)
- {
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- return(DestroyImageList(image));
- }
-- (void) heif_context_get_list_of_top_level_image_IDs(heif_context,
-- image_ids,(int) count);
-+ (void) heif_context_get_list_of_top_level_image_IDs(heif_context,ids,
-+ (int) count);
- for (i=0; i < count; i++)
- {
-- if (image_ids[i] == primary_image_id)
-+ if (ids[i] == primary_image_id)
- continue;
- /*
- Allocate next image structure.
-@@ -523,9 +576,8 @@ static Image *ReadHEICImage(const ImageInfo *image_info,
- break;
- }
- image=SyncNextImageInList(image);
-- error=heif_context_get_image_handle(heif_context,image_ids[i],
-- &image_handle);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ error=heif_context_get_image_handle(heif_context,ids[i],&image_handle);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- {
- status=MagickFalse;
- break;
-@@ -538,20 +590,20 @@ static Image *ReadHEICImage(const ImageInfo *image_info,
- if (image->scene >= (image_info->scene+image_info->number_scenes-1))
- break;
- }
-- image_ids=(heif_item_id *) RelinquishMagickMemory(image_ids);
-+ ids=(heif_item_id *) RelinquishMagickMemory(ids);
- }
- error=heif_context_get_image_handle(heif_context,primary_image_id,
- &image_handle);
-- if (IsHeifSuccess(image,&error,exception) == MagickFalse)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
+ chroma=heif_chroma_interleaved_RGB;
++#if LIBHEIF_NUMERIC_VERSION > 0x01040000
+ if (image->depth > 8)
+ chroma=heif_chroma_interleaved_RRGGBB_LE;
++#endif
+ if (image->alpha_trait != UndefinedPixelTrait)
{
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- return(DestroyImageList(image));
- }
- ReadHEICDepthImage(image_info,image,image_handle,exception);
- heif_image_handle_release(image_handle);
- heif_context_free(heif_context);
-- file_data=RelinquishMagickMemory(file_data);
-+ container=RelinquishMagickMemory(container);
- if (status == MagickFalse)
- return(DestroyImageList(image));
- (void) CloseBlob(image);
-@@ -589,12 +641,12 @@ static MagickBooleanType IsHEIC(const unsigned char *magick,const size_t length)
- #if defined(MAGICKCORE_HEIC_DELEGATE)
- #if LIBHEIF_NUMERIC_VERSION >= 0x01040000
- enum heif_filetype_result
-- heif_filetype;
-+ type;
-
- if (length < 12)
- return(MagickFalse);
-- heif_filetype=heif_check_filetype(magick,(int) length);
-- if (heif_filetype == heif_filetype_yes_supported)
-+ type=heif_check_filetype(magick,(int) length);
-+ if (type == heif_filetype_yes_supported)
- return(MagickTrue);
- #endif
- #endif
-@@ -748,12 +800,12 @@ static void WriteProfile(struct heif_context *context,Image *image,
- const StringInfo
- *profile;
-
-- ssize_t
-- i;
--
- size_t
- length;
-
-+ ssize_t
-+ i;
-+
- struct heif_error
- error;
-
-@@ -765,7 +817,7 @@ static void WriteProfile(struct heif_context *context,Image *image,
- */
- image_handle=(struct heif_image_handle *) NULL;
- error=heif_context_get_primary_image_handle(context,&image_handle);
-- if (error.code != 0)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- return;
- /*
- Save image profile as a APP marker.
-@@ -804,7 +856,7 @@ static void WriteProfile(struct heif_context *context,Image *image,
- length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
- error=heif_context_add_XMP_metadata(context,image_handle,
- (void*) (GetStringInfoDatum(xmp_profile)+i),(int) length);
-- if (error.code != 0)
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
- break;
- }
- xmp_profile=DestroyStringInfo(xmp_profile);
-@@ -841,10 +893,9 @@ static MagickBooleanType WriteHEICImageYCbCr(Image *image,
- struct heif_image *heif_image,ExceptionInfo *exception)
- {
- int
-- bit_depth,
-- p_y,
- p_cb,
-- p_cr;
-+ p_cr,
-+ p_y;
-
- MagickBooleanType
- status;
-@@ -856,33 +907,32 @@ static MagickBooleanType WriteHEICImageYCbCr(Image *image,
- error;
-
- uint8_t
-- *q_y,
- *q_cb,
-- *q_cr;
-+ *q_cr,
-+ *q_y;
-
-+ /*
-+ Transform HEIF YCbCr image.
-+ */
- status=MagickTrue;
-- bit_depth=8;
- error=heif_image_add_plane(heif_image,heif_channel_Y,(int) image->columns,
-- (int) image->rows,bit_depth);
-- status=IsHeifSuccess(image,&error,exception);
-+ (int) image->rows,8);
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- return(status);
- error=heif_image_add_plane(heif_image,heif_channel_Cb,
-- ((int) image->columns+1)/2,((int) image->rows+1)/2,bit_depth);
-- status=IsHeifSuccess(image,&error,exception);
-+ ((int) image->columns+1)/2,((int) image->rows+1)/2,8);
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- return(status);
- error=heif_image_add_plane(heif_image,heif_channel_Cr,
-- ((int) image->columns+1)/2,((int) image->rows+1)/2,bit_depth);
-- status=IsHeifSuccess(image,&error,exception);
-+ ((int) image->columns+1)/2,((int) image->rows+1)/2,8);
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- return(status);
- q_y=heif_image_get_plane(heif_image,heif_channel_Y,&p_y);
- q_cb=heif_image_get_plane(heif_image,heif_channel_Cb,&p_cb);
- q_cr=heif_image_get_plane(heif_image,heif_channel_Cr,&p_cr);
-- /*
-- Copy image to heif_image
-- */
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- const Quantum
-@@ -930,35 +980,124 @@ static MagickBooleanType WriteHEICImageYCbCr(Image *image,
- static MagickBooleanType WriteHEICImageRGBA(Image *image,
- struct heif_image *heif_image,ExceptionInfo *exception)
- {
-+ const Quantum
-+ *p;
-+
-+ enum heif_channel
-+ channel;
-+
-+ int
-+ stride;
-+
- MagickBooleanType
- status;
-
- ssize_t
- y;
-
-+ struct heif_error
-+ error;
-+
-+ uint8_t
-+ *pixels,
-+ *q;
-+
-+ /*
-+ Transform HEIF RGBA image.
-+ */
-+ status=MagickTrue;
-+ channel=heif_channel_interleaved;
-+ if (GetPixelChannels(image) == 1)
-+ channel=heif_channel_Y;
-+ error=heif_image_add_plane(heif_image,channel,(int) image->columns,
-+ (int) image->rows,8);
-+ status=IsHEIFSuccess(image,&error,exception);
-+ if (status == MagickFalse)
-+ return(status);
-+ pixels=heif_image_get_plane(heif_image,channel,&stride);
-+ if (pixels == (uint8_t *) NULL)
-+ return(MagickFalse);
-+ for (y=0; y < (ssize_t) image->rows; y++)
-+ {
-+ ssize_t
-+ x;
-+
-+ p=GetVirtualPixels(image,0,y,image->columns,1,exception);
-+ if (p == (const Quantum *) NULL)
-+ {
-+ status=MagickFalse;
-+ break;
-+ }
-+ q=pixels+(y*stride);
-+ for (x=0; x < (ssize_t) image->columns; x++)
-+ {
-+ *(q++)=ScaleQuantumToChar(GetPixelRed(image,p));
-+ if (GetPixelChannels(image) > 1)
-+ {
-+ *(q++)=ScaleQuantumToChar(GetPixelGreen(image,p));
-+ *(q++)=ScaleQuantumToChar(GetPixelBlue(image,p));
-+ if (image->alpha_trait != UndefinedPixelTrait)
-+ *(q++)=ScaleQuantumToChar(GetPixelAlpha(image,p));
-+ }
-+ p+=GetPixelChannels(image);
-+ }
-+ if (image->previous == (Image *) NULL)
-+ {
-+ status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
-+ image->rows);
-+ if (status == MagickFalse)
-+ break;
-+ }
-+ }
-+ return(status);
-+}
-+
-+static MagickBooleanType WriteHEICImageRRGGBBAA(Image *image,
-+ struct heif_image *heif_image,ExceptionInfo *exception)
-+{
- const Quantum
- *p;
-
-+ enum heif_channel
-+ channel;
-+
- int
-+ depth,
-+ shift,
- stride;
-
-+ MagickBooleanType
-+ status;
-+
-+ ssize_t
-+ y;
-+
- struct heif_error
- error;
-
- uint8_t
-- *q,
-- *plane;
-+ *pixels,
-+ *q;
-
-- status=MagickTrue;
-- error=heif_image_add_plane(heif_image,heif_channel_interleaved,
-- (int) image->columns,(int) image->rows,8);
-- status=IsHeifSuccess(image,&error,exception);
-- if (status == MagickFalse)
-- return status;
-- plane=heif_image_get_plane(heif_image,heif_channel_interleaved,&stride);
- /*
-- Copy image to heif_image
-+ Transform HEIF RGBA image with depth > 8.
- */
-+ status=MagickTrue;
-+ depth=image->depth > 10 ? 12 : 10;
-+ channel=heif_channel_interleaved;
-+ if (GetPixelChannels(image) == 1)
-+ channel=heif_channel_Y;
-+ error=heif_image_add_plane(heif_image,channel,(int) image->columns,
-+ (int) image->rows,depth);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ return(MagickFalse);
-+ status=IsHEIFSuccess(image,&error,exception);
-+ if (status == MagickFalse)
-+ return(status);
-+ pixels=heif_image_get_plane(heif_image,channel,&stride);
-+ if (pixels == (uint8_t *) NULL)
-+ return(MagickFalse);
-+ shift=(int) (16-depth);
- for (y=0; y < (ssize_t) image->rows; y++)
- {
- ssize_t
-@@ -970,17 +1109,29 @@ static MagickBooleanType WriteHEICImageRGBA(Image *image,
- status=MagickFalse;
- break;
- }
-- q=plane+(y*stride);
-+ q=pixels+(y*stride);
- for (x=0; x < (ssize_t) image->columns; x++)
-- {
-- *(q++)=ScaleQuantumToChar(GetPixelRed(image,p));
-- *(q++)=ScaleQuantumToChar(GetPixelGreen(image,p));
-- *(q++)=ScaleQuantumToChar(GetPixelBlue(image,p));
-- if (image->alpha_trait != UndefinedPixelTrait)
-- *(q++)=ScaleQuantumToChar(GetPixelAlpha(image,p));
--
-- p+=GetPixelChannels(image);
-- }
-+ {
-+ int pixel=ScaleQuantumToShort(GetPixelRed(image,p)) >> shift;
-+ *(q++)=(uint8_t) (pixel & 0xff);
-+ *(q++)=(uint8_t) (pixel >> 8);
-+ if (GetPixelChannels(image) > 1)
-+ {
-+ pixel=ScaleQuantumToShort(GetPixelGreen(image,p)) >> shift;
-+ *(q++)=(uint8_t) (pixel & 0xff);
-+ *(q++)=(uint8_t) (pixel >> 8);
-+ pixel=ScaleQuantumToShort(GetPixelBlue(image,p)) >> shift;
-+ *(q++)=(uint8_t) (pixel & 0xff);
-+ *(q++)=(uint8_t) (pixel >> 8);
-+ if (image->alpha_trait != UndefinedPixelTrait)
-+ {
-+ pixel=ScaleQuantumToShort(GetPixelAlpha(image,p)) >> shift;
-+ *(q++)=(uint8_t) (pixel & 0xff);
-+ *(q++)=(uint8_t) (pixel >> 8);
-+ }
-+ }
-+ p+=GetPixelChannels(image);
-+ }
- if (image->previous == (Image *) NULL)
- {
- status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
-@@ -996,6 +1147,9 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- Image *image,ExceptionInfo *exception)
- {
- MagickBooleanType
-+#if LIBHEIF_NUMERIC_VERSION > 0x01060200
-+ encode_avif,
+ chroma=heif_chroma_interleaved_RGBA;
++#if LIBHEIF_NUMERIC_VERSION > 0x01040000
+ if (image->depth > 8)
+ chroma=heif_chroma_interleaved_RRGGBBAA_LE;
+#endif
- status;
-
- MagickOffsetType
-@@ -1005,22 +1159,17 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- *heif_context;
-
- struct heif_encoder
-- *heif_encoder;
-+ *heif_encoder = (struct heif_encoder*) NULL;
-
- struct heif_error
- error;
-
- struct heif_image
-- *heif_image;
-+ *heif_image = (struct heif_image*) NULL;
-
- struct heif_writer
- writer;
-
--#if LIBHEIF_NUMERIC_VERSION > 0x01060200
-- MagickBooleanType
-- encode_avif;
--#endif
--
- /*
- Open output image file.
- */
-@@ -1035,11 +1184,9 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- return(status);
- scene=0;
- heif_context=heif_context_alloc();
-- heif_image=(struct heif_image*) NULL;
-- heif_encoder=(struct heif_encoder*) NULL;
- #if LIBHEIF_NUMERIC_VERSION > 0x01060200
-- encode_avif=(LocaleCompare(image_info->magick,"AVIF") == 0) ?
-- MagickTrue : MagickFalse;
-+ encode_avif=(LocaleCompare(image_info->magick,"AVIF") == 0) ? MagickTrue :
-+ MagickFalse;
- #endif
- do
- {
-@@ -1048,18 +1195,15 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- *profile;
- #endif
-
-- enum heif_colorspace
-- colorspace;
--
- enum heif_chroma
- chroma;
-
-+ enum heif_colorspace
-+ colorspace = heif_colorspace_YCbCr;
-+
- MagickBooleanType
-- lossless;
-+ lossless = image_info->quality >= 100 ? MagickTrue : MagickFalse;
-
-- colorspace=heif_colorspace_YCbCr;
-- lossless=image_info->quality == 100 ? MagickTrue : MagickFalse;
-- chroma=lossless ? heif_chroma_444 : heif_chroma_420;
- /*
- Get encoder for the specified format.
- */
-@@ -1071,23 +1215,37 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- #endif
- error=heif_context_get_encoder_for_format(heif_context,
- heif_compression_HEVC,&heif_encoder);
-- status=IsHeifSuccess(image,&error,exception);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ break;
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- break;
-+ chroma=lossless != MagickFalse ? heif_chroma_444 : heif_chroma_420;
- if (image->alpha_trait == BlendPixelTrait)
- {
-- colorspace=heif_colorspace_RGB;
-- chroma=heif_chroma_interleaved_RGBA;
- if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
+ }
+ error=heif_decode_image(image_handle,&heif_image,heif_colorspace_RGB,chroma,
+ decode_options);
+@@ -1225,16 +1229,20 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
status=TransformImageColorspace(image,sRGBColorspace,exception);
-- }
-- else if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
-- {
colorspace=heif_colorspace_RGB;
-- chroma=heif_chroma_interleaved_RGB;
-+ chroma=heif_chroma_interleaved_RGBA;
-+ if (image->depth > 8)
-+ chroma=heif_chroma_interleaved_RRGGBBAA_LE;
+ chroma=heif_chroma_interleaved_RGBA;
++#if LIBHEIF_NUMERIC_VERSION > 0x01040000
+ if (image->depth > 8)
+ chroma=heif_chroma_interleaved_RRGGBBAA_LE;
++#endif
}
-- else if (image->colorspace != YCbCrColorspace)
-- status=TransformImageColorspace(image,YCbCrColorspace,exception);
-+ else
-+ if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
-+ {
-+ colorspace=heif_colorspace_RGB;
-+ chroma=heif_chroma_interleaved_RGB;
-+ if (image->depth > 8)
-+ chroma=heif_chroma_interleaved_RRGGBB_LE;
-+ if (GetPixelChannels(image) == 1)
-+ {
-+ colorspace=heif_colorspace_monochrome;
-+ chroma=heif_chroma_monochrome;
-+ }
-+ }
-+ else
-+ if (image->colorspace != YCbCrColorspace)
-+ status=TransformImageColorspace(image,YCbCrColorspace,exception);
- if (status == MagickFalse)
- break;
- /*
-@@ -1095,7 +1253,9 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- */
- error=heif_image_create((int) image->columns,(int) image->rows,colorspace,
- chroma,&heif_image);
-- status=IsHeifSuccess(image,&error,exception);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ break;
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- break;
- #if LIBHEIF_NUMERIC_VERSION >= 0x01040000
-@@ -1107,18 +1267,26 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
+ else
+ if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
+ {
+ colorspace=heif_colorspace_RGB;
+ chroma=heif_chroma_interleaved_RGB;
++#if LIBHEIF_NUMERIC_VERSION > 0x01040000
+ if (image->depth > 8)
+ chroma=heif_chroma_interleaved_RRGGBB_LE;
++#endif
+ if (GetPixelChannels(image) == 1)
+ {
+ colorspace=heif_colorspace_monochrome;
+@@ -1265,9 +1273,11 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
if (colorspace == heif_colorspace_YCbCr)
status=WriteHEICImageYCbCr(image,heif_image,exception);
else
-- status=WriteHEICImageRGBA(image,heif_image,exception);
-+ if (image->depth > 8)
-+ status=WriteHEICImageRRGGBBAA(image,heif_image,exception);
-+ else
-+ status=WriteHEICImageRGBA(image,heif_image,exception);
- if (status == MagickFalse)
- break;
- /*
-- Code and actually write the HEIC image
-+ Encode HEIC image.
- */
- if (lossless != MagickFalse)
- error=heif_encoder_set_lossless(heif_encoder,1);
-- else if (image_info->quality != UndefinedCompressionQuality)
-- error=heif_encoder_set_lossy_quality(heif_encoder,(int)
-- image_info->quality);
-- status=IsHeifSuccess(image,&error,exception);
-+ else
-+ if (image_info->quality == UndefinedCompressionQuality)
-+ error=heif_encoder_set_lossy_quality(heif_encoder,50);
-+ else
-+ error=heif_encoder_set_lossy_quality(heif_encoder,(int)
-+ image_info->quality);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ break;
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- break;
- #if LIBHEIF_NUMERIC_VERSION > 0x01060200
-@@ -1131,7 +1299,7 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- if (option != (char *) NULL)
- {
- error=heif_encoder_set_parameter(heif_encoder,"speed",option);
-- status=IsHeifSuccess(image,&error,exception);
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- break;
- }
-@@ -1139,7 +1307,7 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- if (option != (char *) NULL)
- {
- error=heif_encoder_set_parameter(heif_encoder,"chroma",option);
-- status=IsHeifSuccess(image,&error,exception);
-+ status=IsHEIFSuccess(image,&error,exception);
- if (status == MagickFalse)
- break;
- }
-@@ -1148,7 +1316,9 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- error=heif_context_encode_image(heif_context,heif_image,heif_encoder,
- (const struct heif_encoding_options *) NULL,
- (struct heif_image_handle **) NULL);
-- status=IsHeifSuccess(image,&error,exception);
-+ if (IsHEIFSuccess(image,&error,exception) == MagickFalse)
-+ break;
-+ status=IsHEIFSuccess(image,&error,exception);
++#if LIBHEIF_NUMERIC_VERSION > 0x01040000
+ if (image->depth > 8)
+ status=WriteHEICImageRRGGBBAA(image,heif_image,exception);
+ else
++#endif
+ status=WriteHEICImageRGBA(image,heif_image,exception);
if (status == MagickFalse)
break;
- #if LIBHEIF_NUMERIC_VERSION >= 0x01030000
-@@ -1177,7 +1347,7 @@ static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
- WriteProfile(heif_context,image,exception);
- #endif
- error=heif_context_write(heif_context,&writer,image);
-- status=IsHeifSuccess(image,&error,exception);
-+ status=IsHEIFSuccess(image,&error,exception);
- }
- if (heif_encoder != (struct heif_encoder*) NULL)
- heif_encoder_release(heif_encoder);