% March 2000 %
% %
% %
-% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
+% Copyright 1999-2012 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 %
Include declarations.
*/
#include "MagickCore/studio.h"
+#include "MagickCore/artifact.h"
#include "MagickCore/attribute.h"
#include "MagickCore/cache.h"
#include "MagickCore/color.h"
+#include "MagickCore/color-private.h"
+#include "MagickCore/colorspace-private.h"
#include "MagickCore/compare.h"
#include "MagickCore/constitute.h"
#include "MagickCore/draw.h"
#include "MagickCore/geometry.h"
#include "MagickCore/histogram.h"
#include "MagickCore/image.h"
-#include "MagickCore/image.h"
#include "MagickCore/layer.h"
+#include "MagickCore/locale-private.h"
#include "MagickCore/list.h"
#include "MagickCore/magick.h"
#include "MagickCore/memory_.h"
#include "MagickCore/quantum.h"
#include "MagickCore/resource_.h"
#include "MagickCore/splay-tree.h"
-#include "MagickCore/signature-private.h"
+#include "MagickCore/signature.h"
#include "MagickCore/statistic.h"
#include "MagickCore/string_.h"
#include "MagickCore/string-private.h"
#include "MagickCore/token.h"
+#include "MagickCore/token-private.h"
#include "MagickCore/utility.h"
+#include "MagickCore/utility-private.h"
#include "MagickCore/version.h"
#include "MagickCore/xml-tree.h"
+#include "MagickCore/xml-tree-private.h"
\f
/*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% CloneImageProperties() clones one or more image properties.
+% CloneImageProperties() clones all the image properties to another image.
%
% The format of the CloneImageProperties method is:
%
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
assert(clone_image != (const Image *) NULL);
assert(clone_image->signature == MagickSignature);
- if (clone_image->debug != MagickFalse)
+ if( IfMagickTrue(clone_image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
clone_image->filename);
(void) CopyMagickString(image->filename,clone_image->filename,MaxTextExtent);
image->directory=(char *) NULL;
(void) CloneString(&image->geometry,clone_image->geometry);
image->offset=clone_image->offset;
- image->x_resolution=clone_image->x_resolution;
- image->y_resolution=clone_image->y_resolution;
+ image->resolution.x=clone_image->resolution.x;
+ image->resolution.y=clone_image->resolution.y;
image->page=clone_image->page;
image->tile_offset=clone_image->tile_offset;
image->extract_info=clone_image->extract_info;
- image->bias=clone_image->bias;
image->filter=clone_image->filter;
- image->blur=clone_image->blur;
image->fuzz=clone_image->fuzz;
image->interlace=clone_image->interlace;
image->interpolate=clone_image->interpolate;
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% DefineImageProperty() associates a key/value pair with an image property.
+% DefineImageProperty() associates an assignment string of the form
+% "key=value" with per-image artifact. It is equivelent to
+% SetImageProperity().
%
% The format of the DefineImageProperty method is:
%
% MagickBooleanType DefineImageProperty(Image *image,
-% const char *property)
+% const char *property,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o property: the image property.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
MagickExport MagickBooleanType DefineImageProperty(Image *image,
- const char *property)
+ const char *property,ExceptionInfo *exception)
{
char
key[MaxTextExtent],
if (*p == '=')
(void) CopyMagickString(value,p+1,MaxTextExtent);
*p='\0';
- return(SetImageProperty(image,key,value));
+ return(SetImageProperty(image,key,value,exception));
}
\f
/*
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image->filename);
if (image->properties == (void *) NULL)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% DestroyImageProperties() releases memory associated with image property
-% values.
+% DestroyImageProperties() destroys all properities and associated memory
+% attached to the given image.
%
% The format of the DestroyDefines method is:
%
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image->filename);
if (image->properties != (void *) NULL)
char
value[MaxTextExtent];
+ ExceptionInfo
+ *exception;
+
+ MagickBooleanType
+ status;
+
ssize_t
n;
n=FormatLocaleStringList(value,MaxTextExtent,format,operands);
(void) n;
va_end(operands);
- return(SetImageProperty(image,property,value));
+ exception=AcquireExceptionInfo();
+ status=SetImageProperty(image,property,value,exception);
+ exception=DestroyExceptionInfo(exception);
+ return(status);
}
\f
/*
%
% GetImageProperty() gets a value associated with an image property.
%
+% The returned string is a constant string in the tree and should NOT be
+% freed by the caller.
+%
% The format of the GetImageProperty method is:
%
-% const char *GetImageProperty(const Image *image,const char *key)
+% const char *GetImageProperty(const Image *image,const char *key,
+% ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o key: the key.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
static char
*TraceSVGClippath(const unsigned char *,size_t,const size_t,
const size_t);
-static MagickBooleanType GetIPTCProperty(const Image *image,const char *key)
+static MagickBooleanType GetIPTCProperty(const Image *image,const char *key,
+ ExceptionInfo *exception)
{
char
*attribute,
return(MagickFalse);
}
attribute[strlen(attribute)-1]='\0';
- (void) SetImageProperty((Image *) image,key,(const char *) attribute);
+ (void) SetImageProperty((Image *) image,key,(const char *) attribute,
+ exception);
attribute=DestroyString(attribute);
return(MagickTrue);
}
return(y);
}
+static inline ssize_t MagickMin(const ssize_t x,const ssize_t y)
+{
+ if (x < y)
+ return(x);
+ return(y);
+}
+
static inline int ReadPropertyByte(const unsigned char **p,size_t *length)
{
int
return((unsigned short) (value & 0xffff));
}
-static MagickBooleanType Get8BIMProperty(const Image *image,const char *key)
+static MagickBooleanType Get8BIMProperty(const Image *image,const char *key,
+ ExceptionInfo *exception)
{
char
*attribute,
status=MagickFalse;
length=GetStringInfoLength(profile);
info=GetStringInfoDatum(profile);
- while ((length > 0) && (status == MagickFalse))
+ while ((length > 0) && IfMagickFalse(status))
{
if (ReadPropertyByte(&info,&length) != (unsigned char) '8')
continue;
continue;
if (ReadPropertyByte(&info,&length) != (unsigned char) 'M')
continue;
- id=(ssize_t) ReadPropertyMSBShort(&info,&length);
+ id=(ssize_t) ((int) ReadPropertyMSBShort(&info,&length));
if (id < (ssize_t) start)
continue;
if (id > (ssize_t) stop)
if ((count != 0) && ((size_t) count <= length))
{
resource=(char *) NULL;
- if (~(1UL*count) >= (MaxTextExtent-1))
+ if (~((size_t) count) >= (MaxTextExtent-1))
resource=(char *) AcquireQuantumMemory((size_t) count+MaxTextExtent,
sizeof(*resource));
if (resource != (char *) NULL)
No name match, scroll forward and try next.
*/
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
continue;
}
if ((*name == '#') && (sub_number != 1))
*/
sub_number--;
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
continue;
}
/*
We have the resource of interest.
*/
attribute=(char *) NULL;
- if (~(1UL*count) >= (MaxTextExtent-1))
+ if (~((size_t) count) >= (MaxTextExtent-1))
attribute=(char *) AcquireQuantumMemory((size_t) count+MaxTextExtent,
sizeof(*attribute));
if (attribute != (char *) NULL)
(void) CopyMagickMemory(attribute,(char *) info,(size_t) count);
attribute[count]='\0';
info+=count;
- length-=count;
+ length-=MagickMin(count,(ssize_t) length);
if ((id <= 1999) || (id >= 2999))
(void) SetImageProperty((Image *) image,key,(const char *)
- attribute);
+ attribute,exception);
else
{
char
else
path=TracePSClippath((unsigned char *) attribute,(size_t) count,
image->columns,image->rows);
- (void) SetImageProperty((Image *) image,key,(const char *) path);
+ (void) SetImageProperty((Image *) image,key,(const char *) path,
+ exception);
path=DestroyString(path);
}
attribute=DestroyString(attribute);
}
static MagickBooleanType GetEXIFProperty(const Image *image,
- const char *property)
+ const char *property,ExceptionInfo *exception)
{
#define MaxDirectoryStack 16
#define EXIF_DELIMITER "\n"
#define TAG_GPS_OFFSET 0x8825
#define TAG_INTEROP_OFFSET 0xa005
-#define EXIFMultipleValues(size, format, arg) \
+#define EXIFMultipleValues(size,format,arg) \
{ \
ssize_t \
component; \
value=AcquireString(buffer); \
}
-#define EXIFMultipleFractions(size, format, arg1, arg2) \
+#define EXIFMultipleFractions(size,format,arg1,arg2) \
{ \
ssize_t \
component; \
for (component=0; component < components; component++) \
{ \
length+=FormatLocaleString(buffer+length,MaxTextExtent-length, \
- format", ",arg1, arg2); \
+ format", ",(arg1),(arg2)); \
if (length >= (MaxTextExtent-1)) \
length=MaxTextExtent-1; \
p1+=size; \
*directory;
size_t
- entry,
+ entry;
+
+ ssize_t
offset;
} DirectoryInfo;
{ 0x1001c, "exif:GPSAreaInformation" },
{ 0x1001d, "exif:GPSDateStamp" },
{ 0x1001e, "exif:GPSDifferential" },
- { 0x0000, NULL}
+ { 0x00000, (const char *) NULL }
};
const StringInfo
entry,
length,
number_entries,
- tag_offset,
tag;
+ SplayTreeInfo
+ *exif_resources;
+
ssize_t
all,
id,
level,
offset,
+ tag_offset,
tag_value;
static int
}
if (length < 16)
return(MagickFalse);
- id=(ssize_t) ReadPropertyShort(LSBEndian,exif);
+ id=(ssize_t) ((int) ReadPropertyShort(LSBEndian,exif));
endian=LSBEndian;
if (id == 0x4949)
endian=LSBEndian;
This the offset to the first IFD.
*/
offset=(ssize_t) ((int) ReadPropertyLong(endian,exif+4));
- if ((size_t) offset >= length)
+ if ((offset < 0) || (size_t) offset >= length)
return(MagickFalse);
/*
Set the pointer to the first IFD and follow it were it leads.
level=0;
entry=0;
tag_offset=0;
+ exif_resources=NewSplayTree((int (*)(const void *,const void *)) NULL,
+ (void *(*)(void *)) NULL,(void *(*)(void *)) NULL);
do
{
/*
/*
Determine how many entries there are in the current IFD.
*/
- number_entries=ReadPropertyShort(endian,directory);
+ number_entries=(size_t) ((int) ReadPropertyShort(endian,directory));
for ( ; entry < number_entries; entry++)
{
register unsigned char
*q;
size_t
- format,
- number_bytes;
+ format;
ssize_t
+ number_bytes,
components;
- q=(unsigned char *) (directory+2+(12*entry));
- tag_value=(ssize_t) (ReadPropertyShort(endian,q)+tag_offset);
- format=(size_t) ReadPropertyShort(endian,q+2);
+ q=(unsigned char *) (directory+(12*entry)+2);
+ if (GetValueFromSplayTree(exif_resources,q) == q)
+ break;
+ (void) AddValueToSplayTree(exif_resources,q,q);
+ tag_value=(ssize_t) ((int) ReadPropertyShort(endian,q)+tag_offset);
+ format=(size_t) ((int) ReadPropertyShort(endian,q+2));
if (format >= (sizeof(tag_bytes)/sizeof(*tag_bytes)))
break;
components=(ssize_t) ((int) ReadPropertyLong(endian,q+4));
number_bytes=(size_t) components*tag_bytes[format];
+ if (number_bytes < components)
+ break; /* prevent overflow */
if (number_bytes <= 4)
p=q+8;
else
The directory entry contains an offset.
*/
offset=(ssize_t) ((int) ReadPropertyLong(endian,q+8));
+ if ((ssize_t) (offset+number_bytes) < offset)
+ continue; /* prevent overflow */
if ((size_t) (offset+number_bytes) > length)
continue;
p=(unsigned char *) (exif+offset);
buffer[MaxTextExtent],
*value;
+ value=(char *) NULL;
+ *buffer='\0';
switch (format)
{
case EXIF_FMT_BYTE:
case EXIF_FMT_UNDEFINED:
{
- EXIFMultipleValues(1,"%.20g",(double)
- (*(unsigned char *) p1));
+ EXIFMultipleValues(1,"%.20g",(double) (*(unsigned char *) p1));
break;
}
case EXIF_FMT_SBYTE:
case EXIF_FMT_ULONG:
{
EXIFMultipleValues(4,"%.20g",(double)
- ReadPropertyLong(endian,p1));
+ ((int) ReadPropertyLong(endian,p1)));
break;
}
case EXIF_FMT_SLONG:
{
EXIFMultipleValues(4,"%.20g",(double)
- ReadPropertyLong(endian,p1));
+ ((int) ReadPropertyLong(endian,p1)));
break;
}
case EXIF_FMT_URATIONAL:
{
EXIFMultipleFractions(8,"%.20g/%.20g",(double)
- ReadPropertyLong(endian,p1),(double)
- ReadPropertyLong(endian,p1+4));
+ ((int) ReadPropertyLong(endian,p1)),(double)
+ ((int) ReadPropertyLong(endian,p1+4)));
break;
}
case EXIF_FMT_SRATIONAL:
{
EXIFMultipleFractions(8,"%.20g/%.20g",(double)
- ReadPropertyLong(endian,p1),(double)
- ReadPropertyLong(endian,p1+4));
+ ((int) ReadPropertyLong(endian,p1)),(double)
+ ((int) ReadPropertyLong(endian,p1+4)));
break;
}
case EXIF_FMT_SINGLE:
case EXIF_FMT_STRING:
{
value=(char *) NULL;
- if (~(1UL*number_bytes) >= 1)
+ if (~((size_t) number_bytes) >= 1)
value=(char *) AcquireQuantumMemory((size_t) number_bytes+1UL,
sizeof(*value));
if (value != (char *) NULL)
if (value != (char *) NULL)
{
char
- key[MaxTextExtent];
+ *key;
register const char
*p;
- (void) CopyMagickString(key,property,MaxTextExtent);
+ key=AcquireString(property);
+ if (level == 2)
+ (void) SubstituteString(&key,"exif:","exif:thumbnail:");
switch (all)
{
case 1:
break;
}
}
- (void) FormatLocaleString(key,MaxTextExtent,"%s",
- description);
+ (void) FormatLocaleString(key,MaxTextExtent,"%s",description);
break;
}
case 2:
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
image->properties,key);
if (p == (const char *) NULL)
- (void) SetImageProperty((Image *) image,key,value);
+ (void) SetImageProperty((Image *) image,key,value,exception);
value=DestroyString(value);
+ key=DestroyString(key);
status=MagickTrue;
}
}
if ((tag_value == TAG_EXIF_OFFSET) ||
- (tag_value == TAG_INTEROP_OFFSET) ||
- (tag_value == TAG_GPS_OFFSET))
+ (tag_value == TAG_INTEROP_OFFSET) || (tag_value == TAG_GPS_OFFSET))
{
- size_t
+ ssize_t
offset;
- offset=(size_t) ReadPropertyLong(endian,p);
- if ((offset < length) && (level < (MaxDirectoryStack-2)))
+ offset=(ssize_t) ((int) ReadPropertyLong(endian,p));
+ if (((size_t) offset < length) && (level < (MaxDirectoryStack-2)))
{
- size_t
+ ssize_t
tag_offset1;
- tag_offset1=(tag_value == TAG_GPS_OFFSET) ? 0x10000UL : 0UL;
+ tag_offset1=(ssize_t) ((tag_value == TAG_GPS_OFFSET) ? 0x10000 :
+ 0);
directory_stack[level].directory=directory;
entry++;
directory_stack[level].entry=entry;
level++;
if ((directory+2+(12*number_entries)) > (exif+length))
break;
- offset=(size_t) ReadPropertyLong(endian,directory+2+(12*
- number_entries));
- if ((offset != 0) && (offset < length) &&
+ offset=(ssize_t) ((int) ReadPropertyLong(endian,directory+2+(12*
+ number_entries)));
+ if ((offset != 0) && ((size_t) offset < length) &&
(level < (MaxDirectoryStack-2)))
{
directory_stack[level].directory=exif+offset;
}
}
} while (level > 0);
+ exif_resources=DestroySplayTree(exif_resources);
return(status);
}
-static MagickBooleanType GetXMPProperty(const Image *image,
- const char *property)
+static MagickBooleanType GetXMPProperty(const Image *image,const char *property)
{
char
*xmp_profile;
}
static char *TracePSClippath(const unsigned char *blob,size_t length,
- const size_t magick_unused(columns),
- const size_t magick_unused(rows))
+ const size_t magick_unused(columns),const size_t magick_unused(rows))
{
char
*path,
in_subpath=MagickFalse;
while (length > 0)
{
- selector=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ selector=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
switch (selector)
{
case 0:
if (knot_count != 0)
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
Expected subpath length record.
*/
- knot_count=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ knot_count=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
blob+=22;
- length-=22;
+ length-=MagickMin(22,(ssize_t) length);
break;
}
case 1:
Unexpected subpath knot
*/
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
xx,
yy;
- yy=ReadPropertyMSBLong(&blob,&length);
- xx=ReadPropertyMSBLong(&blob,&length);
+ yy=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
+ xx=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
x=(ssize_t) xx;
if (xx > 2147483647)
x=(ssize_t) xx-4294967295U-1;
point[i].x=(double) x/4096/4096;
point[i].y=1.0-(double) y/4096/4096;
}
- if (in_subpath == MagickFalse)
+ if( IfMagickFalse(in_subpath) )
{
(void) FormatLocaleString(message,MaxTextExtent," %g %g m\n",
point[1].x,point[1].y);
default:
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
}
in_subpath=MagickFalse;
while (length != 0)
{
- selector=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ selector=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
switch (selector)
{
case 0:
if (knot_count != 0)
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
Expected subpath length record.
*/
- knot_count=(ssize_t) ReadPropertyMSBShort(&blob,&length);
+ knot_count=(ssize_t) ((int) ReadPropertyMSBShort(&blob,&length));
blob+=22;
- length-=22;
+ length-=MagickMin(22,(ssize_t) length);
break;
}
case 1:
Unexpected subpath knot.
*/
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
/*
xx,
yy;
- yy=ReadPropertyMSBLong(&blob,&length);
- xx=ReadPropertyMSBLong(&blob,&length);
+ yy=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
+ xx=(size_t) ((int) ReadPropertyMSBLong(&blob,&length));
x=(ssize_t) xx;
if (xx > 2147483647)
x=(ssize_t) xx-4294967295U-1;
point[i].x=(double) x*columns/4096/4096;
point[i].y=(double) y*rows/4096/4096;
}
- if (in_subpath == MagickFalse)
+ if( IfMagickFalse(in_subpath) )
{
(void) FormatLocaleString(message,MaxTextExtent,"M %g,%g\n",
point[1].x,point[1].y);
default:
{
blob+=24;
- length-=24;
+ length-=MagickMin(24,(ssize_t) length);
break;
}
}
}
MagickExport const char *GetImageProperty(const Image *image,
- const char *property)
+ const char *property,ExceptionInfo *exception)
{
- ExceptionInfo
- *exception;
-
FxInfo
*fx_info;
- MagickRealType
+ double
alpha;
MagickStatusType
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
p=(const char *) NULL;
if (image->properties != (void *) NULL)
image->properties);
return(p);
}
- if (LocaleNCompare("fx:",property,3) != 0)
+ if (LocaleNCompare("fx:",property,3) != 0) /* NOT %[fx:..] !!!! */
{
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
image->properties,property);
if ((property == (const char *) NULL) ||
(strchr(property,':') == (char *) NULL))
return(p);
- exception=(&((Image *) image)->exception);
switch (*property)
{
case '8':
{
if (LocaleNCompare("8bim:",property,5) == 0)
{
- if ((Get8BIMProperty(image,property) != MagickFalse) &&
+ if( IfMagickTrue(Get8BIMProperty(image,property,exception)) &&
(image->properties != (void *) NULL))
{
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
{
if (LocaleNCompare("exif:",property,5) == 0)
{
- if ((GetEXIFProperty(image,property) != MagickFalse) &&
+ if( IfMagickTrue(GetEXIFProperty(image,property,exception)) &&
(image->properties != (void *) NULL))
{
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
{
if (LocaleNCompare("fx:",property,3) == 0)
{
- fx_info=AcquireFxInfo(image,property+3);
- status=FxEvaluateChannelExpression(fx_info,DefaultChannels,0,0,&alpha,
- exception);
+ fx_info=AcquireFxInfo(image,property+3,exception);
+ status=FxEvaluateChannelExpression(fx_info,IntensityPixelChannel,0,0,
+ &alpha,exception);
fx_info=DestroyFxInfo(fx_info);
- if (status != MagickFalse)
+ if( IfMagickTrue(status) )
{
char
value[MaxTextExtent];
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),(double) alpha);
- (void) SetImageProperty((Image *) image,property,value);
+ (void) SetImageProperty((Image *) image,property,value,exception);
}
if (image->properties != (void *) NULL)
{
{
if (LocaleNCompare("iptc:",property,5) == 0)
{
- if ((GetIPTCProperty(image,property) != MagickFalse) &&
+ if( IfMagickTrue(GetIPTCProperty(image,property,exception)) &&
(image->properties != (void *) NULL))
{
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
pixel;
GetPixelInfo(image,&pixel);
- fx_info=AcquireFxInfo(image,property+6);
- status=FxEvaluateChannelExpression(fx_info,RedChannel,0,0,&alpha,
- exception);
- pixel.red=(MagickRealType) QuantumRange*alpha;
- status|=FxEvaluateChannelExpression(fx_info,GreenChannel,0,0,&alpha,
- exception);
- pixel.green=(MagickRealType) QuantumRange*alpha;
- status|=FxEvaluateChannelExpression(fx_info,BlueChannel,0,0,&alpha,
- exception);
- pixel.blue=(MagickRealType) QuantumRange*alpha;
+ fx_info=AcquireFxInfo(image,property+6,exception);
+ status=FxEvaluateChannelExpression(fx_info,RedPixelChannel,0,0,
+ &alpha,exception);
+ pixel.red=(double) QuantumRange*alpha;
+ status|=FxEvaluateChannelExpression(fx_info,GreenPixelChannel,0,0,
+ &alpha,exception);
+ pixel.green=(double) QuantumRange*alpha;
+ status|=FxEvaluateChannelExpression(fx_info,BluePixelChannel,0,0,
+ &alpha,exception);
+ pixel.blue=(double) QuantumRange*alpha;
if (image->colorspace == CMYKColorspace)
{
- status|=FxEvaluateChannelExpression(fx_info,BlackChannel,0,0,
+ status|=FxEvaluateChannelExpression(fx_info,BlackPixelChannel,0,0,
&alpha,exception);
- pixel.black=(MagickRealType) QuantumRange*alpha;
+ pixel.black=(double) QuantumRange*alpha;
}
- status|=FxEvaluateChannelExpression(fx_info,OpacityChannel,0,0,&alpha,
- exception);
- pixel.alpha=(MagickRealType) QuantumRange*(1.0-alpha);
+ status|=FxEvaluateChannelExpression(fx_info,AlphaPixelChannel,0,0,
+ &alpha,exception);
+ pixel.alpha=(double) QuantumRange*(1.0-alpha);
fx_info=DestroyFxInfo(fx_info);
- if (status != MagickFalse)
+ if( IfMagickTrue(status) )
{
char
name[MaxTextExtent];
- (void) QueryMagickColorname(image,&pixel,SVGCompliance,name,
+ (void) QueryColorname(image,&pixel,SVGCompliance,name,
exception);
- (void) SetImageProperty((Image *) image,property,name);
- return(GetImageProperty(image,property));
+ (void) SetImageProperty((Image *) image,property,name,exception);
+ return(GetImageProperty(image,property,exception));
}
}
break;
{
if (LocaleNCompare("xmp:",property,4) == 0)
{
- if ((GetXMPProperty(image,property) != MagickFalse) &&
+ if( IfMagickTrue(GetXMPProperty(image,property)) &&
(image->properties != (void *) NULL))
{
p=(const char *) GetValueFromSplayTree((SplayTreeInfo *)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% GetMagickProperty() gets a value associated with an image property.
+% GetMagickProperty() gets attributes or calculated values that is associated
+% with a fixed known property name, or single letter property.
+%
+% This does not return, special profile or property expressions. Nor does it
+% return free-form property strings, unless referenced by a single letter
+% property name.
+%
+% The returned string is stored as the image artifact 'get-property' (not as
+% another property), and as such should not be freed. Later calls however
+% will overwrite this value so if needed for a longer period a copy should be
+% made. This artifact can be deleted when no longer required.
%
% The format of the GetMagickProperty method is:
%
-% const char *GetMagickProperty(const ImageInfo *image_info,
-% Image *image,const char *key)
+% const char *GetMagickProperty(const ImageInfo *image_info,Image *image,
+% const char *property,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o key: the key.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
+static const char *GetMagickPropertyLetter(const ImageInfo *image_info,
+ Image *image,const char letter,ExceptionInfo *exception)
+{
+ char
+ value[MaxTextExtent];
+
+ const char
+ *string;
+
+ if (image != (Image *) NULL && IfMagickTrue(image->debug))
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ *value='\0'; /* formatted string */
+ string=(char *) NULL; /* constant string reference */
+ switch (letter)
+ {
+ case 'b': /* image size read in - in bytes */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ ((MagickOffsetType) image->extent));
+ if (image->extent != (MagickSizeType) ((size_t) image->extent))
+ (void) FormatMagickSize(image->extent,MagickFalse,value);
+ ConcatenateMagickString(value,"B",MaxTextExtent);
+ break;
+ }
+ case 'c': /* image comment property - empty string by default */
+ {
+ string=GetImageProperty(image,"comment",exception);
+ if (string == (const char *) NULL)
+ string="";
+ break;
+ }
+ case 'd': /* Directory component of filename */
+ {
+ GetPathComponent(image->magick_filename,HeadPath,value);
+ break;
+ }
+ case 'e': /* Filename extension (suffix) of image file */
+ {
+ GetPathComponent(image->magick_filename,ExtensionPath,value);
+ break;
+ }
+ case 'f': /* Filename without directory component */
+ {
+ GetPathComponent(image->magick_filename,TailPath,value);
+ break;
+ }
+ case 'g': /* Image geometry, canvas and offset %Wx%H+%X+%Y */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20gx%.20g%+.20g%+.20g",
+ (double) image->page.width,(double) image->page.height,
+ (double) image->page.x,(double) image->page.y);
+ break;
+ }
+ case 'h': /* Image height (current) */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ (image->rows != 0 ? image->rows : image->magick_rows));
+ break;
+ }
+ case 'i': /* Filename last used for image (read or write) */
+ {
+ string=image->filename;
+ break;
+ }
+ case 'k': /* Number of unique colors */
+ {
+ /*
+ FUTURE: ensure this does not generate the formatted comment!
+ */
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ GetNumberColors(image,(FILE *) NULL,exception));
+ break;
+ }
+ case 'l': /* Image label property - empty string by default */
+ {
+ string=GetImageProperty(image,"label",exception);
+ if ( string == (const char *)NULL)
+ string="";
+ break;
+ }
+ case 'm': /* Image format (file magick) */
+ {
+ string=image->magick;
+ break;
+ }
+ case 'n': /* Number of images in the list. */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ GetImageListLength(image));
+ break;
+ }
+ case 'o': /* Output Filename - for delegate use only */
+ {
+ string=image_info->filename;
+ break;
+ }
+ case 'p': /* Image index in current image list -- As 'n' OBSOLETE */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ GetImageIndexInList(image));
+ break;
+ }
+ case 'q': /* Quantum depth of image in memory */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ MAGICKCORE_QUANTUM_DEPTH);
+ break;
+ }
+ case 'r': /* Image storage class and colorspace. */
+ {
+ ColorspaceType
+ colorspace;
+
+ colorspace=image->colorspace;
+ if (IfMagickTrue(IsImageGray(image,exception)))
+ colorspace=GRAYColorspace;
+ (void) FormatLocaleString(value,MaxTextExtent,"%s %s %s",
+ CommandOptionToMnemonic(MagickClassOptions,(ssize_t) image->storage_class),
+ CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t) colorspace),
+ image->alpha_trait == BlendPixelTrait ? "Matte" : "");
+ break;
+ }
+ case 's': /* Image scene number */
+ {
+ if (image_info->number_scenes != 0)
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image_info->scene);
+ else
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->scene);
+ break;
+ }
+ case 't': /* Base filename without directory or extention */
+ {
+ GetPathComponent(image->magick_filename,BasePath,value);
+ break;
+ }
+ case 'u': /* Unique filename */
+ {
+ string=image_info->unique;
+ break;
+ }
+ case 'w': /* Image width (current) */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ (image->columns != 0 ? image->columns : image->magick_columns));
+ break;
+ }
+ case 'x': /* Image horizontal resolution (with units) */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%g %s",
+ image->resolution.x,CommandOptionToMnemonic(
+ MagickResolutionOptions,(ssize_t)image->units));
+ break;
+ }
+ case 'y': /* Image vertical resolution (with units) */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%g %s",
+ image->resolution.y,CommandOptionToMnemonic(MagickResolutionOptions,
+ (ssize_t) image->units));
+ break;
+ }
+ case 'z': /* Image depth as read in */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->depth);
+ break;
+ }
+ case 'A': /* Image alpha channel */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%s",
+ CommandOptionToMnemonic(MagickBooleanOptions,(ssize_t) image->alpha_trait));
+ break;
+ }
+ case 'C': /* Image compression method. */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%s",
+ CommandOptionToMnemonic(MagickCompressOptions,(ssize_t)
+ image->compression));
+ break;
+ }
+ case 'D': /* Image dispose method. */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%s",
+ CommandOptionToMnemonic(MagickDisposeOptions,(ssize_t) image->dispose));
+ break;
+ }
+ case 'G': /* Image size as geometry = "%wx%h" */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20gx%.20g",
+ (double)image->magick_columns,(double) image->magick_rows);
+ break;
+ }
+ case 'H': /* layer canvas height */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->page.height);
+ break;
+ }
+ case 'M': /* Magick filename - filename given incl. coder & read mods */
+ {
+ string=image->magick_filename;
+ break;
+ }
+ case 'O': /* layer canvas offset with sign = "+%X+%Y" */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%+ld%+ld",(long)
+ image->page.x,(long) image->page.y);
+ break;
+ }
+ case 'P': /* layer canvas page size = "%Wx%H" */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20gx%.20g",
+ (double) image->page.width,(double) image->page.height);
+ break;
+ }
+ case 'Q': /* image compression quality */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->quality);
+ break;
+ }
+ case 'S': /* Image scenes ???? */
+ {
+ if (image_info->number_scenes == 0)
+ string="2147483647";
+ else
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image_info->scene+image_info->number_scenes);
+ break;
+ }
+ case 'T': /* image time delay for animations */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->delay);
+ break;
+ }
+ case 'W': /* layer canvas width */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->page.width);
+ break;
+ }
+ case 'X': /* layer canvas X offset */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%+.20g",(double)
+ image->page.x);
+ break;
+ }
+ case 'Y': /* layer canvas Y offset */
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%+.20g",(double)
+ image->page.y);
+ break;
+ }
+ case 'Z': /* Zero filename ??? */
+ {
+ string=image_info->zero;
+ break;
+ }
+ case '@': /* Trim bounding box, without Trimming! */
+ {
+ RectangleInfo
+ page;
+
+ page=GetImageBoundingBox(image,exception);
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20gx%.20g%+.20g%+.20g",
+ (double) page.width,(double) page.height,(double) page.x,(double)
+ page.y);
+ break;
+ }
+ case '#': /* Image signature */
+ {
+ (void) SignatureImage(image,exception);
+ string=GetImageProperty(image,"signature",exception);
+ break;
+ }
+ case '%': /* percent escaped */
+ {
+ string="%";
+ break;
+ }
+ }
+ if (*value != '\0')
+ string=value;
+ if (string != (char *) NULL)
+ {
+ (void) SetImageArtifact(image,"get-property",string);
+ return(GetImageArtifact(image,"get-property"));
+ }
+ return((char *)NULL);
+}
+
MagickExport const char *GetMagickProperty(const ImageInfo *image_info,
- Image *image,const char *property)
+ Image *image,const char *property,ExceptionInfo *exception)
{
char
- value[MaxTextExtent],
- filename[MaxTextExtent];
+ value[MaxTextExtent];
- *value='\0';
+ const char
+ *string;
+
+ assert(property[0] != '\0');
+ if (property[1] == '\0') /* single letter property request */
+ return(GetMagickPropertyLetter(image_info,image,*property,exception));
+ if ((image != (Image *) NULL) && IfMagickTrue(image->debug))
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+ *value='\0'; /* formated string */
+ string=(char *) NULL; /* constant string reference */
switch (*property)
{
case 'b':
{
- if (LocaleNCompare("base",property,4) == 0)
+ if ((LocaleCompare("base",property) == 0) ||
+ (LocaleCompare("basename",property) == 0) )
{
- GetPathComponent(image->magick_filename,BasePath,filename);
- (void) CopyMagickString(value,filename,MaxTextExtent);
+ GetPathComponent(image->magick_filename,BasePath,value);
break;
}
break;
}
case 'c':
{
- if (LocaleNCompare("channels",property,8) == 0)
+ if (LocaleCompare("channels",property) == 0)
{
- /*
- Image channels.
- */
+ /* FUTURE: return actual image channels */
(void) FormatLocaleString(value,MaxTextExtent,"%s",
CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t)
image->colorspace));
LocaleLower(value);
- if (image->matte != MagickFalse)
+ if( image->alpha_trait == BlendPixelTrait )
(void) ConcatenateMagickString(value,"a",MaxTextExtent);
break;
}
- if (LocaleNCompare("colorspace",property,10) == 0)
+ if (LocaleCompare("colorspace",property) == 0)
{
ColorspaceType
colorspace;
- /*
- Image storage class and colorspace.
- */
+ /* FUTURE: return actual colorspace - no 'gray' stuff */
colorspace=image->colorspace;
- if (IsImageGray(image,&image->exception) != MagickFalse)
+ if( IfMagickTrue(IsImageGray(image,exception)) )
colorspace=GRAYColorspace;
- (void) FormatLocaleString(value,MaxTextExtent,"%s",
- CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t)
- colorspace));
+ string=CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t)
+ colorspace);
break;
}
- if (LocaleNCompare("copyright",property,9) == 0)
+ if (LocaleCompare("copyright",property) == 0)
{
(void) CopyMagickString(value,GetMagickCopyright(),MaxTextExtent);
break;
}
case 'd':
{
- if (LocaleNCompare("depth",property,5) == 0)
+ if (LocaleCompare("depth",property) == 0)
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
image->depth);
break;
}
- if (LocaleNCompare("directory",property,9) == 0)
+ if (LocaleCompare("directory",property) == 0)
{
- GetPathComponent(image->magick_filename,HeadPath,filename);
- (void) CopyMagickString(value,filename,MaxTextExtent);
+ GetPathComponent(image->magick_filename,HeadPath,value);
break;
}
break;
}
case 'e':
{
- if (LocaleNCompare("extension",property,9) == 0)
+ if (LocaleCompare("extension",property) == 0)
{
- GetPathComponent(image->magick_filename,ExtensionPath,filename);
- (void) CopyMagickString(value,filename,MaxTextExtent);
+ GetPathComponent(image->magick_filename,ExtensionPath,value);
break;
}
break;
}
case 'g':
{
- if (LocaleNCompare("group",property,5) == 0)
+ if (LocaleCompare("gamma",property) == 0)
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%.*g",
+ GetMagickPrecision(),image->gamma);
+ break;
+ }
+ if ( (image_info != (ImageInfo *) NULL) &&
+ (LocaleCompare("group",property) == 0) )
{
- (void) FormatLocaleString(value,MaxTextExtent,"0x%lx",
- (unsigned long) image_info->group);
+ (void) FormatLocaleString(value,MaxTextExtent,"0x%lx",(unsigned long)
+ image_info->group);
break;
}
break;
}
case 'h':
{
- if (LocaleNCompare("height",property,6) == 0)
+ if (LocaleCompare("height",property) == 0)
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",
image->magick_rows != 0 ? (double) image->magick_rows : 256.0);
}
case 'i':
{
- if (LocaleNCompare("input",property,5) == 0)
+ if (LocaleCompare("input",property) == 0)
{
- (void) CopyMagickString(value,image->filename,MaxTextExtent);
+ string=image->filename;
break;
}
break;
}
case 'k':
{
- if (LocaleNCompare("kurtosis",property,8) == 0)
+ if (LocaleCompare("kurtosis",property) == 0)
{
double
kurtosis,
skewness;
- (void) GetImageChannelKurtosis(image,image_info->channel,&kurtosis,
- &skewness,&image->exception);
+ (void) GetImageKurtosis(image,&kurtosis,&skewness,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),kurtosis);
break;
}
case 'm':
{
- if (LocaleNCompare("magick",property,6) == 0)
+ if (LocaleCompare("magick",property) == 0)
{
- (void) CopyMagickString(value,image->magick,MaxTextExtent);
+ string=image->magick;
break;
}
- if (LocaleNCompare("max",property,3) == 0)
+ if (LocaleCompare("max",property) == 0)
{
double
maximum,
minimum;
- (void) GetImageChannelRange(image,image_info->channel,&minimum,
- &maximum,&image->exception);
+ (void) GetImageRange(image,&minimum,&maximum,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),maximum);
break;
}
- if (LocaleNCompare("mean",property,4) == 0)
+ if (LocaleCompare("mean",property) == 0)
{
double
mean,
standard_deviation;
- (void) GetImageChannelMean(image,image_info->channel,&mean,
- &standard_deviation,&image->exception);
+ (void) GetImageMean(image,&mean,&standard_deviation,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),mean);
break;
}
- if (LocaleNCompare("min",property,3) == 0)
+ if (LocaleCompare("min",property) == 0)
{
double
maximum,
minimum;
- (void) GetImageChannelRange(image,image_info->channel,&minimum,
- &maximum,&image->exception);
+ (void) GetImageRange(image,&minimum,&maximum,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),minimum);
break;
}
break;
}
- case 'n':
- {
- if (LocaleNCompare("name",property,4) == 0)
- {
- (void) CopyMagickString(value,filename,MaxTextExtent);
- break;
- }
- break;
- }
case 'o':
{
- if (LocaleNCompare("opaque",property,6) == 0)
+ if (LocaleCompare("opaque",property) == 0)
{
MagickBooleanType
opaque;
- opaque=IsImageOpaque(image,&image->exception);
- (void) CopyMagickString(value,opaque == MagickFalse ? "false" :
- "true",MaxTextExtent);
+ opaque=IsImageOpaque(image,exception);
+ (void) CopyMagickString(value,IfMagickTrue(opaque) ? "true" : "false",
+ MaxTextExtent);
+ break;
+ }
+ if (LocaleCompare("orientation",property) == 0)
+ {
+ string=CommandOptionToMnemonic(MagickOrientationOptions,(ssize_t)
+ image->orientation);
break;
}
- if (LocaleNCompare("output",property,6) == 0)
+ if ((image_info != (ImageInfo *) NULL) &&
+ (LocaleCompare("output",property) == 0))
{
(void) CopyMagickString(value,image_info->filename,MaxTextExtent);
break;
}
case 'p':
{
- if (LocaleNCompare("page",property,4) == 0)
+ if (LocaleCompare("page",property) == 0)
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
- GetImageIndexInList(image)+1);
+ GetImageIndexInList(image)+1);
+ break;
+ }
+ break;
+ }
+ case 'r':
+ {
+ /* This matches %[fx:resolution.x] */
+ if (LocaleCompare("resolution.x",property) == 0)
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%g",
+ image->resolution.x);
+ break;
+ }
+ /* This matches %[fx:resolution.y] */
+ if (LocaleCompare("resolution.y",property) == 0)
+ {
+ (void) FormatLocaleString(value,MaxTextExtent,"%g",
+ image->resolution.y);
break;
}
break;
}
case 's':
{
- if (LocaleNCompare("size",property,4) == 0)
+ if (LocaleCompare("scene",property) == 0)
{
- char
- format[MaxTextExtent];
-
- (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format);
- (void) FormatLocaleString(value,MaxTextExtent,"%sB",format);
+ if ((image_info != (ImageInfo *) NULL) &&
+ (image_info->number_scenes != 0))
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image_info->scene);
+ else
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
+ image->scene);
break;
}
- if (LocaleNCompare("scenes",property,6) == 0)
+ if (LocaleCompare("scenes",property) == 0)
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
GetImageListLength(image));
break;
}
- if (LocaleNCompare("scene",property,5) == 0)
+ if (LocaleCompare("size",property) == 0)
{
- (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
- image->scene);
- if (image_info->number_scenes != 0)
- (void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
- image_info->scene);
+ char
+ format[MaxTextExtent];
+
+ (void) FormatMagickSize(GetBlobSize(image),MagickFalse,format);
+ (void) FormatLocaleString(value,MaxTextExtent,"%sB",format);
break;
}
- if (LocaleNCompare("skewness",property,8) == 0)
+ if (LocaleCompare("skewness",property) == 0)
{
double
kurtosis,
skewness;
- (void) GetImageChannelKurtosis(image,image_info->channel,&kurtosis,
- &skewness,&image->exception);
+ (void) GetImageKurtosis(image,&kurtosis,&skewness,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),skewness);
break;
}
- if ((LocaleNCompare("standard-deviation",property,18) == 0) ||
- (LocaleNCompare("standard_deviation",property,18) == 0))
+ if (LocaleCompare("standard-deviation",property) == 0)
{
double
mean,
standard_deviation;
- (void) GetImageChannelMean(image,image_info->channel,&mean,
- &standard_deviation,&image->exception);
+ (void) GetImageMean(image,&mean,&standard_deviation,exception);
(void) FormatLocaleString(value,MaxTextExtent,"%.*g",
GetMagickPrecision(),standard_deviation);
break;
}
break;
}
+ case 't':
+ {
+ if (LocaleCompare("type",property) == 0)
+ {
+ string=CommandOptionToMnemonic(MagickTypeOptions,(ssize_t)
+ GetImageType(image,exception));
+ break;
+ }
+ break;
+ }
case 'u':
{
- if (LocaleNCompare("unique",property,6) == 0)
+ if ((image_info != (ImageInfo *) NULL) &&
+ (LocaleCompare("unique",property) == 0))
{
- (void) CopyMagickString(filename,image_info->unique,MaxTextExtent);
- (void) CopyMagickString(value,filename,MaxTextExtent);
+ string=image_info->unique;
break;
}
break;
}
case 'v':
{
- if (LocaleNCompare("version",property,7) == 0)
+ if (LocaleCompare("version",property) == 0)
{
- (void) CopyMagickString(value,GetMagickVersion((size_t *) NULL),
- MaxTextExtent);
+ string=GetMagickVersion((size_t *) NULL);
break;
}
break;
}
case 'w':
{
- if (LocaleNCompare("width",property,5) == 0)
+ if (LocaleCompare("width",property) == 0)
{
(void) FormatLocaleString(value,MaxTextExtent,"%.20g",(double)
(image->magick_columns != 0 ? image->magick_columns : 256));
}
break;
}
- case 'x':
+ case 'x': /* FUTURE: Obsolete X resolution */
{
- if (LocaleNCompare("xresolution",property,11) == 0)
+ if ((LocaleCompare("xresolution",property) == 0) ||
+ (LocaleCompare("x-resolution",property) == 0) )
{
- (void) FormatLocaleString(value,MaxTextExtent,"%g",
- image->x_resolution);
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",
+ image->resolution.x);
break;
}
break;
}
- case 'y':
+ case 'y': /* FUTURE: Obsolete Y resolution */
{
- if (LocaleNCompare("yresolution",property,11) == 0)
+ if ((LocaleCompare("yresolution",property) == 0) ||
+ (LocaleCompare("y-resolution",property) == 0) )
{
- (void) FormatLocaleString(value,MaxTextExtent,"%g",
- image->y_resolution);
+ (void) FormatLocaleString(value,MaxTextExtent,"%.20g",
+ image->resolution.y);
break;
}
break;
}
case 'z':
{
- if (LocaleNCompare("zero",property,4) == 0)
+ if ((image_info != (ImageInfo *) NULL) &&
+ (LocaleCompare("zero",property) == 0))
{
- (void) CopyMagickString(filename,image_info->zero,MaxTextExtent);
- (void) CopyMagickString(value,filename,MaxTextExtent);
+ string=image_info->zero;
break;
}
break;
}
}
if (*value != '\0')
- {
- if (image->properties == (void *) NULL)
- image->properties=NewSplayTree(CompareSplayTreeString,
- RelinquishMagickMemory,RelinquishMagickMemory);
- (void) AddValueToSplayTree((SplayTreeInfo *) image->properties,
- ConstantString(property),ConstantString(value));
- }
- return(GetImageProperty(image,property));
+ string=value;
+ if (string != (char *)NULL)
+ {
+ (void) SetImageArtifact(image,"get-property", string);
+ return(GetImageArtifact(image,"get-property"));
+ }
+ return((char *)NULL);
}
\f
/*
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% GetNextImageProperty() gets the next image property value.
+% GetNextImageProperty() gets the next free-form string property name.
%
% The format of the GetNextImageProperty method is:
%
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image->filename);
if (image->properties == (void *) NULL)
% InterpretImageProperties() replaces any embedded formatting characters with
% the appropriate image property and returns the interpreted text.
%
+% This searches for and replaces
+% \n \r \% replaced by newline, return, and percent resp.
+% < > & replaced by '<', '>', '&' resp.
+% %% replaced by percent
+%
+% %x %[x] where 'x' is a single letter properity, case sensitive).
+% %[type:name] where 'type' a is special and known prefix.
+% %[name] where 'name' is a specifically known attribute, calculated
+% value, or a per-image property string name, or a per-image
+% 'artifact' (as generated from a global option).
+% It may contain ':' as long as the prefix is not special.
+%
+% Single letter % substitutions will only happen if the character before the
+% percent is NOT a number. But braced substitutions will always be performed.
+% This prevents the typical usage of percent in a interpreted geometry
+% argument from being substituted when the percent is a geometry flag.
+%
+% If 'glob-expresions' ('*' or '?' characters) is used for 'name' it may be
+% used as a search pattern to print multiple lines of "name=value\n" pairs of
+% the associacted set of properities.
+%
+% The returned string must be freed using DestoryString() by the caller.
+%
% The format of the InterpretImageProperties method is:
%
-% char *InterpretImageProperties(const ImageInfo *image_info,Image *image,
-% const char *embed_text)
+% char *InterpretImageProperties(const ImageInfo *image_info,
+% Image *image,const char *embed_text,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
% o embed_text: the address of a character string containing the embedded
% formatting characters.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
MagickExport char *InterpretImageProperties(const ImageInfo *image_info,
- Image *image,const char *embed_text)
+ Image *image,const char *embed_text,ExceptionInfo *exception)
{
char
- filename[MaxTextExtent],
- *interpret_text,
- *text;
-
- const char
- *value;
+ *interpret_text;
register char
*q;
register const char
*p;
- register ssize_t
- i;
-
size_t
extent,
length;
+ MagickBooleanType
+ number;
+
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
- if ((embed_text == (const char *) NULL) || (*embed_text == '\0'))
+
+ if ((embed_text == (const char *) NULL))
return((char *) NULL);
- text=(char *) embed_text;
- if ((*text == '@') && ((*(text+1) == '-') ||
- (IsPathAccessible(text+1) != MagickFalse)))
- return(FileToString(embed_text+1,~0,&image->exception));
+ p=embed_text;
+
+ if (*p == '\0')
+ return(ConstantString(""));
+
+ /* handle a '@' replace string from file */
+ if (*p == '@') {
+ p++;
+ if (*p != '-' && IfMagickFalse(IsPathAccessible(p)) ) {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnableToAccessPath","%s",p);
+ return((char *) NULL);
+ }
+ return(FileToString(p,~0,exception));
+ }
+
/*
Translate any embedded format characters.
*/
- interpret_text=AcquireString(text);
- extent=MaxTextExtent;
- p=text;
- for (q=interpret_text; *p != '\0'; p++)
+ interpret_text=AcquireString(embed_text); /* new string with extra space */
+ extent=MaxTextExtent; /* how many extra space */
+ number=MagickFalse; /* is last char a number? */
+ for (q=interpret_text; *p!='\0'; number=IsMagickTrue(isdigit(*p)),p++)
{
*q='\0';
if ((size_t) (q-interpret_text+MaxTextExtent) >= extent)
interpret_text=(char *) ResizeQuantumMemory(interpret_text,extent+
MaxTextExtent+1,sizeof(*interpret_text));
if (interpret_text == (char *) NULL)
- break;
+ return((char *) NULL);
q=interpret_text+strlen(interpret_text);
}
/*
- Process formatting characters in text.
+ Look for the various escapes, (and handle other specials)
*/
- if ((*p == '\\') && (*(p+1) == 'r'))
- {
- *q++='\r';
- p++;
- continue;
- }
- if ((*p == '\\') && (*(p+1) == 'n'))
- {
- *q++='\n';
- p++;
+ switch (*p) {
+ case '\\':
+ switch (*(p+1)) {
+ case '\0':
+ continue;
+ case 'r': /* convert to RETURN */
+ *q++='\r';
+ p++;
+ continue;
+ case 'n': /* convert to NEWLINE */
+ *q++='\n';
+ p++;
+ continue;
+ case '\n': /* EOL removal UNIX,MacOSX */
+ p++;
+ continue;
+ case '\r': /* EOL removal DOS,Windows */
+ p++;
+ if (*p == '\n') /* return-newline EOL */
+ p++;
+ continue;
+ default:
+ p++;
+ *q++=(*p);
+ continue;
+ }
+ continue; /* never reached! */
+ case '&':
+ if (LocaleNCompare("<",p,4) == 0)
+ *q++='<', p+=3;
+ else if (LocaleNCompare(">",p,4) == 0)
+ *q++='>', p+=3;
+ else if (LocaleNCompare("&",p,5) == 0)
+ *q++='&', p+=4;
+ else
+ *q++=(*p);
continue;
- }
- if (*p == '\\')
- {
- p++;
- *q++=(*p);
+ case '%':
+ break; /* continue to next set of handlers */
+ default:
+ *q++=(*p); /* any thing else is 'as normal' */
continue;
- }
- if (*p != '%')
- {
- *q++=(*p);
+ }
+ p++; /* advance beyond the percent */
+
+ /*
+ Doubled Percent - or percent at end of string
+ */
+ if ( *p == '\0' )
+ p--;
+ if ( *p == '%' ) {
+ *q++='%';
continue;
}
- p++;
- switch (*p)
- {
- case 'b':
- {
- char
- format[MaxTextExtent];
- /*
- File size.
- */
- (void) FormatLocaleString(format,MaxTextExtent,"%.20g",(double)
- ((MagickOffsetType) image->extent));
- if (image->extent != (MagickSizeType) ((size_t) image->extent))
- (void) FormatMagickSize(image->extent,MagickFalse,format);
- q+=ConcatenateMagickString(q,format,extent);
- q+=ConcatenateMagickString(q,"B",extent);
- break;
+ /*
+ Single letter escapes %c
+ */
+ if ( *p != '[' ) {
+ const char
+ *value;
+
+ /* But only if not preceeded by a number! */
+ if ( IfMagickTrue(number) ) {
+ *q++='%'; /* do NOT substitute the percent */
+ p--; /* back up one */
+ continue;
}
- case 'c':
- {
- /*
- Image comment.
- */
- value=GetImageProperty(image,"comment");
- if (value == (const char *) NULL)
- break;
+ value=GetMagickPropertyLetter(image_info,image,*p, exception);
+ if (value != (char *) NULL) {
length=strlen(value);
if ((size_t) (q-interpret_text+length+1) >= extent)
{
extent+=length;
- interpret_text=(char *) ResizeQuantumMemory(interpret_text,extent+
- MaxTextExtent,sizeof(*interpret_text));
+ interpret_text=(char *) ResizeQuantumMemory(interpret_text,
+ extent+MaxTextExtent,sizeof(*interpret_text));
if (interpret_text == (char *) NULL)
- break;
+ return((char *)NULL);
q=interpret_text+strlen(interpret_text);
}
(void) CopyMagickString(q,value,extent);
q+=length;
- break;
- }
- case 'd':
- case 'e':
- case 'f':
- case 't':
- {
- /*
- Label segment is the base of the filename.
- */
- if (*image->magick_filename == '\0')
- break;
- switch (*p)
- {
- case 'd':
- {
- /*
- Directory.
- */
- GetPathComponent(image->magick_filename,HeadPath,filename);
- q+=CopyMagickString(q,filename,extent);
- break;
- }
- case 'e':
- {
- /*
- Filename extension.
- */
- GetPathComponent(image->magick_filename,ExtensionPath,filename);
- q+=CopyMagickString(q,filename,extent);
- break;
- }
- case 'f':
- {
- /*
- Filename.
- */
- GetPathComponent(image->magick_filename,TailPath,filename);
- q+=CopyMagickString(q,filename,extent);
- break;
- }
- case 't':
- {
- /*
- Base filename.
- */
- GetPathComponent(image->magick_filename,BasePath,filename);
- q+=CopyMagickString(q,filename,extent);
- break;
- }
- }
- break;
- }
- case 'g':
- {
- /*
- Image geometry.
- */
- q+=FormatLocaleString(q,extent,"%.20gx%.20g%+.20g%+.20g",(double)
- image->page.width,(double) image->page.height,(double) image->page.x,
- (double) image->page.y);
- break;
- }
- case 'h':
- {
- /*
- Image height.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double) (image->rows != 0 ?
- image->rows : image->magick_rows));
- break;
- }
- case 'i':
- {
- /*
- Image filename.
- */
- q+=CopyMagickString(q,image->filename,extent);
- break;
- }
- case 'k':
- {
- /*
- Number of unique colors.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double) GetNumberColors(image,
- (FILE *) NULL,&image->exception));
- break;
- }
- case 'l':
- {
- /*
- Image label.
- */
- value=GetImageProperty(image,"label");
- if (value == (const char *) NULL)
- break;
- length=strlen(value);
- if ((size_t) (q-interpret_text+length+1) >= extent)
- {
- extent+=length;
- interpret_text=(char *) ResizeQuantumMemory(interpret_text,extent+
- MaxTextExtent,sizeof(*interpret_text));
- if (interpret_text == (char *) NULL)
- break;
- q=interpret_text+strlen(interpret_text);
- }
- q+=CopyMagickString(q,value,extent);
- break;
- }
- case 'm':
- {
- /*
- Image format.
- */
- q+=CopyMagickString(q,image->magick,extent);
- break;
- }
- case 'M':
- {
- /*
- Image magick filename.
- */
- q+=CopyMagickString(q,image->magick_filename,extent);
- break;
- }
- case 'n':
- {
- /*
- Number of images in the list.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double)
- GetImageListLength(image));
- break;
- }
- case 'o':
- {
- /*
- Image output filename.
- */
- q+=CopyMagickString(q,image_info->filename,extent);
- break;
- }
- case 'p':
- {
- /*
- Image index in list.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double)
- GetImageIndexInList(image));
- break;
- }
- case 'q':
- {
- /*
- Image depth.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double)
- MAGICKCORE_QUANTUM_DEPTH);
- break;
+ continue;
}
- case 'r':
- {
- ColorspaceType
- colorspace;
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionWarning,"UnknownImageProperty","\"%%%c\"",*p);
+ continue;
+ }
- /*
- Image storage class and colorspace.
- */
- colorspace=image->colorspace;
- if (IsImageGray(image,&image->exception) != MagickFalse)
- colorspace=GRAYColorspace;
- q+=FormatLocaleString(q,extent,"%s%s%s",CommandOptionToMnemonic(
- MagickClassOptions,(ssize_t) image->storage_class),
- CommandOptionToMnemonic(MagickColorspaceOptions,(ssize_t) colorspace),
- image->matte != MagickFalse ? "Matte" : "");
- break;
- }
- case 's':
- {
- /*
- Image scene number.
- */
- if (image_info->number_scenes == 0)
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->scene);
- else
- q+=FormatLocaleString(q,extent,"%.20g",(double) image_info->scene);
- break;
- }
- case 'u':
- {
- /*
- Unique filename.
- */
- (void) CopyMagickString(filename,image_info->unique,extent);
- q+=CopyMagickString(q,filename,extent);
- break;
- }
- case 'w':
- {
- /*
- Image width.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double) (image->columns != 0 ?
- image->columns : image->magick_columns));
- break;
- }
- case 'x':
- {
- /*
- Image horizontal resolution.
- */
- q+=FormatLocaleString(q,extent,"%g %s",image->x_resolution,
- CommandOptionToMnemonic(MagickResolutionOptions,(ssize_t)
- image->units));
- break;
- }
- case 'y':
- {
- /*
- Image vertical resolution.
- */
- q+=FormatLocaleString(q,extent,"%g %s",image->y_resolution,
- CommandOptionToMnemonic(MagickResolutionOptions,(ssize_t)
- image->units));
- break;
- }
- case 'z':
- {
- /*
- Image depth.
- */
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->depth);
- break;
- }
- case 'A':
- {
- /*
- Image alpha channel.
- */
- q+=FormatLocaleString(q,extent,"%s",CommandOptionToMnemonic(
- MagickBooleanOptions,(ssize_t) image->matte));
- break;
- }
- case 'C':
- {
- /*
- Image compression method.
- */
- q+=FormatLocaleString(q,extent,"%s",CommandOptionToMnemonic(
- MagickCompressOptions,(ssize_t) image->compression));
- break;
- }
- case 'D':
- {
- /*
- Image dispose method.
- */
- q+=FormatLocaleString(q,extent,"%s",CommandOptionToMnemonic(
- MagickDisposeOptions,(ssize_t) image->dispose));
- break;
- }
- case 'G':
- {
- q+=FormatLocaleString(q,extent,"%.20gx%.20g",(double)
- image->magick_columns,(double) image->magick_rows);
- break;
- }
- case 'H':
- {
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->page.height);
- break;
- }
- case 'O':
- {
- q+=FormatLocaleString(q,extent,"%+ld%+ld",(long) image->page.x,(long)
- image->page.y);
- break;
- }
- case 'P':
- {
- q+=FormatLocaleString(q,extent,"%.20gx%.20g",(double) image->page.width,
- (double) image->page.height);
- break;
- }
- case 'Q':
- {
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->quality);
- break;
- }
- case 'S':
- {
- /*
- Image scenes.
- */
- if (image_info->number_scenes == 0)
- q+=CopyMagickString(q,"2147483647",extent);
- else
- q+=FormatLocaleString(q,extent,"%.20g",(double) (image_info->scene+
- image_info->number_scenes));
- break;
- }
- case 'T':
- {
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->delay);
- break;
- }
- case 'W':
- {
- q+=FormatLocaleString(q,extent,"%.20g",(double) image->page.width);
- break;
- }
- case 'X':
- {
- q+=FormatLocaleString(q,extent,"%+.20g",(double) image->page.x);
+ /*
+ Braced Percent Escape %[...]
+ */
+ {
+ char
+ pattern[MaxTextExtent];
+
+ const char
+ *key,
+ *value;
+
+ register ssize_t
+ len;
+
+ ssize_t
+ depth;
+
+ /* get the string framed by the %[...] */
+ p++; /* advance p to just inside the opening brace */
+ depth=1;
+ if ( *p == ']' ) {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionWarning,"UnknownImageProperty","\"%%[]\"");
break;
}
- case 'Y':
+ for (len=0; len<(MaxTextExtent-1L) && (*p != '\0');)
{
- q+=FormatLocaleString(q,extent,"%+.20g",(double) image->page.y);
- break;
+ /* skip escaped braces within braced pattern */
+ if ( (*p == '\\') && (*(p+1) != '\0') ) {
+ pattern[len++]=(*p++);
+ pattern[len++]=(*p++);
+ continue;
+ }
+ if (*p == '[')
+ depth++;
+ if (*p == ']')
+ depth--;
+ if (depth <= 0)
+ break;
+ pattern[len++]=(*p++);
}
- case 'Z':
- {
- /*
- Unique filename.
- */
- (void) CopyMagickString(filename,image_info->zero,extent);
- q+=CopyMagickString(q,filename,extent);
- break;
+ pattern[len]='\0';
+ /* Check for unmatched final ']' for "%[...]" */
+ if ( depth != 0 ) {
+ if (len >= 64) { /* truncate string for error message */
+ pattern[61] = '.';
+ pattern[62] = '.';
+ pattern[63] = '.';
+ pattern[64] = '\0';
+ }
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"UnbalancedBraces","\"%%[%s\"",pattern);
+ interpret_text=DestroyString(interpret_text);
+ return((char *)NULL);
}
- case '[':
- {
- char
- pattern[MaxTextExtent];
-
- const char
- *key,
- *value;
- ssize_t
- depth;
-
- /*
- Image value.
- */
- if (strchr(p,']') == (char *) NULL)
- break;
- depth=1;
- p++;
- for (i=0; (i < (MaxTextExtent-1L)) && (*p != '\0'); i++)
- {
- if (*p == '[')
- depth++;
- if (*p == ']')
- depth--;
- if (depth <= 0)
- break;
- pattern[i]=(*p++);
+ /*
+ Special Property Prefixes
+ such as: %[exif:...] %[fx:...] %[pixel:...]
+ Otherwise a free-form property string
+ */
+ value=GetImageProperty(image,pattern,exception);
+ if (value != (const char *) NULL)
+ {
+ length=strlen(value);
+ if ((size_t) (q-interpret_text+length+1) >= extent)
+ {
+ extent+=length;
+ interpret_text=(char *) ResizeQuantumMemory(interpret_text,
+ extent+MaxTextExtent,sizeof(*interpret_text));
+ if (interpret_text == (char *) NULL)
+ return((char *)NULL);
+ q=interpret_text+strlen(interpret_text);
+ }
+ (void) CopyMagickString(q,value,extent);
+ q+=length;
+ continue;
}
- pattern[i]='\0';
- value=GetImageProperty(image,pattern);
- if (value != (const char *) NULL)
+ /*
+ Handle property 'glob' patterns
+ Such as: %[*] %[user:array_??] %[filename:e*]
+ */
+ if( IfMagickTrue(IsGlob(pattern)) )
+ {
+ ResetImagePropertyIterator(image);
+ key=GetNextImageProperty(image);
+ while (key != (const char *) NULL)
{
- length=strlen(value);
- if ((size_t) (q-interpret_text+length+1) >= extent)
- {
- extent+=length;
- interpret_text=(char *) ResizeQuantumMemory(interpret_text,
- extent+MaxTextExtent,sizeof(*interpret_text));
- if (interpret_text == (char *) NULL)
- break;
- q=interpret_text+strlen(interpret_text);
- }
- (void) CopyMagickString(q,value,extent);
- q+=length;
- break;
- }
- else
- if (IsGlob(pattern) != MagickFalse)
- {
- /*
- Iterate over image properties.
- */
- ResetImagePropertyIterator(image);
- key=GetNextImageProperty(image);
- while (key != (const char *) NULL)
+ if( IfMagickTrue(GlobExpression(key,pattern,MagickTrue)) )
{
- if (GlobExpression(key,pattern,MagickTrue) != MagickFalse)
+ value=GetImageProperty(image,key,exception);
+ if (value != (const char *) NULL)
{
- value=GetImageProperty(image,key);
- if (value != (const char *) NULL)
+ length=strlen(key)+strlen(value)+2;
+ if ((size_t) (q-interpret_text+length+1) >= extent)
{
- length=strlen(key)+strlen(value)+2;
- if ((size_t) (q-interpret_text+length+1) >= extent)
- {
- extent+=length;
- interpret_text=(char *) ResizeQuantumMemory(
- interpret_text,extent+MaxTextExtent,
- sizeof(*interpret_text));
- if (interpret_text == (char *) NULL)
- break;
- q=interpret_text+strlen(interpret_text);
- }
- q+=FormatLocaleString(q,extent,"%s=%s\n",key,value);
+ extent+=length;
+ interpret_text=(char *) ResizeQuantumMemory(
+ interpret_text,extent+MaxTextExtent,
+ sizeof(*interpret_text));
+ if (interpret_text == (char *) NULL)
+ return((char *)NULL);
+ q=interpret_text+strlen(interpret_text);
}
+ q+=FormatLocaleString(q,extent,"%s=%s\n",key,value);
}
- key=GetNextImageProperty(image);
- }
- }
- value=GetMagickProperty(image_info,image,pattern);
- if (value != (const char *) NULL)
- {
- length=strlen(value);
- if ((size_t) (q-interpret_text+length+1) >= extent)
- {
- extent+=length;
- interpret_text=(char *) ResizeQuantumMemory(interpret_text,
- extent+MaxTextExtent,sizeof(*interpret_text));
- if (interpret_text == (char *) NULL)
- break;
- q=interpret_text+strlen(interpret_text);
}
- (void) CopyMagickString(q,value,extent);
- q+=length;
- break;
+ key=GetNextImageProperty(image);
}
- if (image_info == (ImageInfo *) NULL)
- break;
+ continue;
+ }
+ /*
+ Look for a known property or image attribute
+ Such as %[basename] %[denisty] %[delay]
+ Also does wrapped single letters: %[b] %[G] %[g]
+ */
+ value=GetMagickProperty(image_info,image,pattern,exception);
+ if (value != (const char *) NULL)
+ {
+ length=strlen(value);
+ if ((size_t) (q-interpret_text+length+1) >= extent)
+ {
+ extent+=length;
+ interpret_text=(char *) ResizeQuantumMemory(interpret_text,
+ extent+MaxTextExtent,sizeof(*interpret_text));
+ if (interpret_text == (char *) NULL)
+ return((char *)NULL);
+ q=interpret_text+strlen(interpret_text);
+ }
+ (void) CopyMagickString(q,value,extent);
+ q+=length;
+ continue;
+ }
+ /*
+ Look for a per-image Artifact (user option, post-interpreted)
+ */
+ value=GetImageArtifact(image,pattern);
+ if (value != (char *) NULL)
+ {
+ length=strlen(value);
+ if ((size_t) (q-interpret_text+length+1) >= extent)
+ {
+ extent+=length;
+ interpret_text=(char *) ResizeQuantumMemory(interpret_text,
+ extent+MaxTextExtent,sizeof(*interpret_text));
+ if (interpret_text == (char *) NULL)
+ return((char *)NULL);
+ q=interpret_text+strlen(interpret_text);
+ }
+ (void) CopyMagickString(q,value,extent);
+ q+=length;
+ continue;
+ }
+ /*
+ Look for user option of this name (should never match in CLI usage)
+ */
+ if (image_info != (ImageInfo *) NULL) {
value=GetImageOption(image_info,pattern);
if (value != (char *) NULL)
{
interpret_text=(char *) ResizeQuantumMemory(interpret_text,
extent+MaxTextExtent,sizeof(*interpret_text));
if (interpret_text == (char *) NULL)
- break;
+ return((char *)NULL);
q=interpret_text+strlen(interpret_text);
}
(void) CopyMagickString(q,value,extent);
q+=length;
- break;
+ continue;
}
- break;
+ }
+ /*
+ Failed to find any match anywhere!
+ */
+ if (len >= 64) { /* truncate string for error message */
+ pattern[61] = '.';
+ pattern[62] = '.';
+ pattern[63] = '.';
+ pattern[64] = '\0';
}
- case '@':
- {
- RectangleInfo
- page;
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionWarning,"UnknownImageProperty","\"%%[%s]\"",pattern);
+ /* continue */
+ } /* Braced Percent Escape */
- /*
- Image bounding box.
- */
- page=GetImageBoundingBox(image,&image->exception);
- q+=FormatLocaleString(q,MaxTextExtent,"%.20gx%.20g%+.20g%+.20g",
- (double) page.width,(double) page.height,(double) page.x,(double)
- page.y);
- break;
- }
- case '#':
- {
- /*
- Image signature.
- */
- (void) SignatureImage(image);
- value=GetImageProperty(image,"signature");
- if (value == (const char *) NULL)
- break;
- q+=CopyMagickString(q,value,extent);
- break;
- }
- case '%':
- {
- *q++=(*p);
- break;
- }
- default:
- {
- *q++='%';
- *q++=(*p);
- break;
- }
- }
- }
+ } /* for each char in 'embed_text' */
*q='\0';
- if (text != (const char *) embed_text)
- text=DestroyString(text);
- (void) SubstituteString(&interpret_text,"<","<");
- (void) SubstituteString(&interpret_text,">",">");
return(interpret_text);
}
\f
% RemoveImageProperty() removes a property from the image and returns its
% value.
%
+% In this case the ConstantString() value returned should be freed by the
+% caller when finished.
+%
% The format of the RemoveImageProperty method is:
%
% char *RemoveImageProperty(Image *image,const char *property)
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image->filename);
if (image->properties == (void *) NULL)
{
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
+ if( IfMagickTrue(image->debug) )
(void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
image->filename);
if (image->properties == (void *) NULL)
% %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
-% SetImageProperty() associates an value with an image property.
+% SetImageProperty() saves the given string value either to specific known
+% attribute or to a freeform property string.
+%
+% Attempting to set a property that is normally calculated will produce
+% an exception.
%
% The format of the SetImageProperty method is:
%
% MagickBooleanType SetImageProperty(Image *image,const char *property,
-% const char *value)
+% const char *value,ExceptionInfo *exception)
%
% A description of each parameter follows:
%
%
% o values: the image property values.
%
+% o exception: return any errors or warnings in this structure.
+%
*/
MagickExport MagickBooleanType SetImageProperty(Image *image,
- const char *property,const char *value)
+ const char *property,const char *value,ExceptionInfo *exception)
{
- ExceptionInfo
- *exception;
-
MagickBooleanType
status;
assert(image != (Image *) NULL);
assert(image->signature == MagickSignature);
- if (image->debug != MagickFalse)
- (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
- image->filename);
+ if( IfMagickTrue(image->debug) )
+ (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
+
+ /* Create splay-tree */
if (image->properties == (void *) NULL)
image->properties=NewSplayTree(CompareSplayTreeString,
RelinquishMagickMemory,RelinquishMagickMemory);
- if ((value == (const char *) NULL) || (*value == '\0'))
+
+ /* Delete property if NULL -- empty string values are valid! */
+ if ((value == (const char *) NULL))
return(DeleteImageProperty(image,property));
status=MagickTrue;
- exception=(&image->exception);
+
+ /* Do not 'set' single letter properties - read only shorthand */
+ if (strlen(property) <= 1)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ return(MagickFalse);
+ }
+
+ /* FUTURE: These should produce a 'illegal settings' error
+ + binary chars in property key
+ + single letter property keys (read only)
+ + known special prefixes (read only, they don't get saved!)
+ */
+
switch (*property)
{
case 'B':
case 'b':
{
- if (LocaleCompare(property,"background") == 0)
- {
- (void) QueryColorDatabase(value,&image->background_color,exception);
- break;
- }
- if (LocaleCompare(property,"bias") == 0)
+ if (LocaleCompare("background",property) == 0)
{
- image->bias=SiPrefixToDouble(value,QuantumRange);
+ (void) QueryColorCompliance(value,AllCompliance,
+ &image->background_color,exception);
break;
}
status=AddValueToSplayTree((SplayTreeInfo *) image->properties,
ConstantString(property),ConstantString(value));
+ /* FUTURE: error if status is bad? */
break;
}
case 'C':
case 'c':
{
- if (LocaleCompare(property,"colorspace") == 0)
+ if (LocaleCompare("channels",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
+ if (LocaleCompare("colorspace",property) == 0)
{
ssize_t
colorspace;
value);
if (colorspace < 0)
break;
- (void) SetImageColorspace(image,(ColorspaceType) colorspace);
+ image->colorspace=(ColorspaceType) colorspace;
+ image->rendering_intent=UndefinedIntent;
+ image->gamma=1.000f;
+ ResetMagickMemory(&image->chromaticity,0,sizeof(image->chromaticity));
+ if (IssRGBColorspace(image->colorspace) != MagickFalse)
+ {
+ image->rendering_intent=PerceptualIntent;
+ image->gamma=1.000f/2.200f;
+ image->chromaticity.red_primary.x=0.6400f;
+ image->chromaticity.red_primary.y=0.3300f;
+ image->chromaticity.red_primary.z=0.0300f;
+ image->chromaticity.green_primary.x=0.3000f;
+ image->chromaticity.green_primary.y=0.6000f;
+ image->chromaticity.green_primary.z=0.1000f;
+ image->chromaticity.blue_primary.x=0.1500f;
+ image->chromaticity.blue_primary.y=0.0600f;
+ image->chromaticity.blue_primary.z=0.7900f;
+ image->chromaticity.white_point.x=0.3127f;
+ image->chromaticity.white_point.y=0.3290f;
+ image->chromaticity.white_point.z=0.3583f;
+ }
break;
}
- if (LocaleCompare(property,"compose") == 0)
+ if (LocaleCompare("compose",property) == 0)
{
ssize_t
compose;
image->compose=(CompositeOperator) compose;
break;
}
- if (LocaleCompare(property,"compress") == 0)
+ if (LocaleCompare("compress",property) == 0)
{
ssize_t
compression;
image->compression=(CompressionType) compression;
break;
}
+ if (LocaleCompare("copyright",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
status=AddValueToSplayTree((SplayTreeInfo *) image->properties,
ConstantString(property),ConstantString(value));
break;
case 'D':
case 'd':
{
- if (LocaleCompare(property,"delay") == 0)
+ if (LocaleCompare("delay",property) == 0)
{
GeometryInfo
geometry_info;
image->ticks_per_second=(ssize_t) floor(geometry_info.sigma+0.5);
break;
}
- if (LocaleCompare(property,"density") == 0)
+ if (LocaleCompare("density",property) == 0)
{
GeometryInfo
geometry_info;
flags=ParseGeometry(value,&geometry_info);
- image->x_resolution=geometry_info.rho;
- image->y_resolution=geometry_info.sigma;
+ image->resolution.x=geometry_info.rho;
+ image->resolution.y=geometry_info.sigma;
if ((flags & SigmaValue) == 0)
- image->y_resolution=image->x_resolution;
+ image->resolution.y=image->resolution.x;
}
- if (LocaleCompare(property,"depth") == 0)
+ if (LocaleCompare("depth",property) == 0)
{
image->depth=StringToUnsignedLong(value);
break;
}
- if (LocaleCompare(property,"dispose") == 0)
+ if (LocaleCompare("dispose",property) == 0)
{
ssize_t
dispose;
case 'G':
case 'g':
{
- if (LocaleCompare(property,"gravity") == 0)
+ if (LocaleCompare("gamma",property) == 0)
+ {
+ image->gamma=StringToDouble(value,(char **) NULL);
+ break;
+ }
+ if (LocaleCompare("gravity",property) == 0)
{
ssize_t
gravity;
ConstantString(property),ConstantString(value));
break;
}
+ case 'H':
+ case 'h':
+ if (LocaleCompare("height",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
case 'I':
case 'i':
{
- if (LocaleCompare(property,"intent") == 0)
+ if (LocaleCompare("intent",property) == 0)
{
ssize_t
rendering_intent;
image->rendering_intent=(RenderingIntent) rendering_intent;
break;
}
- if (LocaleCompare(property,"interpolate") == 0)
+ if (LocaleCompare("interpolate",property) == 0)
{
ssize_t
interpolate;
value);
if (interpolate < 0)
break;
- image->interpolate=(InterpolatePixelMethod) interpolate;
+ image->interpolate=(PixelInterpolateMethod) interpolate;
break;
}
status=AddValueToSplayTree((SplayTreeInfo *) image->properties,
ConstantString(property),ConstantString(value));
break;
}
+ case 'K':
+ case 'k':
+ if (LocaleCompare("kurtosis",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
case 'L':
case 'l':
{
- if (LocaleCompare(property,"loop") == 0)
+ if (LocaleCompare("loop",property) == 0)
{
image->iterations=StringToUnsignedLong(value);
break;
ConstantString(property),ConstantString(value));
break;
}
+ case 'M':
+ case 'm':
+ if ( (LocaleCompare("magick",property) == 0) ||
+ (LocaleCompare("max",property) == 0) ||
+ (LocaleCompare("mean",property) == 0) ||
+ (LocaleCompare("min",property) == 0) ||
+ (LocaleCompare("min",property) == 0) )
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
+ "SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
+ case 'O':
+ case 'o':
+ if (LocaleCompare("opaque",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
case 'P':
case 'p':
{
- if (LocaleCompare(property,"page") == 0)
+ if (LocaleCompare("page",property) == 0)
{
char
*geometry;
geometry=DestroyString(geometry);
break;
}
- if (LocaleCompare(property,"profile") == 0)
+ if (LocaleCompare("profile",property) == 0)
{
ImageInfo
*image_info;
(void) SetImageInfo(image_info,1,exception);
profile=FileToStringInfo(image_info->filename,~0UL,exception);
if (profile != (StringInfo *) NULL)
- status=SetImageProfile(image,image_info->magick,profile);
+ status=SetImageProfile(image,image_info->magick,profile,exception);
image_info=DestroyImageInfo(image_info);
break;
}
case 'R':
case 'r':
{
- if (LocaleCompare(property,"rendering-intent") == 0)
+ if (LocaleCompare("rendering-intent",property) == 0)
{
ssize_t
rendering_intent;
rendering_intent=ParseCommandOption(MagickIntentOptions,MagickFalse,
value);
if (rendering_intent < 0)
- break;
- image->rendering_intent=(RenderingIntent) rendering_intent;
+ status=MagickFalse;
+ else
+ image->rendering_intent=(RenderingIntent) rendering_intent;
break;
}
status=AddValueToSplayTree((SplayTreeInfo *) image->properties,
ConstantString(property),ConstantString(value));
break;
}
+ case 'S':
+ case 's':
+ if ( (LocaleCompare("size",property) == 0) ||
+ (LocaleCompare("skewness",property) == 0) ||
+ (LocaleCompare("scenes",property) == 0) ||
+ (LocaleCompare("standard-deviation",property) == 0) )
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
case 'T':
case 't':
{
- if (LocaleCompare(property,"tile-offset") == 0)
+ if (LocaleCompare("tile-offset",property) == 0)
{
char
*geometry;
case 'U':
case 'u':
{
- if (LocaleCompare(property,"units") == 0)
+ if (LocaleCompare("units",property) == 0)
{
ssize_t
units;
ConstantString(property),ConstantString(value));
break;
}
+ case 'V':
+ case 'v':
+ if (LocaleCompare("version",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
+ case 'W':
+ case 'w':
+ if (LocaleCompare("width",property) == 0)
+ {
+ (void) ThrowMagickException(exception,GetMagickModule(),
+ OptionError,"SetReadOnlyProperty","'%s'",property);
+ status=MagickFalse;
+ break;
+ }
default:
{
status=AddValueToSplayTree((SplayTreeInfo *) image->properties,