]> granicus.if.org Git - imagemagick/commitdiff
Refactored the code to prepare for reading all images from a HEIC image.
authorDirk Lemstra <dirk@lemstra.org>
Fri, 14 Jun 2019 09:53:45 +0000 (11:53 +0200)
committerDirk Lemstra <dirk@lemstra.org>
Fri, 14 Jun 2019 09:53:45 +0000 (11:53 +0200)
coders/heic.c

index a0c0c25470aaf20056ad181781f76a97587df960..5b16a9ef3a6c53fa090926d80c33afed5dadaff5 100644 (file)
@@ -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