#endif
#endif
-
#if defined(MAGICKCORE_HEIC_DELEGATE)
+/*
+ Define declarations.
+*/
+#define XmpNamespaceExtent 28
/*
Const declarations.
*/
-static const char *xmp_namespace = "http://ns.adobe.com/xap/1.0/ ";
-#define XmpNamespaceExtent 28
+static const char
+ *xmp_namespace = "http://ns.adobe.com/xap/1.0/ ";
\f
+#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
/*
Forward declarations.
*/
-
-#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
static MagickBooleanType
WriteHEICImage(const ImageInfo *,Image *,ExceptionInfo *);
#endif
{
if (error->code == 0)
return(MagickTrue);
-
ThrowBinaryException(CorruptImageError,error->message,image->filename);
}
static Image *ReadHEICImage(const ImageInfo *image_info,
ExceptionInfo *exception)
{
+ const char
+ *option;
+
heif_item_id
exif_id;
MagickBooleanType
status;
- MagickSizeType
+ size_t
length;
ssize_t
struct heif_context
*heif_context;
+ struct heif_decoding_options
+ *decode_options;
+
struct heif_error
error;
struct heif_image_handle
*image_handle;
- struct heif_decoding_options
- *decode_options;
-
uint8_t
*p_y,
*p_cb,
void
*file_data;
- const char
- *option;
-
/*
Open image file.
*/
status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
if (status == MagickFalse)
return(DestroyImageList(image));
- length=GetBlobSize(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");
heif_context_free(heif_context);
return(DestroyImageList(image));
}
- /*
- Read Exif data from HEIC file
- */
+ length=heif_image_handle_get_raw_color_profile_size(image_handle);
+ if (length > 0)
+ {
+ unsigned char
+ *color_buffer;
+
+ /*
+ Read color profile.
+ */
+ if ((MagickSizeType) length > GetBlobSize(image))
+ {
+ heif_image_handle_release(image_handle);
+ heif_context_free(heif_context);
+ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
+ }
+ color_buffer=(unsigned char *) AcquireMagickMemory(length);
+ if (color_buffer != (unsigned char *) NULL)
+ {
+ 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);
+ }
+ }
+ }
+ color_buffer=(unsigned char *) RelinquishMagickMemory(color_buffer);
+ }
count=heif_image_handle_get_list_of_metadata_block_IDs(image_handle,"Exif",
&exif_id,1);
if (count > 0)
unsigned char
*exif_buffer;
+ /*
+ Read Exif profile.
+ */
exif_size=heif_image_handle_get_metadata_size(image_handle,exif_id);
- if (exif_size > GetBlobSize(image))
+ if ((MagickSizeType) exif_size > GetBlobSize(image))
{
heif_image_handle_release(image_handle);
heif_context_free(heif_context);
- ThrowReaderException(CorruptImageError,
- "InsufficientImageDataInFile");
+ ThrowReaderException(CorruptImageError,"InsufficientImageDataInFile");
}
exif_buffer=(unsigned char *) AcquireMagickMemory(exif_size);
- if (exif_buffer !=(unsigned char *) NULL)
+ if (exif_buffer != (unsigned char *) NULL)
{
error=heif_image_handle_get_metadata(image_handle,
exif_id,exif_buffer);
StringInfo
*profile;
- // The first 4 byte should be skipped since they indicate the
- // offset to the start of the TIFF header of the Exif data.
+ /*
+ The first 4 byte should be skipped since they indicate the
+ offset to the start of the TIFF header of the Exif data.
+ */
profile=(StringInfo*) NULL;
if (exif_size > 8)
- profile=BlobToStringInfo(exif_buffer+4,exif_size-4);
+ profile=BlobToStringInfo(exif_buffer+4,(size_t) exif_size-4);
if (profile != (StringInfo*) NULL)
{
- SetImageProfile(image,"exif",profile,exception);
+ (void) SetImageProfile(image,"exif",profile,exception);
profile=DestroyStringInfo(profile);
}
}
exif_buffer=(unsigned char *) RelinquishMagickMemory(exif_buffer);
}
/*
- Set image size
- */
+ Set image size.
+ */
image->depth=8;
image->columns=(size_t) heif_image_handle_get_width(image_handle);
image->rows=(size_t) heif_image_handle_get_height(image_handle);
return(DestroyImageList(image));
}
/*
- Copy HEIF image into ImageMagick data structures
+ Copy HEIF image into ImageMagick data structures.
*/
(void) SetImageColorspace(image,YCbCrColorspace,exception);
decode_options=(struct heif_decoding_options *) NULL;
decode_options->ignore_transformations=1;
}
else
- SetImageProperty(image,"exif:Orientation","1",exception);
+ (void) SetImageProperty(image,"exif:Orientation","1",exception);
error=heif_decode_image(image_handle,&heif_image,heif_colorspace_YCbCr,
heif_chroma_420,decode_options);
if (decode_options != (struct heif_decoding_options *) NULL)
{
- /* Correct the width and height of the image */
+ /*
+ Correct the width and height of the image.
+ */
image->columns=(size_t) heif_image_get_width(heif_image,heif_channel_Y);
image->rows=(size_t) heif_image_get_height(heif_image,heif_channel_Y);
status=SetImageExtent(image,image->columns,image->rows,exception);
q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
if (q == (Quantum *) NULL)
break;
- for (x=0; x < (long) image->columns; x++)
+ for (x=0; x < (ssize_t) image->columns; x++)
{
- SetPixelRed(image,ScaleCharToQuantum(p_y[y*stride_y + x]),q);
- SetPixelGreen(image,ScaleCharToQuantum(p_cb[(y/2)*stride_cb + x/2]),q);
- SetPixelBlue(image,ScaleCharToQuantum(p_cr[(y/2)*stride_cr + x/2]),q);
+ SetPixelRed(image,ScaleCharToQuantum((unsigned char) p_y[y*
+ stride_y+x]),q);
+ SetPixelGreen(image,ScaleCharToQuantum((unsigned char) p_cb[(y/2)*
+ stride_cb+x/2]),q);
+ SetPixelBlue(image,ScaleCharToQuantum((unsigned char) p_cr[(y/2)*
+ stride_cr+x/2]),q);
q+=GetPixelChannels(image);
}
if (SyncAuthenticPixels(image,exception) == MagickFalse)
return(GetFirstImageInList(image));
}
#endif
-
+\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
return(MagickTrue);
return(MagickFalse);
}
-
+\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
(void) RegisterMagickInfo(entry);
return(MagickImageCoderSignature);
}
-
+\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
{
(void) UnregisterMagickInfo("HEIC");
}
-
+\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
% o exception: return any errors or warnings in this structure.
%
*/
+
#if defined(MAGICKCORE_HEIC_DELEGATE) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
-static void WriteProfile(struct heif_context* ctx,Image *image,
+static void WriteProfile(struct heif_context *context,Image *image,
ExceptionInfo *exception)
{
const char
const StringInfo
*profile;
- MagickBooleanType
- iptc;
-
register ssize_t
i;
struct heif_image_handle
*image_handle;
- /*Get image handle*/
+ /*
+ Get image handle.
+ */
image_handle=(struct heif_image_handle *) NULL;
- error=heif_context_get_primary_image_handle(ctx,&image_handle);
+ error=heif_context_get_primary_image_handle(context,&image_handle);
if (error.code != 0)
return;
-
/*
Save image profile as a APP marker.
*/
- iptc=MagickFalse;
custom_profile=AcquireStringInfo(65535L);
ResetImageProfileIterator(image);
for (name=GetNextImageProfile(image); name != (const char *) NULL; )
{
profile=GetImageProfile(image,name);
length=GetStringInfoLength(profile);
-
if (LocaleCompare(name,"EXIF") == 0)
{
length=GetStringInfoLength(profile);
image->filename);
length=65533L;
}
- (void) heif_context_add_exif_metadata(ctx,image_handle,
+ (void) heif_context_add_exif_metadata(context,image_handle,
(void*) GetStringInfoDatum(profile),length);
}
-
if (LocaleCompare(name,"XMP") == 0)
{
StringInfo
for (i=0; i < (ssize_t) GetStringInfoLength(xmp_profile); i+=65533L)
{
length=MagickMin(GetStringInfoLength(xmp_profile)-i,65533L);
- error=heif_context_add_XMP_metadata(ctx,image_handle,
+ error=heif_context_add_XMP_metadata(context,image_handle,
(void*) (GetStringInfoDatum(xmp_profile)+i),length);
if (error.code != 0)
break;
heif_image_handle_release(image_handle);
}
-static struct heif_error heif_write_func(struct heif_context *ctx,const void* data,
- size_t size,void* userdata)
+static struct heif_error heif_write_func(struct heif_context *context,
+ const void* data,size_t size,void* userdata)
{
Image
*image;
struct heif_error
error_ok;
- (void) ctx;
+ (void) context;
image=(Image*) userdata;
(void) WriteBlob(image,size,(const unsigned char *) data);
error_ok.code=heif_error_Ok;
return(error_ok);
}
-static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,Image *image,
- ExceptionInfo *exception)
+static MagickBooleanType WriteHEICImage(const ImageInfo *image_info,
+ Image *image,ExceptionInfo *exception)
{
- long
- x,
- y;
-
MagickBooleanType
status;
MagickOffsetType
scene;
+ ssize_t
+ y;
+
struct heif_context
*heif_context;
const Quantum
*p;
+ const StringInfo
+ *profile;
+
int
stride_y,
stride_cb,
if (status == MagickFalse)
break;
/*
- Initialize HEIF encoder context
+ Initialize HEIF encoder context.
*/
error=heif_image_create((int) image->columns,(int) image->rows,
heif_colorspace_YCbCr,heif_chroma_420,&heif_image);
status=IsHeifSuccess(&error,image,exception);
if (status == MagickFalse)
break;
+ profile=GetImageProfile(image,"icc");
+ if (profile != (StringInfo *) NULL)
+ (void) heif_image_set_raw_color_profile(heif_image,"prof",
+ GetStringInfoDatum(profile),GetStringInfoLength(profile));
error=heif_image_add_plane(heif_image,heif_channel_Y,(int) image->columns,
(int) image->rows,8);
status=IsHeifSuccess(&error,image,exception);
/*
Copy image to heif_image
*/
- for (y=0; y < (long) image->rows; y++)
+ for (y=0; y < (ssize_t) image->rows; y++)
{
+ register ssize_t
+ x;
+
p=GetVirtualPixels(image,0,y,image->columns,1,exception);
if (p == (const Quantum *) NULL)
{
status=MagickFalse;
break;
}
- if ((y & 1)==0)
+ if ((y & 0x01) == 0)
+ for (x=0; x < (ssize_t) image->columns; x+=2)
{
- for (x=0; x < (long) image->columns; x+=2)
+ p_y[y*stride_y+x]=ScaleQuantumToChar(GetPixelRed(image,p));
+ p_cb[y/2*stride_cb+x/2]=ScaleQuantumToChar(GetPixelGreen(image,p));
+ p_cr[y/2*stride_cr+x/2]=ScaleQuantumToChar(GetPixelBlue(image,p));
+ p+=GetPixelChannels(image);
+ if ((x+1) < (ssize_t) image->columns)
{
- p_y[y*stride_y+x]=ScaleQuantumToChar(GetPixelRed(image,p));
- p_cb[y/2*stride_cb+x/2]=ScaleQuantumToChar(GetPixelGreen(image,
- p));
- p_cr[y/2*stride_cr+x/2]=ScaleQuantumToChar(GetPixelBlue(image,
- p));
+ p_y[y*stride_y+x+1]=ScaleQuantumToChar(GetPixelRed(image,p));
p+=GetPixelChannels(image);
-
- if ((x+1) < (ssize_t) image->columns)
- {
- p_y[y*stride_y + x+1]=ScaleQuantumToChar(GetPixelRed(image,
- p));
- p+=GetPixelChannels(image);
- }
}
}
else
+ for (x=0; x < (ssize_t) image->columns; x++)
{
- for (x=0; x < (long) image->columns; x++)
- {
- p_y[y*stride_y + x]=ScaleQuantumToChar(GetPixelRed(image,p));
- p+=GetPixelChannels(image);
- }
+ p_y[y*stride_y+x]=ScaleQuantumToChar(GetPixelRed(image,p));
+ p+=GetPixelChannels(image);
}
if (image->previous == (Image *) NULL)
{
break;
if (image_info->quality != UndefinedCompressionQuality)
{
- error=heif_encoder_set_lossy_quality(heif_encoder,
- (int) image_info->quality);
+ error=heif_encoder_set_lossy_quality(heif_encoder,(int)
+ image_info->quality);
status=IsHeifSuccess(&error,image,exception);
if (status == MagickFalse)
break;
}
error=heif_context_encode_image(heif_context,heif_image,heif_encoder,
- (const struct heif_encoding_options*) NULL,
- (struct heif_image_handle**) NULL);
+ (const struct heif_encoding_options *) NULL,
+ (struct heif_image_handle **) NULL);
status=IsHeifSuccess(&error,image,exception);
if (status == MagickFalse)
break;
writer.writer_api_version=1;
writer.write=heif_write_func;
-
if (image->profiles != (void *) NULL)
WriteProfile(heif_context, image, exception);
-
error=heif_context_write(heif_context,&writer,image);
status=IsHeifSuccess(&error,image,exception);
if (status == MagickFalse)
break;
if (GetNextImageInList(image) == (Image *) NULL)
- break;
+ break;
image=SyncNextImageInList(image);
status=SetImageProgress(image,SaveImagesTag,scene,
GetImageListLength(image));
heif_image=(struct heif_image*) NULL;
scene++;
} while (image_info->adjoin != MagickFalse);
-
if (heif_encoder != (struct heif_encoder*) NULL)
heif_encoder_release(heif_encoder);
if (heif_image != (struct heif_image*) NULL)
heif_image_release(heif_image);
heif_context_free(heif_context);
-
(void) CloseBlob(image);
return(status);
}