00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
#include "magick/studio.h"
00046
#include "magick/attribute.h"
00047
#include "magick/blob.h"
00048
#include "magick/draw.h"
00049
#include "magick/error_private.h"
00050
#include "magick/list.h"
00051
#include "magick/memory_.h"
00052
#include "magick/profile.h"
00053
#include "magick/string_.h"
00054
#include "magick/utility.h"
00055
00056
00057
00058
00059
static char
00060 *
TracePSClippath(
unsigned char *,size_t,
const unsigned long,
00061
const unsigned long),
00062 *
TraceSVGClippath(
unsigned char *,size_t,
const unsigned long,
00063
const unsigned long);
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 MagickExport void DestroyImageAttributes(
Image *image)
00090 {
00091
ImageAttribute
00092 *attribute;
00093
00094
register ImageAttribute
00095 *p;
00096
00097
assert(image != (
Image *) NULL);
00098
assert(image->
signature ==
MagickSignature);
00099
if (image->
debug !=
MagickFalse)
00100 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image->
filename);
00101
for (p=image->
attributes; p != (
ImageAttribute *) NULL; )
00102 {
00103 attribute=p;
00104 p=p->
next;
00105
if (attribute->
key != (
char *) NULL)
00106 attribute->
key=(
char *)
RelinquishMagickMemory(attribute->
key);
00107
if (attribute->
value != (
char *) NULL)
00108 attribute->
value=(
char *)
RelinquishMagickMemory(attribute->
value);
00109 attribute=(
ImageAttribute *)
RelinquishMagickMemory(attribute);
00110 }
00111 image->
attributes=(
ImageAttribute *) NULL;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 static MagickBooleanType GenerateIPTCAttribute(
Image *image,
const char *key)
00144 {
00145
char
00146 *attribute;
00147
00148
const StringInfo
00149 *profile;
00150
00151
int
00152 count,
00153 dataset,
00154 record;
00155
00156
register long
00157 i;
00158
00159 size_t
00160 length;
00161
00162 profile=
GetImageProfile(image,
"8bim");
00163
if (profile == (
StringInfo *) NULL)
00164
return(
MagickFalse);
00165 count=sscanf(key,
"IPTC:%d:%d",&dataset,&record);
00166
if (count != 2)
00167
return(
MagickFalse);
00168
for (i=0; i < (
long) profile->
length; i++)
00169 {
00170
if ((
int) profile->
datum[i] != 0x1c)
00171
continue;
00172
if ((
int) profile->
datum[i+1] != dataset)
00173
continue;
00174
if ((
int) profile->
datum[i+2] != record)
00175
continue;
00176 length=(size_t) (profile->
datum[i+3] << 8);
00177 length|=profile->
datum[i+4];
00178 attribute=(
char *)
AcquireMagickMemory(length+
MaxTextExtent);
00179
if (attribute == (
char *) NULL)
00180
continue;
00181 (
void)
CopyMagickString(attribute,(
char *) profile->
datum+i+5,length+1);
00182 (
void)
SetImageAttribute(image,key,(
const char *) attribute);
00183 attribute=(
char *)
RelinquishMagickMemory(attribute);
00184
break;
00185 }
00186
return((
MagickBooleanType) (i < (
long) profile->
length));
00187 }
00188
00189 static unsigned char ReadByte(
unsigned char **p,size_t *length)
00190 {
00191
unsigned char
00192 c;
00193
00194
if (*length < 1)
00195
return((
unsigned char) 0xff);
00196 c=(*(*p)++);
00197 (*length)--;
00198
return(c);
00199 }
00200
00201 static long ReadMSBLong(
unsigned char **p,size_t *length)
00202 {
00203
int
00204 c;
00205
00206
long
00207 value;
00208
00209
register long
00210 i;
00211
00212
unsigned char
00213 buffer[4];
00214
00215
if (*length < 4)
00216
return(-1);
00217
for (i=0; i < 4; i++)
00218 {
00219 c=(
int) (*(*p)++);
00220 (*length)--;
00221 buffer[i]=(
unsigned char) c;
00222 }
00223 value=(
long) (buffer[0] << 24);
00224 value|=buffer[1] << 16;
00225 value|=buffer[2] << 8;
00226 value|=buffer[3];
00227
return(value);
00228 }
00229
00230 static long ReadMSBShort(
unsigned char **p,size_t *length)
00231 {
00232
int
00233 c;
00234
00235
long
00236 value;
00237
00238
register long
00239 i;
00240
00241
unsigned char
00242 buffer[2];
00243
00244
if (*length < 2)
00245
return(-1);
00246
for (i=0; i < 2; i++)
00247 {
00248 c=(
int) (*(*p)++);
00249 (*length)--;
00250 buffer[i]=(
unsigned char) c;
00251 }
00252 value=(
long) (buffer[0] << 8);
00253 value|=buffer[1];
00254
return(value);
00255 }
00256
00257 static MagickBooleanType Generate8BIMAttribute(
Image *image,
const char *key)
00258 {
00259
char
00260 *attribute,
00261 format[
MaxTextExtent],
00262
name[
MaxTextExtent],
00263 *resource;
00264
00265
const StringInfo
00266 *profile;
00267
00268
long
00269
id,
00270 start,
00271 stop,
00272 sub_number;
00273
00274
MagickBooleanType
00275 status;
00276
00277
register long
00278 i;
00279
00280
ssize_t
00281 count;
00282
00283 size_t
00284 length;
00285
00286
unsigned char
00287 *info;
00288
00289
00290
00291
00292 profile=
GetImageProfile(image,
"iptc");
00293
if (profile == (
StringInfo *) NULL)
00294
return(
MagickFalse);
00295 count=(
ssize_t) sscanf(key,
"8BIM:%ld,%ld:%[^\n]\n%[^\n]",&start,&stop,
name,
00296 format);
00297
if ((count != 2) && (count != 3) && (count != 4))
00298
return(
MagickFalse);
00299
if (count < 4)
00300 (
void) strcpy(format,
"SVG");
00301
if (count < 3)
00302 *
name=
'\0';
00303 sub_number=1;
00304
if (*
name ==
'#')
00305 sub_number=atol(&
name[1]);
00306 sub_number=
Max(sub_number,1);
00307 resource=(
char *) NULL;
00308 status=
MagickFalse;
00309 length=profile->
length;
00310 info=(
unsigned char *) profile->
datum;
00311
while ((length > 0) && (status ==
MagickFalse))
00312 {
00313
if (
ReadByte(&info,&length) != (
unsigned char)
'8')
00314
continue;
00315
if (
ReadByte(&info,&length) != (
unsigned char)
'B')
00316
continue;
00317
if (
ReadByte(&info,&length) != (
unsigned char)
'I')
00318
continue;
00319
if (
ReadByte(&info,&length) != (
unsigned char)
'M')
00320
continue;
00321
id=
ReadMSBShort(&info,&length);
00322
if (
id < start)
00323
continue;
00324
if (
id > stop)
00325
continue;
00326
if (resource != (
char *) NULL)
00327 resource=(
char *)
RelinquishMagickMemory(resource);
00328 count=(
ssize_t)
ReadByte(&info,&length);
00329
if ((count != 0) && ((size_t) count <= length))
00330 {
00331 resource=(
char *)
AcquireMagickMemory((size_t) count+
MaxTextExtent);
00332
if (resource != (
char *) NULL)
00333 {
00334
for (i=0; i < (
long) count; i++)
00335 resource[i]=(
char)
ReadByte(&info,&length);
00336 resource[count]=
'\0';
00337 }
00338 }
00339
if ((count & 0x01) == 0)
00340 (
void)
ReadByte(&info,&length);
00341 count=(
ssize_t)
ReadMSBLong(&info,&length);
00342
if ((*
name !=
'\0') && (*
name !=
'#'))
00343
if ((resource == (
char *) NULL) || (
LocaleCompare(
name,resource) != 0))
00344 {
00345
00346
00347
00348 info+=count;
00349 length-=count;
00350
continue;
00351 }
00352
if ((*
name ==
'#') && (sub_number != 1))
00353 {
00354
00355
00356
00357 sub_number--;
00358 info+=count;
00359 length-=count;
00360
continue;
00361 }
00362
00363
00364
00365 attribute=(
char *)
AcquireMagickMemory((size_t) count+
MaxTextExtent);
00366
if (attribute != (
char *) NULL)
00367 {
00368 (
void)
CopyMagickMemory(attribute,(
char *) info,(size_t) count);
00369 attribute[count]=
'\0';
00370 info+=count;
00371 length-=count;
00372
if ((id <= 1999) || (id >= 2999))
00373 (
void)
SetImageAttribute(image,key,(
const char *) attribute);
00374
else
00375 {
00376
char
00377 *path;
00378
00379
if (
LocaleCompare(
"svg",format) == 0)
00380 path=
TraceSVGClippath((
unsigned char *) attribute,(size_t) count,
00381 image->
columns,image->
rows);
00382
else
00383 path=
TracePSClippath((
unsigned char *) attribute,(size_t) count,
00384 image->
columns,image->
rows);
00385 (
void)
SetImageAttribute(image,key,(
const char *) path);
00386 path=(
char *)
RelinquishMagickMemory(path);
00387 }
00388 attribute=(
char *)
RelinquishMagickMemory(attribute);
00389 status=
MagickTrue;
00390 }
00391 }
00392
if (resource != (
char *) NULL)
00393 resource=(
char *)
RelinquishMagickMemory(resource);
00394
return(status);
00395 }
00396
00397 #define DE_STACK_SIZE 16
00398 #define EXIF_DELIMITER "\n"
00399 #define EXIF_NUM_FORMATS 12
00400 #define EXIF_FMT_BYTE 1
00401 #define EXIF_FMT_STRING 2
00402 #define EXIF_FMT_USHORT 3
00403 #define EXIF_FMT_ULONG 4
00404 #define EXIF_FMT_URATIONAL 5
00405 #define EXIF_FMT_SBYTE 6
00406 #define EXIF_FMT_UNDEFINED 7
00407 #define EXIF_FMT_SSHORT 8
00408 #define EXIF_FMT_SLONG 9
00409 #define EXIF_FMT_SRATIONAL 10
00410 #define EXIF_FMT_SINGLE 11
00411 #define EXIF_FMT_DOUBLE 12
00412 #define TAG_EXIF_OFFSET 0x8769
00413 #define TAG_INTEROP_OFFSET 0xa005
00414
00415 typedef struct _TagInfo
00416 {
00417
unsigned short
00418 tag;
00419
00420
char
00421 *
description;
00422 }
TagInfo;
00423
00424
static TagInfo
00425 tag_table[] =
00426 {
00427 { 0x100, (
char *)
"ImageWidth"},
00428 { 0x101, (
char *)
"ImageLength"},
00429 { 0x102, (
char *)
"BitsPerSample"},
00430 { 0x103, (
char *)
"Compression"},
00431 { 0x106, (
char *)
"PhotometricInterpretation"},
00432 { 0x10a, (
char *)
"FillOrder"},
00433 { 0x10d, (
char *)
"DocumentName"},
00434 { 0x10e, (
char *)
"ImageDescription"},
00435 { 0x10f, (
char *)
"Make"},
00436 { 0x110, (
char *)
"Model"},
00437 { 0x111, (
char *)
"StripOffsets"},
00438 { 0x112, (
char *)
"Orientation"},
00439 { 0x115, (
char *)
"SamplesPerPixel"},
00440 { 0x116, (
char *)
"RowsPerStrip"},
00441 { 0x117, (
char *)
"StripByteCounts"},
00442 { 0x11a, (
char *)
"XResolution"},
00443 { 0x11b, (
char *)
"YResolution"},
00444 { 0x11c, (
char *)
"PlanarConfiguration"},
00445 { 0x128, (
char *)
"ResolutionUnit"},
00446 { 0x12d, (
char *)
"TransferFunction"},
00447 { 0x131, (
char *)
"Software"},
00448 { 0x132, (
char *)
"DateTime"},
00449 { 0x13b, (
char *)
"Artist"},
00450 { 0x13e, (
char *)
"WhitePoint"},
00451 { 0x13f, (
char *)
"PrimaryChromaticities"},
00452 { 0x156, (
char *)
"TransferRange"},
00453 { 0x200, (
char *)
"JPEGProc"},
00454 { 0x201, (
char *)
"JPEGInterchangeFormat"},
00455 { 0x202, (
char *)
"JPEGInterchangeFormatLength"},
00456 { 0x211, (
char *)
"YCbCrCoefficients"},
00457 { 0x212, (
char *)
"YCbCrSubSampling"},
00458 { 0x213, (
char *)
"YCbCrPositioning"},
00459 { 0x214, (
char *)
"ReferenceBlackWhite"},
00460 { 0x1000, (
char *)
"RelatedImageFileFormat"},
00461 { 0x1001, (
char *)
"RelatedImageLength"},
00462 { 0x1002, (
char *)
"RelatedImageWidth"},
00463 { 0x828d, (
char *)
"CFARepeatPatternDim"},
00464 { 0x828e, (
char *)
"CFAPattern"},
00465 { 0x828f, (
char *)
"BatteryLevel"},
00466 { 0x8298, (
char *)
"Copyright"},
00467 { 0x829a, (
char *)
"ExposureTime"},
00468 { 0x829d, (
char *)
"FNumber"},
00469 { 0x83Bb, (
char *)
"IPTC/NAA"},
00470 { 0x8769, (
char *)
"ExifOffset"},
00471 { 0x8773, (
char *)
"InterColorProfile"},
00472 { 0x8822, (
char *)
"ExposureProgram"},
00473 { 0x8824, (
char *)
"SpectralSensitivity"},
00474 { 0x8825, (
char *)
"GPSInfo"},
00475 { 0x8827, (
char *)
"ISOSpeedRatings"},
00476 { 0x8828, (
char *)
"OECF"},
00477 { 0x8829, (
char *)
"Interlace"},
00478 { 0x882a, (
char *)
"TimeZoneOffset"},
00479 { 0x882b, (
char *)
"SelfTimerMode"},
00480 { 0x9000, (
char *)
"ExifVersion"},
00481 { 0x9003, (
char *)
"DateTimeOriginal"},
00482 { 0x9004, (
char *)
"DateTimeDigitized"},
00483 { 0x9101, (
char *)
"ComponentsConfiguration"},
00484 { 0x9102, (
char *)
"CompressedBitsPerPixel"},
00485 { 0x9201, (
char *)
"ShutterSpeedValue"},
00486 { 0x9202, (
char *)
"ApertureValue"},
00487 { 0x9203, (
char *)
"BrightnessValue"},
00488 { 0x9204, (
char *)
"ExposureBiasValue"},
00489 { 0x9205, (
char *)
"MaxApertureValue"},
00490 { 0x9206, (
char *)
"SubjectDistance"},
00491 { 0x9207, (
char *)
"MeteringMode"},
00492 { 0x9208, (
char *)
"LightSrc"},
00493 { 0x9209, (
char *)
"Flash"},
00494 { 0x920a, (
char *)
"FocalLength"},
00495 { 0x920b, (
char *)
"FlashEnergy"},
00496 { 0x920c, (
char *)
"SpatialFrequencyResponse"},
00497 { 0x920d, (
char *)
"Noise"},
00498 { 0x9211, (
char *)
"ImageNumber"},
00499 { 0x9212, (
char *)
"SecurityClassification"},
00500 { 0x9213, (
char *)
"ImageHistory"},
00501 { 0x9214, (
char *)
"SubjectLocation"},
00502 { 0x9215, (
char *)
"ExposureIndex"},
00503 { 0x9216, (
char *)
"TIFF/EPStandardID"},
00504 { 0x927c, (
char *)
"MakerNote"},
00505 { 0x9286, (
char *)
"UserComment"},
00506 { 0x9290, (
char *)
"SubSecTime"},
00507 { 0x9291, (
char *)
"SubSecTimeOriginal"},
00508 { 0x9292, (
char *)
"SubSecTimeDigitized"},
00509 { 0xA000, (
char *)
"FlashPixVersion"},
00510 { 0xA001, (
char *)
"ColorSpace"},
00511 { 0xA002, (
char *)
"ExifImageWidth"},
00512 { 0xA003, (
char *)
"ExifImageLength"},
00513 { 0xA005, (
char *)
"InteroperabilityOffset"},
00514 { 0xA20b, (
char *)
"FlashEnergy"},
00515 { 0xA20c, (
char *)
"SpatialFrequencyResponse"},
00516 { 0xA20e, (
char *)
"FocalPlaneXResolution"},
00517 { 0xA20f, (
char *)
"FocalPlaneYResolution"},
00518 { 0xA210, (
char *)
"FocalPlaneResolutionUnit"},
00519 { 0xA214, (
char *)
"SubjectLocation"},
00520 { 0xA215, (
char *)
"ExposureIndex"},
00521 { 0xA217, (
char *)
"SensingMethod"},
00522 { 0xA300, (
char *)
"FileSource"},
00523 { 0xA301, (
char *)
"SceneType"},
00524 { 0xA302, (
char *)
"CFAPattern"},
00525 { 0x0000, (
char *) NULL}
00526 };
00527
00528
static int
00529 format_bytes[] = {0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8};
00530
00531 static short ReadInt16(
unsigned int msb_order,
void *buffer)
00532 {
00533
short
00534 value;
00535
00536
if (msb_order !=
MagickFalse)
00537 {
00538 value=(
short) ((((
unsigned char *) buffer)[0] << 8) |
00539 ((
unsigned char *) buffer)[1]);
00540
return(value);
00541 }
00542 value=(
short) ((((
unsigned char *) buffer)[1] << 8) |
00543 ((
unsigned char *) buffer)[0]);
00544
return(value);
00545 }
00546
00547 static long ReadInt32(
unsigned int msb_order,
void *buffer)
00548 {
00549
long
00550 value;
00551
00552
if (msb_order !=
MagickFalse)
00553 {
00554 value=(
long) ((((
unsigned char *) buffer)[0] << 24) |
00555 (((
unsigned char *) buffer)[1] << 16) |
00556 (((
unsigned char *) buffer)[2] << 8) | (((
unsigned char *) buffer)[3]));
00557
return(value);
00558 }
00559 value=(
long) ((((
unsigned char *) buffer)[3] << 24) |
00560 (((
unsigned char *) buffer)[2] << 16) |
00561 (((
unsigned char *) buffer)[1] << 8 ) |
00562 (((
unsigned char *) buffer)[0]));
00563
return(value);
00564 }
00565
00566 static unsigned short ReadUint16(
unsigned int msb_order,
void *buffer)
00567 {
00568
unsigned short
00569 value;
00570
00571
if (msb_order !=
MagickFalse)
00572 {
00573 value=(
unsigned short) ((((
unsigned char *) buffer)[0] << 8) |
00574 ((
unsigned char *) buffer)[1]);
00575
return(value);
00576 }
00577 value=(
unsigned short) ((((
unsigned char *) buffer)[1] << 8) |
00578 ((
unsigned char *) buffer)[0]);
00579
return(value);
00580 }
00581
00582 static unsigned long ReadUint32(
unsigned int msb_order,
void *buffer)
00583 {
00584
return((
unsigned long)
ReadInt32(msb_order,buffer) & 0xffffffff);
00585 }
00586
00587 static int GenerateEXIFAttribute(
Image *image,
const char *specification)
00588 {
00589
char
00590 *key,
00591 *value,
00592 *
final;
00593
00594
const StringInfo
00595 *profile;
00596
00597
int
00598 all,
00599
id,
00600 level;
00601
00602
register long
00603 i;
00604
00605 size_t
00606 length;
00607
00608
unsigned long
00609 offset;
00610
00611
unsigned char
00612 *tiffp,
00613 *ifdstack[
DE_STACK_SIZE],
00614 *ifdp,
00615 *info;
00616
00617
unsigned int
00618 de,
00619 destack[
DE_STACK_SIZE],
00620 msb_order,
00621 nde;
00622
00623
unsigned long
00624 tag;
00625
00626
00627
00628
00629 profile=
GetImageProfile(image,
"exif");
00630
if (profile == (
StringInfo *) NULL)
00631
return(
MagickFalse);
00632 value=(
char *) NULL;
00633
final=
AcquireString(
"");
00634 key=(
char *) &specification[5];
00635
if ((key == (
char *) NULL) || (*key ==
'\0'))
00636
return(
MagickFalse);
00637
while (isspace((
int) ((
unsigned char) *key)) != 0)
00638 key++;
00639 all=0;
00640 tag=(~0UL);
00641
switch (*key)
00642 {
00643
00644
00645
00646
case '*':
00647 {
00648 tag=0;
00649 all=1;
00650
break;
00651 }
00652
case '!':
00653 {
00654 tag=0;
00655 all=2;
00656
break;
00657 }
00658
00659
00660
00661
case '#':
00662 {
00663
char
00664 c;
00665
00666
unsigned long
00667 n;
00668
00669 tag=0;
00670 key++;
00671 n=(
unsigned long) strlen(key);
00672
if (n != 4)
00673
return(
MagickFalse);
00674
else
00675 {
00676
00677
00678
00679 n/=4;
00680
do
00681 {
00682
for (i=(
long) n-1; i >= 0; i--)
00683 {
00684 c=(*key++);
00685 tag<<=4;
00686
if ((c >=
'0') && (c <=
'9'))
00687 tag|=(
int) (c-
'0');
00688
else
00689
if ((c >=
'A') && (c <=
'F'))
00690 tag|=(
int) (c-(
'A'-(
char) 10));
00691
else
00692
if ((c >=
'a') && (c <=
'f'))
00693 tag|=(
int) (c-(
'a'-(
char) 10));
00694
else
00695
return(
MagickFalse);
00696 }
00697 }
while (*key !=
'\0');
00698 }
00699
break;
00700 }
00701
default:
00702 {
00703
00704
00705
00706
for (i=0; ; i++)
00707 {
00708
if (
tag_table[i].
tag == 0)
00709
break;
00710
if (
LocaleCompare(
tag_table[i].description,key) == 0)
00711 {
00712 tag=(
unsigned long)
tag_table[i].
tag;
00713
break;
00714 }
00715 }
00716
break;
00717 }
00718 }
00719
if (tag == (~0UL))
00720
return(
MagickFalse);
00721 length=profile->
length;
00722 info=(
unsigned char *) profile->
datum;
00723
while (length != 0)
00724 {
00725
if ((
int)
ReadByte(&info,&length) != 0x45)
00726
continue;
00727
if ((
int)
ReadByte(&info,&length) != 0x78)
00728
continue;
00729
if ((
int)
ReadByte(&info,&length) != 0x69)
00730
continue;
00731
if ((
int)
ReadByte(&info,&length) != 0x66)
00732
continue;
00733
if ((
int)
ReadByte(&info,&length) != 0x00)
00734
continue;
00735
if ((
int)
ReadByte(&info,&length) != 0x00)
00736
continue;
00737
break;
00738 }
00739
if (length < 16)
00740
return(
MagickFalse);
00741 tiffp=info;
00742
id=(
int)
ReadUint16(0,tiffp);
00743 msb_order=0;
00744
if (
id == 0x4949)
00745 msb_order=0;
00746
else
00747
if (
id == 0x4D4D)
00748 msb_order=1;
00749
else
00750
return(
MagickFalse);
00751
if (
ReadUint16(msb_order,tiffp+2) != 0x002a)
00752
return(
MagickFalse);
00753
00754
00755
00756 offset=
ReadUint32(msb_order,tiffp+4);
00757
if ((size_t) offset >= length)
00758
return(
MagickFalse);
00759
00760
00761
00762 ifdp=tiffp+offset;
00763 level=0;
00764 de=0;
00765
do
00766 {
00767
00768
00769
00770
if (level > 0)
00771 {
00772 level--;
00773 ifdp=ifdstack[level];
00774 de=destack[level];
00775 }
00776
00777
00778
00779 nde=
ReadUint16(msb_order,ifdp);
00780
for (; de < nde; de++)
00781 {
00782
long
00783 n,
00784 t,
00785 f,
00786 c;
00787
00788
char
00789 *pde,
00790 *pval;
00791
00792 pde=(
char *) (ifdp+2+(12*de));
00793 t=(
long)
ReadUint16(msb_order,pde);
00794 f=(
long)
ReadUint16(msb_order,pde+2);
00795
if ((f-1) >=
EXIF_NUM_FORMATS)
00796
break;
00797 c=(
long)
ReadUint32(msb_order,pde+4);
00798 n=c*
format_bytes[f];
00799
if (n <= 4)
00800 pval=pde+8;
00801
else
00802 {
00803
unsigned long
00804 oval;
00805
00806
00807
00808
00809 oval=
ReadUint32(msb_order,pde+8);
00810
if ((size_t) (oval+n) > length)
00811
continue;
00812 pval=(
char *)(tiffp+oval);
00813 }
00814
if ((all != 0) || (tag == (
unsigned long) t))
00815 {
00816
char
00817 buffer[
MaxTextExtent];
00818
00819
switch (f)
00820 {
00821
case EXIF_FMT_SBYTE:
00822 {
00823 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%ld",
00824 (
long) (*(
char *) pval));
00825 value=
AcquireString(buffer);
00826
break;
00827 }
00828
case EXIF_FMT_BYTE:
00829 {
00830 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%ld",
00831 (
long) (*(
unsigned char *) pval));
00832 value=
AcquireString(buffer);
00833
break;
00834 }
00835
case EXIF_FMT_SSHORT:
00836 {
00837 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%hd",
00838
ReadUint16(msb_order,pval));
00839 value=
AcquireString(buffer);
00840
break;
00841 }
00842
case EXIF_FMT_USHORT:
00843 {
00844 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%hu",
00845
ReadInt16(msb_order,pval));
00846 value=
AcquireString(buffer);
00847
break;
00848 }
00849
case EXIF_FMT_ULONG:
00850 {
00851 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%lu",
00852
ReadUint32(msb_order,pval));
00853 value=
AcquireString(buffer);
00854
break;
00855 }
00856
case EXIF_FMT_SLONG:
00857 {
00858 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%ld",
00859
ReadInt32(msb_order,pval));
00860 value=
AcquireString(buffer);
00861
break;
00862 }
00863
case EXIF_FMT_URATIONAL:
00864 {
00865 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%ld/%ld",
00866
ReadUint32(msb_order,pval),
00867
ReadUint32(msb_order,4+(
char *) pval));
00868 value=
AcquireString(buffer);
00869
break;
00870 }
00871
case EXIF_FMT_SRATIONAL:
00872 {
00873 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%ld/%ld",
00874
ReadInt32(msb_order,pval),
00875
ReadInt32(msb_order,4+(
char *) pval));
00876 value=
AcquireString(buffer);
00877
break;
00878 }
00879
case EXIF_FMT_SINGLE:
00880 {
00881 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%f",
00882 (
double) *(
float *) pval);
00883 value=
AcquireString(buffer);
00884
break;
00885 }
00886
case EXIF_FMT_DOUBLE:
00887 {
00888 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%f",
00889 *(
double *) pval);
00890 value=
AcquireString(buffer);
00891
break;
00892 }
00893
default:
00894
case EXIF_FMT_UNDEFINED:
00895
case EXIF_FMT_STRING:
00896 {
00897 value=(
char *)
AcquireMagickMemory((size_t) n+1);
00898
if (value != (
char *) NULL)
00899 {
00900
long
00901 a;
00902
00903
for (a=0; a < n; a++)
00904 {
00905 value[a]=
'.';
00906
if (isprint((
int) ((
unsigned char) pval[a])) != 0)
00907 value[a]=pval[a];
00908 }
00909 value[a]=
'\0';
00910
break;
00911 }
00912
break;
00913 }
00914 }
00915
if (value != (
char *) NULL)
00916 {
00917
int
00918 i;
00919
00920
char
00921 *description;
00922
00923
if (strlen(
final) != 0)
00924 (
void)
ConcatenateString(&
final,
EXIF_DELIMITER);
00925 description=(
char *) NULL;
00926
switch (all)
00927 {
00928
case 1:
00929 {
00930 description=(
char *)
"unknown";
00931
for (i=0; ; i++)
00932 {
00933
if (
tag_table[i].
tag == 0)
00934
break;
00935
if ((
long)
tag_table[i].
tag == t)
00936 {
00937 description=
tag_table[i].
description;
00938
break;
00939 }
00940 }
00941 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"%s=",
00942 description);
00943 (
void)
ConcatenateString(&
final,buffer);
00944
break;
00945 }
00946
case 2:
00947 {
00948 (
void)
FormatMagickString(buffer,
MaxTextExtent,
"#%04lx=",t);
00949 (
void)
ConcatenateString(&
final,buffer);
00950
break;
00951 }
00952 }
00953 (
void)
ConcatenateString(&
final,value);
00954 value=(
char *)
RelinquishMagickMemory(value);
00955 }
00956 }
00957
if ((t ==
TAG_EXIF_OFFSET) || (t ==
TAG_INTEROP_OFFSET))
00958 {
00959
long
00960 offset;
00961
00962 offset=(
long)
ReadUint32(msb_order,pval);
00963
if ((offset < (
long) length) || (level < (
DE_STACK_SIZE-2)))
00964 {
00965
00966
00967
00968 ifdstack[level]=ifdp;
00969 de++;
00970 destack[level]=de;
00971 level++;
00972
00973
00974
00975 ifdstack[level]=tiffp+offset;
00976 destack[level]=0;
00977 level++;
00978 }
00979
break;
00980 }
00981 }
00982 }
while ((level > 0) && (level <
DE_STACK_SIZE));
00983
if (strlen(
final) == 0)
00984 (
void)
ConcatenateString(&
final,
"unknown");
00985 (
void)
SetImageAttribute(image,specification,(
const char *)
final);
00986
final=(
char *)
RelinquishMagickMemory(
final);
00987
return(
MagickTrue);
00988 }
00989
00990 MagickExport const ImageAttribute *
GetImageAttribute(
const Image *image,
00991
const char *key)
00992 {
00993
register ImageAttribute
00994 *p;
00995
00996
assert(image != (
Image *) NULL);
00997
assert(image->
signature ==
MagickSignature);
00998
if (image->
debug !=
MagickFalse)
00999 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image->
filename);
01000
if (key == (
char *) NULL)
01001
return(image->
attributes);
01002
for (p=image->
attributes; p != (
ImageAttribute *) NULL; p=p->
next)
01003
if (
LocaleCompare(key,p->
key) == 0)
01004
return(p);
01005
if (
LocaleNCompare(
"iptc:",key,5) == 0)
01006 {
01007
if (
GenerateIPTCAttribute((
Image *) image,key) ==
MagickTrue)
01008
return(
GetImageAttribute(image,key));
01009 }
01010
if (
LocaleNCompare(
"8bim:",key,5) == 0)
01011 {
01012
if (
Generate8BIMAttribute((
Image *) image,key) ==
MagickTrue)
01013
return(
GetImageAttribute(image,key));
01014 }
01015
if (
LocaleNCompare(
"exif:",key,5) == 0)
01016 {
01017
if (
GenerateEXIFAttribute((
Image *) image,key) ==
MagickTrue)
01018
return(
GetImageAttribute(image,key));
01019 }
01020
return(p);
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 MagickExport const ImageAttribute *
GetImageClippingPathAttribute(
01051
const Image *image)
01052 {
01053
return(
GetImageAttribute(image,
"8BIM:1999,2998"));
01054 }
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 MagickExport const ImageAttribute *
GetImageInfoAttribute(
01089
const ImageInfo *image_info,
const Image *image,
const char *key)
01090 {
01091
char
01092 attribute[
MaxTextExtent],
01093 filename[
MaxTextExtent];
01094
01095 attribute[0]=
'\0';
01096
switch (*(key))
01097 {
01098
case 'b':
01099 {
01100
if (
LocaleNCompare(
"base",key,2) == 0)
01101 {
01102
GetPathComponent(image->
magick_filename,
BasePath,filename);
01103 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01104
break;
01105 }
01106
break;
01107 }
01108
case 'd':
01109 {
01110
if (
LocaleNCompare(
"depth",key,2) == 0)
01111 {
01112 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",image->
depth);
01113
break;
01114 }
01115
if (
LocaleNCompare(
"directory",key,2) == 0)
01116 {
01117
GetPathComponent(image->
magick_filename,
HeadPath,filename);
01118 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01119
break;
01120 }
01121
break;
01122 }
01123
case 'e':
01124 {
01125
if (
LocaleNCompare(
"extension",key,2) == 0)
01126 {
01127
GetPathComponent(image->
magick_filename,
ExtensionPath,filename);
01128 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01129
break;
01130 }
01131
break;
01132 }
01133
case 'g':
01134 {
01135
if (
LocaleNCompare(
"group",key,2) == 0)
01136 {
01137 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"0x%lx",
01138 image_info->
group);
01139
break;
01140 }
01141
break;
01142 }
01143
case 'h':
01144 {
01145
if (
LocaleNCompare(
"height",key,2) == 0)
01146 {
01147 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",
01148 image->
magick_rows != 0 ? image->
magick_rows : 256UL);
01149
break;
01150 }
01151
break;
01152 }
01153
case 'i':
01154 {
01155
if (
LocaleNCompare(
"input",key,2) == 0)
01156 {
01157 (
void)
CopyMagickString(attribute,image->
filename,
MaxTextExtent);
01158
break;
01159 }
01160
break;
01161 }
01162
case 'm':
01163 {
01164
if (
LocaleNCompare(
"magick",key,2) == 0)
01165 {
01166 (
void)
CopyMagickString(attribute,image->
magick,
MaxTextExtent);
01167
break;
01168 }
01169
break;
01170 }
01171
case 'n':
01172 {
01173
if (
LocaleNCompare(
"name",key,2) == 0)
01174 {
01175 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01176
break;
01177 }
01178
break;
01179 }
01180
case 's':
01181 {
01182
if (
LocaleNCompare(
"size",key,2) == 0)
01183 {
01184
char
01185 format[
MaxTextExtent];
01186
01187
FormatSize(
GetBlobSize(image),format);
01188 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%s",format);
01189
break;
01190 }
01191
if (
LocaleNCompare(
"scene",key,2) == 0)
01192 {
01193 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",image->
scene);
01194
if (image_info->
number_scenes != 0)
01195 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",
01196 image_info->
scene);
01197
break;
01198 }
01199
if (
LocaleNCompare(
"scenes",key,6) == 0)
01200 {
01201 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",
01202 (
unsigned long)
GetImageListLength(image));
01203
break;
01204 }
01205
break;
01206 }
01207
case 'o':
01208 {
01209
if (
LocaleNCompare(
"output",key,2) == 0)
01210 {
01211 (
void)
CopyMagickString(attribute,image_info->
filename,
MaxTextExtent);
01212
break;
01213 }
01214
break;
01215 }
01216
case 'p':
01217 {
01218
if (
LocaleNCompare(
"page",key,2) == 0)
01219 {
01220
register const Image
01221 *p;
01222
01223
unsigned long
01224 page;
01225
01226 p=image;
01227
for (page=1; p->
previous != (
Image *) NULL; page++)
01228 p=p->
previous;
01229 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",page);
01230
break;
01231 }
01232
break;
01233 }
01234
case 'u':
01235 {
01236
if (
LocaleNCompare(
"unique",key,2) == 0)
01237 {
01238 (
void)
CopyMagickString(filename,image_info->
unique,
MaxTextExtent);
01239 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01240
break;
01241 }
01242
break;
01243 }
01244
case 'w':
01245 {
01246
if (
LocaleNCompare(
"width",key,2) == 0)
01247 {
01248 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%lu",
01249 image->
magick_columns != 0 ? image->
magick_columns : 256UL);
01250
break;
01251 }
01252
break;
01253 }
01254
case 'x':
01255 {
01256
if (
LocaleNCompare(
"xresolution",key,2) == 0)
01257 {
01258 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%g",
01259 image->
x_resolution);
01260
break;
01261 }
01262
break;
01263 }
01264
case 'y':
01265 {
01266
if (
LocaleNCompare(
"yresolution",key,2) == 0)
01267 {
01268 (
void)
FormatMagickString(attribute,
MaxTextExtent,
"%g",
01269 image->
y_resolution);
01270
break;
01271 }
01272
break;
01273 }
01274
case 'z':
01275 {
01276
if (
LocaleNCompare(
"zero",key,2) == 0)
01277 {
01278 (
void)
CopyMagickString(filename,image_info->
zero,
MaxTextExtent);
01279 (
void)
CopyMagickString(attribute,filename,
MaxTextExtent);
01280
break;
01281 }
01282
break;
01283 }
01284 }
01285
if (strlen(image->
magick_filename) != 0)
01286
return(
GetImageAttribute(image,key));
01287
return((
ImageAttribute *) NULL);
01288 }
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 MagickExport MagickBooleanType SetImageAttribute(
Image *image,
const char *key,
01324
const char *value)
01325 {
01326
ImageAttribute
01327 *attribute;
01328
01329
register const char
01330 *q;
01331
01332
register ImageAttribute
01333 *p;
01334
01335
01336
01337
01338
assert(image != (
Image *) NULL);
01339
assert(image->
signature ==
MagickSignature);
01340
if (image->
debug !=
MagickFalse)
01341 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image->
filename);
01342
if ((key == (
const char *) NULL) || (*key ==
'\0'))
01343
return(
MagickFalse);
01344
if (value == (
const char *) NULL)
01345 {
01346
01347
01348
01349
for (p=image->
attributes; p != (
ImageAttribute *) NULL; p=p->
next)
01350
if (
LocaleCompare(key,p->
key) == 0)
01351
break;
01352
if (p == (
ImageAttribute *) NULL)
01353
return(
MagickFalse);
01354
if (p->
key != (
char *) NULL)
01355 p->
key=(
char *)
RelinquishMagickMemory(p->
key);
01356
if (p->
value != (
char *) NULL)
01357 p->
value=(
char *)
RelinquishMagickMemory(p->
value);
01358
if (p->
previous != (
ImageAttribute *) NULL)
01359 p->
previous->
next=p->
next;
01360
else
01361 {
01362 image->
attributes=p->
next;
01363
if (p->
next != (
ImageAttribute *) NULL)
01364 p->
next->
previous=(
ImageAttribute *) NULL;
01365 }
01366
if (p->
next != (
ImageAttribute *) NULL)
01367 p->
next->
previous=p->
previous;
01368 attribute=p;
01369 attribute=(
ImageAttribute *)
RelinquishMagickMemory(attribute);
01370
return(
MagickTrue);
01371 }
01372
if (*value ==
'\0')
01373
return(
MagickFalse);
01374 attribute=(
ImageAttribute *)
AcquireMagickMemory(
sizeof(
ImageAttribute));
01375
if (attribute == (
ImageAttribute *) NULL)
01376
return(
MagickFalse);
01377 attribute->
key=
AcquireString(key);
01378
for (q=value; *q !=
'\0'; q++)
01379
if (((
int) ((
unsigned char) *q) < 32) &&
01380 (isspace((
int) ((
unsigned char) *q)) == 0))
01381
break;
01382
if (*q !=
'\0')
01383 attribute->
value=
AcquireString(value);
01384
else
01385 attribute->
value=
TranslateText((
ImageInfo *) NULL,image,value);
01386 attribute->
compression=
MagickFalse;
01387 attribute->
previous=(
ImageAttribute *) NULL;
01388 attribute->
next=(
ImageAttribute *) NULL;
01389
if (image->
attributes == (
ImageAttribute *) NULL)
01390 {
01391 image->
attributes=attribute;
01392
return(
MagickTrue);
01393 }
01394
for (p=image->
attributes; p != (
ImageAttribute *) NULL; p=p->
next)
01395 {
01396
if (
LocaleCompare(attribute->
key,p->
key) == 0)
01397 {
01398 (
void)
ConcatenateString(&p->
value,attribute->
value);
01399 attribute->
value=(
char *)
RelinquishMagickMemory(attribute->
value);
01400 attribute->
key=(
char *)
RelinquishMagickMemory(attribute->
key);
01401 attribute=(
ImageAttribute *)
RelinquishMagickMemory(attribute);
01402
return(
MagickTrue);
01403 }
01404
if (p->
next == (
ImageAttribute *) NULL)
01405
break;
01406 }
01407
01408
01409
01410 attribute->
previous=p;
01411 p->
next=attribute;
01412
return(
MagickTrue);
01413 }
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445 static char *
TracePSClippath(
unsigned char *blob,size_t length,
01446
const unsigned long magick_unused(columns),
01447
const unsigned long magick_unused(rows))
01448 {
01449
char
01450 *path,
01451 *message;
01452
01453
long
01454