% MagickCore Image Profile Methods %
% %
% Software Design %
-% John Cristy %
+% Cristy %
% July 1992 %
% %
% %
-% Copyright 1999-2013 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
% dedicated to making software imaging solutions freely available. %
% %
% You may not use this file except in compliance with the License. You may %
assert(clone_image != (const Image *) NULL);
assert(clone_image->signature == MagickSignature);
if (clone_image->profiles != (void *) NULL)
- image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
- (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
+ {
+ if (image->profiles != (void *) NULL)
+ DestroyImageProfiles(image);
+ image->profiles=CloneSplayTree((SplayTreeInfo *) clone_image->profiles,
+ (void *(*)(void *)) ConstantString,(void *(*)(void *)) CloneStringInfo);
+ }
return(MagickTrue);
}
\f
(void) ResetMagickMemory(transform,0,number_threads*sizeof(*transform));
for (i=0; i < (ssize_t) number_threads; i++)
{
- transform[i]=cmsCreateTransformTHR(image,source_profile,source_type,
- target_profile,target_type,intent,flags);
+ transform[i]=cmsCreateTransformTHR((cmsContext) image,source_profile,
+ source_type,target_profile,target_type,intent,flags);
if (transform[i] == (cmsHTRANSFORM) NULL)
return(DestroyTransformThreadSet(transform));
}
cms_exception.image=image;
cms_exception.exception=exception;
(void) cms_exception;
- source_profile=cmsOpenProfileFromMemTHR(&cms_exception,
+ source_profile=cmsOpenProfileFromMemTHR((cmsContext) &cms_exception,
GetStringInfoDatum(profile),(cmsUInt32Number)
GetStringInfoLength(profile));
if (source_profile == (cmsHPROFILE) NULL)
if (icc_profile != (StringInfo *) NULL)
{
target_profile=source_profile;
- source_profile=cmsOpenProfileFromMemTHR(&cms_exception,
- GetStringInfoDatum(icc_profile),(cmsUInt32Number)
- GetStringInfoLength(icc_profile));
+ source_profile=cmsOpenProfileFromMemTHR((cmsContext)
+ &cms_exception,GetStringInfoDatum(icc_profile),
+ (cmsUInt32Number) GetStringInfoLength(icc_profile));
if (source_profile == (cmsHPROFILE) NULL)
ThrowProfileException(ResourceLimitError,
"ColorspaceColorProfileMismatch",name);
}
static inline const unsigned char *ReadResourceLong(const unsigned char *p,
- size_t *quantum)
+ unsigned int *quantum)
{
*quantum=(size_t) (*p++ << 24);
*quantum|=(size_t) (*p++ << 16);
size_t
length;
+ ssize_t
+ count;
+
StringInfo
*profile;
unsigned char
length_byte;
- size_t
- count;
+ unsigned int
+ value;
unsigned short
id;
p++;
if (p > (datum+length-4))
break;
- p=ReadResourceLong(p,&count);
+ p=ReadResourceLong(p,&value);
+ count=(ssize_t) value;
if ((p > (datum+length-count)) || (count > length))
break;
switch (id)
{
case 0x03ed:
{
- unsigned short
+ unsigned int
resolution;
+ unsigned short
+ units;
+
/*
Resolution.
*/
- p=ReadResourceShort(p,&resolution)+6;
- image->resolution.x=(double) resolution;
- p=ReadResourceShort(p,&resolution)+6;
- image->resolution.y=(double) resolution;
+ p=ReadResourceLong(p,&resolution);
+ image->resolution.x=((double) resolution)/65536.0;
+ p=ReadResourceShort(p,&units)+2;
+ p=ReadResourceLong(p,&resolution)+4;
+ image->resolution.y=((double) resolution)/65536.0;
+ /*
+ Values are always stored as pixels per inch.
+ */
+ if ((ResolutionType) units != PixelsPerCentimeterResolution)
+ image->units=PixelsPerInchResolution;
+ else
+ {
+ image->units=PixelsPerCentimeterResolution;
+ image->resolution.x/=2.54;
+ image->resolution.y/=2.54;
+ }
break;
}
case 0x0404:
/*
Inject profile into image properties.
*/
- (void) FormatLocaleString(property,MaxTextExtent,"%s:sans",name);
+ (void) FormatLocaleString(property,MaxTextExtent,"%s:*",name);
(void) GetImageProperty(image,property,exception);
return(status);
}
return((size_t) (value & 0xffffffff));
}
+static inline size_t ReadProfileMSBLong(unsigned char **p,
+ size_t *length)
+{
+ size_t
+ value;
+
+ if (*length < 4)
+ return(0);
+
+ value=ReadProfileLong(MSBEndian,*p);
+ (*length)-=4;
+ *p+=4;
+ return(value);
+}
+
+static inline unsigned short ReadProfileMSBShort(unsigned char **p,
+ size_t *length)
+{
+ unsigned short
+ value;
+
+ if (*length < 2)
+ return(0);
+
+ value=ReadProfileShort(MSBEndian,*p);
+ (*length)-=2;
+ *p+=2;
+ return(value);
+}
+
static inline void WriteProfileLong(const EndianType endian,
const size_t value,unsigned char *p)
{
(void) CopyMagickMemory(p,buffer,2);
}
-MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
+static MagickBooleanType Sync8BimProfile(Image *image,StringInfo *profile)
+{
+ size_t
+ count,
+ length;
+
+ unsigned char
+ *p;
+
+ unsigned short
+ id;
+
+ length=GetStringInfoLength(profile);
+ p=GetStringInfoDatum(profile);
+ while(length != 0)
+ {
+ if (ReadProfileByte(&p,&length) != 0x38)
+ continue;
+ if (ReadProfileByte(&p,&length) != 0x42)
+ continue;
+ if (ReadProfileByte(&p,&length) != 0x49)
+ continue;
+ if (ReadProfileByte(&p,&length) != 0x4D)
+ continue;
+ if (length < 7)
+ return(MagickFalse);
+ id=ReadProfileMSBShort(&p,&length);
+ count=ReadProfileByte(&p,&length);
+ if (count > length)
+ return(MagickFalse);
+ p+=count;
+ if ((*p & 0x01) == 0)
+ p++;
+ count=ReadProfileMSBLong(&p,&length);
+ if (count > length)
+ return(MagickFalse);
+ if (id == 0x3ED && count == 16)
+ {
+ if (image->units == PixelsPerCentimeterResolution)
+ WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*2.54*
+ 65536.0),p);
+ else
+ WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.x*
+ 65536.0),p);
+ WriteProfileShort(MSBEndian,(unsigned short) image->units,p+4);
+ if (image->units == PixelsPerCentimeterResolution)
+ WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*2.54*
+ 65536.0),p+8);
+ else
+ WriteProfileLong(MSBEndian, (unsigned int) (image->resolution.y*
+ 65536.0),p+8);
+ WriteProfileShort(MSBEndian,(unsigned short) image->units,p+12);
+ }
+ p+=count;
+ length-=count;
+ }
+ return(MagickTrue);
+}
+
+MagickBooleanType SyncExifProfile(Image *image,StringInfo *profile)
{
#define MaxDirectoryStack 16
#define EXIF_DELIMITER "\n"
static int
format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
- StringInfo
- *profile;
-
unsigned char
*directory,
*exif;
/*
Set EXIF resolution tag.
*/
- profile=(StringInfo *) GetImageProfile(image,"EXIF");
- if (profile == (StringInfo *) NULL)
- return(MagickTrue);
length=GetStringInfoLength(profile);
exif=GetStringInfoDatum(profile);
- while (length != 0)
- {
- if (ReadProfileByte(&exif,&length) != 0x45)
- continue;
- if (ReadProfileByte(&exif,&length) != 0x78)
- continue;
- if (ReadProfileByte(&exif,&length) != 0x69)
- continue;
- if (ReadProfileByte(&exif,&length) != 0x66)
- continue;
- if (ReadProfileByte(&exif,&length) != 0x00)
- continue;
- if (ReadProfileByte(&exif,&length) != 0x00)
- continue;
- break;
- }
if (length < 16)
return(MagickFalse);
id=(ssize_t) ReadProfileShort(LSBEndian,exif);
+ if ((id != 0x4949) && (id != 0x4D4D))
+ {
+ while (length != 0)
+ {
+ if (ReadProfileByte(&exif,&length) != 0x45)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x78)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x69)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x66)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x00)
+ continue;
+ if (ReadProfileByte(&exif,&length) != 0x00)
+ continue;
+ break;
+ }
+ if (length < 16)
+ return(MagickFalse);
+ id=(ssize_t) ReadProfileShort(LSBEndian,exif);
+ }
endian=LSBEndian;
if (id == 0x4949)
endian=LSBEndian;
} while (level > 0);
return(MagickTrue);
}
+
+MagickPrivate MagickBooleanType SyncImageProfiles(Image *image)
+{
+ MagickBooleanType
+ status;
+
+ StringInfo
+ *profile;
+
+ status=MagickTrue;
+ profile=(StringInfo *) GetImageProfile(image,"8BIM");
+ if (profile != (StringInfo *) NULL)
+ if (Sync8BimProfile(image,profile) == MagickFalse)
+ status=MagickFalse;
+ profile=(StringInfo *) GetImageProfile(image,"EXIF");
+ if (profile != (StringInfo *) NULL)
+ if (SyncExifProfile(image,profile) == MagickFalse)
+ status=MagickFalse;
+ return(status);
+}