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
#include "magick/studio.h"
00043
#include "magick/blob.h"
00044
#include "magick/blob_private.h"
00045
#include "magick/error.h"
00046
#include "magick/error_private.h"
00047
#include "magick/image.h"
00048
#include "magick/image_private.h"
00049
#include "magick/list.h"
00050
#include "magick/magick.h"
00051
#include "magick/memory_.h"
00052
#include "magick/profile.h"
00053
#include "magick/static.h"
00054
#include "magick/string_.h"
00055
#include "magick/token.h"
00056
#include "magick/utility.h"
00057
00058
00059
00060
00061
static MagickBooleanType
00062
WriteMETAImage(
const ImageInfo *,
Image *);
00063
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
00090
00091
#ifdef IMPLEMENT_IS_FUNCTION
00092
static MagickBooleanType IsMETA(
const unsigned char *magick,
const size_t length)
00093 {
00094
if (length < 4)
00095
return(
MagickFalse);
00096
if (
LocaleNCompare((
char *) magick,
"8BIM",4) == 0)
00097
return(
MagickTrue);
00098
if (
LocaleNCompare((
char *) magick,
"APP1",4) == 0)
00099
return(
MagickTrue);
00100
if (
LocaleNCompare((
char *) magick,
"\034\002",2) == 0)
00101
return(
MagickTrue);
00102
return(
MagickFalse);
00103 }
00104
#endif
00105
00106
00107
00108
00109
00110
00111
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
#define BUFFER_SZ 4096
00141
00142 typedef struct _html_code
00143 {
00144
short
00145 len;
00146
const char
00147 *
code,
00148
val;
00149 }
html_code;
00150
00151 static html_code html_codes[] = {
00152
#ifdef HANDLE_GT_LT
00153
{ 4,
"<",
'<' },
00154 { 4,
">",
'>' },
00155
#endif
00156
{ 5,
"&",
'&' },
00157 { 6,
""",
'"' },
00158 { 6,
"'",
'\''}
00159 };
00160
00161 static int stringnicmp(
const char *p,
const char *q,size_t n)
00162 {
00163
register long
00164 i,
00165 j;
00166
00167
if (p == q)
00168
return(0);
00169
if (p == (
char *) NULL)
00170
return(-1);
00171
if (q == (
char *) NULL)
00172
return(1);
00173
while ((*p !=
'\0') && (*q !=
'\0'))
00174 {
00175
if ((*p ==
'\0') || (*q ==
'\0'))
00176
break;
00177 i=(*p);
00178
if (islower(i))
00179 i=toupper(i);
00180 j=(*q);
00181
if (islower(j))
00182 j=toupper(j);
00183
if (i != j)
00184
break;
00185 n--;
00186
if (n == 0)
00187
break;
00188 p++;
00189 q++;
00190 }
00191
return(toupper(*p)-toupper(*q));
00192 }
00193
00194 static int convertHTMLcodes(
char *s,
int len)
00195 {
00196
if (len <=0 || s==(
char*)NULL || *s==
'\0')
00197
return 0;
00198
00199
if (s[1] ==
'#')
00200 {
00201
int val, o;
00202
00203
if (sscanf(s,
"&#%d;",&val) == 1)
00204 {
00205 o = 3;
00206
while (s[o] !=
';')
00207 {
00208 o++;
00209
if (o > 5)
00210
break;
00211 }
00212
if (o < 6)
00213 (
void) strcpy(s+1, s+1+o);
00214 *s = val;
00215
return o;
00216 }
00217 }
00218
else
00219 {
00220
int
00221 i,
00222 codes =
sizeof(
html_codes) /
sizeof(
html_code);
00223
00224
for (i=0; i < codes; i++)
00225 {
00226
if (
html_codes[i].
len <= len)
00227
if (
stringnicmp(s,
html_codes[i].code,
html_codes[i].len) == 0)
00228 {
00229 (
void) strcpy(s+1, s+
html_codes[i].len);
00230 *s =
html_codes[i].
val;
00231
return html_codes[i].
len-1;
00232 }
00233 }
00234 }
00235
return 0;
00236 }
00237
00238 static char *
super_fgets(
char **b,
int *blen,
Image *file)
00239 {
00240
int
00241 c,
00242 len;
00243
00244
unsigned char
00245 *p,
00246 *q;
00247
00248 len=*blen;
00249 p=(
unsigned char *) (*b);
00250
for (q=p; ; q++)
00251 {
00252 c=
ReadBlobByte(file);
00253
if (c == EOF || c ==
'\n')
00254
break;
00255
if ((q-p+1) >= (
int) len)
00256 {
00257
int
00258 tlen;
00259
00260 tlen=q-p;
00261 len<<=1;
00262 p=(
unsigned char *)
ResizeMagickMemory(p,(len+2));
00263 *b=(
char *) p;
00264
if (p == (
unsigned char *) NULL)
00265
break;
00266 q=p+tlen;
00267 }
00268 *q=(
unsigned char) c;
00269 }
00270 *blen=0;
00271
if (p != (
unsigned char *) NULL)
00272 {
00273
int
00274 tlen;
00275
00276 tlen=q-p;
00277
if (tlen == 0)
00278
return (
char *) NULL;
00279 p[tlen] =
'\0';
00280 *blen=++tlen;
00281 }
00282
return((
char *) p);
00283 }
00284
00285 #define BUFFER_SZ 4096
00286 #define IPTC_ID 1028
00287 #define THUMBNAIL_ID 1033
00288
00289 static long parse8BIM(
Image *ifile,
Image *ofile)
00290 {
00291
char
00292 brkused,
00293 quoted,
00294 *line,
00295 *token,
00296 *newstr,
00297 *
name;
00298
00299
int
00300 state,
00301 next;
00302
00303
unsigned char
00304 dataset;
00305
00306
unsigned int
00307 recnum;
00308
00309
int
00310 inputlen =
BUFFER_SZ;
00311
00312
long
00313 savedolen = 0L,
00314 outputlen = 0L;
00315
00316
MagickOffsetType
00317 savedpos,
00318 currentpos;
00319
00320
TokenInfo
00321 token_info;
00322
00323 dataset = 0;
00324 recnum = 0;
00325 line = (
char *)
AcquireMagickMemory(inputlen);
00326
name = token = (
char *)NULL;
00327 savedpos = 0;
00328
while(
super_fgets(&line,&inputlen,ifile)!=NULL)
00329 {
00330 state=0;
00331 next=0;
00332
00333 token = (
char *)
AcquireMagickMemory(inputlen);
00334 newstr = (
char *)
AcquireMagickMemory(inputlen);
00335
while (
Tokenizer(&token_info, 0, token, inputlen, line,
00336 (
char *)
"", (
char *)
"=",
00337 (
char *)
"\"", 0, &brkused,&next,"ed)==0)
00338 {
00339
if (state == 0)
00340 {
00341
int
00342 state,
00343 next;
00344
00345
char
00346 brkused,
00347 quoted;
00348
00349 state=0;
00350 next=0;
00351
while(
Tokenizer(&token_info, 0, newstr, inputlen, token, (
char *)
"",
00352 (
char *)
"#", (
char *)
"", 0, &brkused, &next, "ed)==0)
00353 {
00354
switch (state)
00355 {
00356
case 0:
00357
if (
strcmp(newstr,
"8BIM")==0)
00358 dataset = 255;
00359
else
00360 dataset = (
unsigned char) atoi(newstr);
00361
break;
00362
case 1:
00363 recnum = atoi(newstr);
00364
break;
00365
case 2:
00366
name=(
char *)
AcquireMagickMemory(strlen(newstr)+
MaxTextExtent);
00367
if (
name)
00368 (
void) strcpy(
name,newstr);
00369
break;
00370 }
00371 state++;
00372 }
00373 }
00374
else
00375
if (state == 1)
00376 {
00377
int
00378 next;
00379
00380
unsigned long
00381 len;
00382
00383
char
00384 brkused,
00385 quoted;
00386
00387 next=0;
00388 len = strlen(token);
00389
while (
Tokenizer(&token_info,0, newstr, inputlen, token, (
char *)
"",
00390 (
char *)
"&", (
char *)
"", 0, &brkused, &next, "ed)==0)
00391 {
00392
if (brkused && next > 0)
00393 {
00394
char
00395 *s = &token[next-1];
00396
00397 len -=
convertHTMLcodes(s, strlen(s));
00398 }
00399 }
00400
00401
if (dataset == 255)
00402 {
00403
unsigned char
00404 nlen = 0;
00405
00406
int
00407 i;
00408
00409
if (savedolen > 0)
00410 {
00411
long diff = outputlen - savedolen;
00412 currentpos =
TellBlob(ofile);
00413
SeekBlob(ofile,savedpos,SEEK_SET);
00414
WriteBlobMSBLong(ofile,diff);
00415
SeekBlob(ofile,currentpos,SEEK_SET);
00416 savedolen = 0L;
00417 }
00418
if (outputlen & 1)
00419 {
00420
WriteBlobByte(ofile,0x00);
00421 outputlen++;
00422 }
00423
WriteBlobString(ofile,
"8BIM");
00424
WriteBlobMSBShort(ofile,recnum);
00425 outputlen += 6;
00426
if (
name)
00427 nlen = strlen(
name);
00428
WriteBlobByte(ofile,nlen);
00429 outputlen++;
00430
for (i=0; i<nlen; i++)
00431
WriteBlobByte(ofile,
name[i]);
00432 outputlen += nlen;
00433
if ((nlen & 0x01) == 0)
00434 {
00435
WriteBlobByte(ofile,0x00);
00436 outputlen++;
00437 }
00438
if (recnum !=
IPTC_ID)
00439 {
00440
WriteBlobMSBLong(ofile, len);
00441 outputlen += 4;
00442
00443 next=0;
00444 outputlen += len;
00445
while (len--)
00446
WriteBlobByte(ofile,token[next++]);
00447
00448
if (outputlen & 1)
00449 {
00450
WriteBlobByte(ofile,0x00);
00451 outputlen++;
00452 }
00453 }
00454
else
00455 {
00456
00457 savedpos =
TellBlob(ofile);
00458
WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
00459 outputlen += 4;
00460 savedolen = outputlen;
00461 }
00462 }
00463
else
00464 {
00465
if (len <= 0x7FFF)
00466 {
00467
WriteBlobByte(ofile,0x1c);
00468
WriteBlobByte(ofile,dataset);
00469
WriteBlobByte(ofile,recnum & 255);
00470
WriteBlobMSBShort(ofile,len);
00471 outputlen += 5;
00472 next=0;
00473 outputlen += len;
00474
while (len--)
00475
WriteBlobByte(ofile,token[next++]);
00476 }
00477 }
00478 }
00479 state++;
00480 }
00481 token=(
char *)
RelinquishMagickMemory(token);
00482 newstr=(
char *)
RelinquishMagickMemory(newstr);
00483
name=(
char *)
RelinquishMagickMemory(
name);
00484 }
00485 line=(
char *)
RelinquishMagickMemory(line);
00486
if (savedolen > 0)
00487 {
00488
long diff = outputlen - savedolen;
00489
00490 currentpos =
TellBlob(ofile);
00491
SeekBlob(ofile,savedpos,SEEK_SET);
00492
WriteBlobMSBLong(ofile,diff);
00493
SeekBlob(ofile,currentpos,SEEK_SET);
00494 savedolen = 0L;
00495 }
00496
return outputlen;
00497 }
00498
00499 static char *
super_fgets_w(
char **b,
int *blen,
Image *file)
00500 {
00501
int
00502 c,
00503 len;
00504
00505
unsigned char
00506 *p,
00507 *q;
00508
00509 len=*blen;
00510 p=(
unsigned char *) (*b);
00511
for (q=p; ; q++)
00512 {
00513 c=
ReadBlobLSBShort(file);
00514
if (c == ((
unsigned short) ~0) || c ==
'\n')
00515
break;
00516
if (
EOFBlob(file))
00517
break;
00518
if ((q-p+1) >= (
int) len)
00519 {
00520
int
00521 tlen;
00522
00523 tlen=q-p;
00524 len<<=1;
00525 p=(
unsigned char *)
ResizeMagickMemory(p,(len+2));
00526 *b=(
char *) p;
00527
if (p == (
unsigned char *) NULL)
00528
break;
00529 q=p+tlen;
00530 }
00531 *q=(
unsigned char) c;
00532 }
00533 *blen=0;
00534
if ((*b) != (
char *) NULL)
00535 {
00536
int
00537 tlen;
00538
00539 tlen=q-p;
00540
if (tlen == 0)
00541
return (
char *) NULL;
00542 p[tlen] =
'\0';
00543 *blen=++tlen;
00544 }
00545
return((
char *) p);
00546 }
00547
00548 static long parse8BIMW(
Image *ifile,
Image *ofile)
00549 {
00550
char
00551 brkused,
00552 quoted,
00553 *line,
00554 *token,
00555 *newstr,
00556 *
name;
00557
00558
int
00559 state,
00560 next;
00561
00562
unsigned char
00563 dataset;
00564
00565
unsigned int
00566 recnum;
00567
00568
int
00569 inputlen =
BUFFER_SZ;
00570
00571
long
00572 savedolen = 0L,
00573 outputlen = 0L;
00574
00575
MagickOffsetType
00576 savedpos,
00577 currentpos;
00578
00579
TokenInfo
00580 token_info;
00581
00582 dataset = 0;
00583 recnum = 0;
00584 line = (
char *)
AcquireMagickMemory(inputlen);
00585
name = token = (
char *)NULL;
00586 savedpos = 0;
00587
while(
super_fgets_w(&line,&inputlen,ifile)!=NULL)
00588 {
00589 state=0;
00590 next=0;
00591
00592 token = (
char *)
AcquireMagickMemory(inputlen);
00593 newstr = (
char *)
AcquireMagickMemory(inputlen);
00594
while (
Tokenizer(&token_info, 0, token, inputlen, line,
00595 (
char *)
"", (
char *)
"=",
00596 (
char *)
"\"", 0, &brkused,&next,"ed)==0)
00597 {
00598
if (state == 0)
00599 {
00600
int
00601 state,
00602 next;
00603
00604
char
00605 brkused,
00606 quoted;
00607
00608 state=0;
00609 next=0;
00610
while(
Tokenizer(&token_info, 0, newstr, inputlen, token, (
char *)
"",
00611 (
char *)
"#", (
char *)
"", 0, &brkused, &next, "ed)==0)
00612 {
00613
switch (state)
00614 {
00615
case 0:
00616
if (
strcmp(newstr,
"8BIM")==0)
00617 dataset = 255;
00618
else
00619 dataset = (
unsigned char) atoi(newstr);
00620
break;
00621
case 1:
00622 recnum = atoi(newstr);
00623
break;
00624
case 2:
00625
name=(
char *)
AcquireMagickMemory(strlen(newstr)+
MaxTextExtent);
00626
if (
name)
00627 (
void) strcpy(
name,newstr);
00628
break;
00629 }
00630 state++;
00631 }
00632 }
00633
else
00634
if (state == 1)
00635 {
00636
int
00637 next;
00638
00639
unsigned long
00640 len;
00641
00642
char
00643 brkused,
00644 quoted;
00645
00646 next=0;
00647 len = strlen(token);
00648
while (
Tokenizer(&token_info,0, newstr, inputlen, token, (
char *)
"",
00649 (
char *)
"&", (
char *)
"", 0, &brkused, &next, "ed)==0)
00650 {
00651
if (brkused && next > 0)
00652 {
00653
char
00654 *s = &token[next-1];
00655
00656 len -=
convertHTMLcodes(s, strlen(s));
00657 }
00658 }
00659
00660
if (dataset == 255)
00661 {
00662
unsigned char
00663 nlen = 0;
00664
00665
int
00666 i;
00667
00668
if (savedolen > 0)
00669 {
00670
long diff = outputlen - savedolen;
00671 currentpos =
TellBlob(ofile);
00672
SeekBlob(ofile,savedpos,SEEK_SET);
00673
WriteBlobMSBLong(ofile,diff);
00674
SeekBlob(ofile,currentpos,SEEK_SET);
00675 savedolen = 0L;
00676 }
00677
if (outputlen & 1)
00678 {
00679
WriteBlobByte(ofile,0x00);
00680 outputlen++;
00681 }
00682
WriteBlobString(ofile,
"8BIM");
00683
WriteBlobMSBShort(ofile,recnum);
00684 outputlen += 6;
00685
if (
name)
00686 nlen = strlen(
name);
00687
WriteBlobByte(ofile,nlen);
00688 outputlen++;
00689
for (i=0; i<nlen; i++)
00690
WriteBlobByte(ofile,
name[i]);
00691 outputlen += nlen;
00692
if ((nlen & 0x01) == 0)
00693 {
00694
WriteBlobByte(ofile,0x00);
00695 outputlen++;
00696 }
00697
if (recnum !=
IPTC_ID)
00698 {
00699
WriteBlobMSBLong(ofile, len);
00700 outputlen += 4;
00701
00702 next=0;
00703 outputlen += len;
00704
while (len--)
00705
WriteBlobByte(ofile,token[next++]);
00706
00707
if (outputlen & 1)
00708 {
00709
WriteBlobByte(ofile,0x00);
00710 outputlen++;
00711 }
00712 }
00713
else
00714 {
00715
00716 savedpos =
TellBlob(ofile);
00717
WriteBlobMSBLong(ofile,0xFFFFFFFFUL);
00718 outputlen += 4;
00719 savedolen = outputlen;
00720 }
00721 }
00722
else
00723 {
00724
if (len <= 0x7FFF)
00725 {
00726
WriteBlobByte(ofile,0x1c);
00727
WriteBlobByte(ofile,dataset);
00728
WriteBlobByte(ofile,recnum & 255);
00729
WriteBlobMSBShort(ofile,len);
00730 outputlen += 5;
00731 next=0;
00732 outputlen += len;
00733
while (len--)
00734
WriteBlobByte(ofile,token[next++]);
00735 }
00736 }
00737 }
00738 state++;
00739 }
00740 token=(
char *)
RelinquishMagickMemory(token);
00741 newstr=(
char *)
RelinquishMagickMemory(newstr);
00742
name=(
char *)
RelinquishMagickMemory(
name);
00743 }
00744 line=(
char *)
RelinquishMagickMemory(line);
00745
if (savedolen > 0)
00746 {
00747
long diff = outputlen - savedolen;
00748
00749 currentpos =
TellBlob(ofile);
00750
SeekBlob(ofile,savedpos,SEEK_SET);
00751
WriteBlobMSBLong(ofile,diff);
00752
SeekBlob(ofile,currentpos,SEEK_SET);
00753 savedolen = 0L;
00754 }
00755
return outputlen;
00756 }
00757
00758
00759 #define M_SOF0 0xC0
00760 #define M_SOF1 0xC1
00761 #define M_SOF2 0xC2
00762 #define M_SOF3 0xC3
00763 #define M_SOF5 0xC5
00764 #define M_SOF6 0xC6
00765 #define M_SOF7 0xC7
00766 #define M_SOF9 0xC9
00767 #define M_SOF10 0xCA
00768 #define M_SOF11 0xCB
00769 #define M_SOF13 0xCD
00770 #define M_SOF14 0xCE
00771 #define M_SOF15 0xCF
00772 #define M_SOI 0xD8
00773 #define M_EOI 0xD9
00774 #define M_SOS 0xDA
00775 #define M_APP0 0xe0
00776 #define M_APP1 0xe1
00777 #define M_APP2 0xe2
00778 #define M_APP3 0xe3
00779 #define M_APP4 0xe4
00780 #define M_APP5 0xe5
00781 #define M_APP6 0xe6
00782 #define M_APP7 0xe7
00783 #define M_APP8 0xe8
00784 #define M_APP9 0xe9
00785 #define M_APP10 0xea
00786 #define M_APP11 0xeb
00787 #define M_APP12 0xec
00788 #define M_APP13 0xed
00789 #define M_APP14 0xee
00790 #define M_APP15 0xef
00791
00792 static int jpeg_transfer_1(
Image *ifile,
Image *ofile)
00793 {
00794
int c;
00795
00796 c =
ReadBlobByte(ifile);
00797
if (c == EOF)
00798
return EOF;
00799
WriteBlobByte(ofile,c);
00800
return c;
00801 }
00802
00803
#if defined(future)
00804
static int jpeg_skip_1(
Image *ifile)
00805 {
00806
int c;
00807
00808 c =
ReadBlobByte(ifile);
00809
if (c == EOF)
00810
return EOF;
00811
return c;
00812 }
00813
#endif
00814
00815 static int jpeg_read_remaining(
Image *ifile,
Image *ofile)
00816 {
00817
int c;
00818
00819
while ((c =
jpeg_transfer_1(ifile, ofile)) != EOF)
00820
continue;
00821
return M_EOI;
00822 }
00823
00824 static int jpeg_skip_variable(
Image *ifile,
Image *ofile)
00825 {
00826
unsigned int length;
00827
int c1,c2;
00828
00829
if ((c1 =
jpeg_transfer_1(ifile, ofile)) == EOF)
00830
return M_EOI;
00831
if ((c2 =
jpeg_transfer_1(ifile, ofile)) == EOF)
00832
return M_EOI;
00833
00834 length = (((
unsigned char) c1) << 8) + ((
unsigned char) c2);
00835 length -= 2;
00836
00837
while (length--)
00838
if (
jpeg_transfer_1(ifile, ofile) == EOF)
00839
return M_EOI;
00840
00841
return 0;
00842 }
00843
00844 static int jpeg_skip_variable2(
Image *ifile,
Image *ofile)
00845 {
00846
unsigned int length;
00847
int c1,c2;
00848
00849
if ((c1 =
ReadBlobByte(ifile)) == EOF)
return M_EOI;
00850
if ((c2 =
ReadBlobByte(ifile)) == EOF)
return M_EOI;
00851
00852 length = (((
unsigned char) c1) << 8) + ((
unsigned char) c2);
00853 length -= 2;
00854
00855
while (length--)
00856
if (
ReadBlobByte(ifile) == EOF)
00857
return M_EOI;
00858
00859
return 0;
00860 }
00861
00862 static int jpeg_nextmarker(
Image *ifile,
Image *ofile)
00863 {
00864
int c;
00865
00866
00867
do
00868 {
00869 c =
ReadBlobByte(ifile);
00870
if (c == EOF)
00871
return M_EOI;
00872
else
00873
if (c != 0xff)
00874
WriteBlobByte(ofile,c);
00875 }
while (c != 0xff);
00876
00877
00878
do
00879 {
00880 c =
ReadBlobByte(ifile);
00881
if (c == EOF)
00882
return M_EOI;
00883 }
while (c == 0xff);
00884
00885
return c;
00886 }
00887
00888
#if defined(future)
00889
static int jpeg_skip_till_marker(
Image *ifile,
int marker)
00890 {
00891
int c, i;
00892
00893
do
00894 {
00895
00896 i = 0;
00897
do
00898 {
00899 c =
ReadBlobByte(ifile);
00900 i++;
00901
if (c == EOF)
00902
return M_EOI;
00903 }
while (c != 0xff);
00904
00905
00906
do
00907 {
00908 c =
ReadBlobByte(ifile);
00909
if (c == EOF)
00910
return M_EOI;
00911 }
while (c == 0xff);
00912 }
while (c != marker);
00913
return c;
00914 }
00915
#endif
00916
00917 static char psheader[] =
"\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0";
00918
00919
00920 static int jpeg_embed(
Image *ifile,
Image *ofile,
Image *iptc)
00921 {
00922
unsigned int marker;
00923
unsigned int done = 0;
00924
unsigned int len;
00925
int inx;
00926
00927
if (
jpeg_transfer_1(ifile, ofile) != 0xFF)
00928
return 0;
00929
if (
jpeg_transfer_1(ifile, ofile) !=
M_SOI)
00930
return 0;
00931
00932
while (done ==
MagickFalse)
00933 {
00934 marker =
jpeg_nextmarker(ifile, ofile);
00935
if (marker ==
M_EOI)
00936 {
00937
break;
00938 }
00939
else
00940 {
00941
if (marker !=
M_APP13)
00942 {
00943
WriteBlobByte(ofile,0xff);
00944
WriteBlobByte(ofile,marker);
00945 }
00946 }
00947
00948
switch (marker)
00949 {
00950
case M_APP13:
00951
00952
jpeg_skip_variable2(ifile, ofile);
00953
break;
00954
00955
case M_APP0:
00956
00957
jpeg_skip_variable(ifile, ofile);
00958
00959
if (iptc != (
Image *)NULL)
00960 {
00961 len=
GetBlobSize(iptc);
00962
if (len & 1)
00963 len++;
00964
psheader[ 2 ] = (len+16)>>8;
00965
psheader[ 3 ] = (len+16)&0xff;
00966
for (inx = 0; inx < 18; inx++)
00967
WriteBlobByte(ofile,
psheader[inx]);
00968
jpeg_read_remaining(iptc, ofile);
00969 len=
GetBlobSize(iptc);
00970
if (len & 1)
00971
WriteBlobByte(ofile,0);
00972 }
00973
break;
00974
00975
case M_SOS:
00976
00977
jpeg_read_remaining(ifile, ofile);
00978 done = 1;
00979
break;
00980
00981
default:
00982
jpeg_skip_variable(ifile, ofile);
00983
break;
00984 }
00985 }
00986
return 1;
00987 }
00988
00989
00990
#if defined(future)
00991
static void jpeg_strip(
Image *ifile,
Image *ofile)
00992 {
00993
unsigned int marker;
00994
00995 marker = jpeg_skip_till_marker(ifile, M_SOI);
00996
if (marker ==
M_SOI)
00997 {
00998
WriteBlobByte(ofile,0xff);
00999
WriteBlobByte(ofile,M_SOI);
01000
jpeg_read_remaining(ifile, ofile);
01001 }
01002 }
01003
01004
01005
static int jpeg_extract(
Image *ifile,
Image *ofile)
01006 {
01007
unsigned int marker;
01008
unsigned int done = 0;
01009
01010
if (jpeg_skip_1(ifile) != 0xff)
01011
return 0;
01012
if (jpeg_skip_1(ifile) !=
M_SOI)
01013
return 0;
01014
01015
while (done ==
MagickFalse)
01016 {
01017 marker = jpeg_skip_till_marker(ifile, M_APP13);
01018
if (marker ==
M_APP13)
01019 {
01020 marker =
jpeg_nextmarker(ifile, ofile);
01021
break;
01022 }
01023 }
01024
return 1;
01025 }
01026
#endif
01027
01028 static Image *
ReadMETAImage(
const ImageInfo *image_info,
01029
ExceptionInfo *
exception)
01030 {
01031
Image
01032 *buff,
01033 *image;
01034
01035
int
01036 c;
01037
01038
MagickBooleanType
01039 status;
01040
01041 size_t
01042 length;
01043
01044
StringInfo
01045 *profile;
01046
01047
void
01048 *blob;
01049
01050
01051
01052
01053
assert(image_info != (
const ImageInfo *) NULL);
01054
assert(image_info->
signature ==
MagickSignature);
01055
if (image_info->
debug !=
MagickFalse)
01056 (
void)
LogMagickEvent(
TraceEvent,
GetMagickModule(),image_info->
filename);
01057
assert(exception != (
ExceptionInfo *) NULL);
01058
assert(exception->
signature ==
MagickSignature);
01059 image=
AllocateImage(image_info);
01060 status=
OpenBlob(image_info,image,
ReadBinaryBlobMode,exception);
01061
if (status ==
MagickFalse)
01062 {
01063
DestroyImageList(image);
01064
return((
Image *) NULL);
01065 }
01066 image->
columns=1;
01067 image->
rows=1;
01068
SetImage(image,
OpaqueOpacity);
01069 length=1;
01070
if (
LocaleNCompare(image_info->
magick,
"8BIM",4) == 0)
01071 {
01072
01073
01074
01075 buff=
AllocateImage((
ImageInfo *) NULL);
01076
if (buff == (
Image *) NULL)
01077
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01078 blob=(
unsigned char *)
AcquireMagickMemory(length);
01079
if (blob == (
unsigned char *) NULL)
01080 {
01081 buff=
DestroyImage(buff);
01082
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01083 }
01084
AttachBlob(buff->
blob,blob,length);
01085
if (
LocaleCompare(image_info->
magick,
"8BIMTEXT") == 0)
01086 {
01087 length=
parse8BIM(image, buff);
01088
if (length & 1)
01089
WriteBlobByte(buff,0x0);
01090 }
01091
else if (
LocaleCompare(image_info->
magick,
"8BIMWTEXT") == 0)
01092 {
01093 length=
parse8BIMW(image, buff);
01094
if (length & 1)
01095
WriteBlobByte(buff,0x0);
01096 }
01097
else
01098 {
01099
for ( ; ; )
01100 {
01101 c=
ReadBlobByte(image);
01102
if (c == EOF)
01103
break;
01104
WriteBlobByte(buff,c);
01105 }
01106 }
01107 profile=
AcquireStringInfo(
GetBlobSize(buff));
01108
SetStringInfoDatum(profile,
GetBlobStreamData(buff));
01109 status=
SetImageProfile(image,
"iptc",profile);
01110 profile=
DestroyStringInfo(profile);
01111
if (status ==
MagickFalse)
01112
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01113 blob=
DetachBlob(buff->
blob);
01114 blob=(
unsigned char *)
RelinquishMagickMemory(blob);
01115 buff=
DestroyImage(buff);
01116 }
01117
if (
LocaleNCompare(image_info->
magick,
"APP1",4) == 0)
01118 {
01119
char
01120
name[
MaxTextExtent];
01121
01122 (
void)
FormatMagickString(
name,
MaxTextExtent,
"APP%d",1);
01123 buff=
AllocateImage((
ImageInfo *) NULL);
01124
if (buff == (
Image *) NULL)
01125
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01126 blob=(
unsigned char *)
AcquireMagickMemory(length);
01127
if (blob == (
unsigned char *) NULL)
01128 {
01129 buff=
DestroyImage(buff);
01130
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01131 }
01132
AttachBlob(buff->
blob,blob,length);
01133
if (
LocaleCompare(image_info->
magick,
"APP1JPEG") == 0)
01134 {
01135
Image
01136 *iptc;
01137
01138
int
01139 result;
01140
01141 profile=(
StringInfo *) image_info->
client_data;
01142
if ((profile == (
StringInfo *) NULL) ||
01143 (profile->
datum == (
unsigned char *) NULL) ||
01144 (profile->
length == 0))
01145 {
01146 blob=
DetachBlob(buff->
blob);
01147 blob=(
char *)
RelinquishMagickMemory(blob);
01148 buff=
DestroyImage(buff);
01149
ThrowReaderException(
CoderError,
"NoIPTCProfileAvailable");
01150 }
01151 iptc=
AllocateImage((
ImageInfo *) NULL);
01152
if (iptc == (
Image *) NULL)
01153 {
01154 blob=
DetachBlob(buff->
blob);
01155 blob=(
char *)
RelinquishMagickMemory(blob);
01156 buff=
DestroyImage(buff);
01157
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01158 }
01159
AttachBlob(iptc->
blob,profile->
datum,profile->
length);
01160 result=
jpeg_embed(image,buff,iptc);
01161 blob=
DetachBlob(iptc->
blob);
01162 blob=(
char *)
RelinquishMagickMemory(blob);
01163 iptc=
DestroyImage(iptc);
01164
if (result == 0)
01165 {
01166 blob=
DetachBlob(buff->
blob);
01167 blob=(
char *)
RelinquishMagickMemory(blob);
01168 buff=
DestroyImage(buff);
01169
ThrowReaderException(
CoderError,
"JPEGEmbeddingFailed");
01170 }
01171 }
01172
else
01173 {
01174
#ifdef SLOW_METHOD
01175
for ( ; ; )
01176 {
01177
01178 c=
ReadBlobByte(image);
01179
if (c == EOF)
01180
break;
01181
WriteBlobByte(buff,c);
01182 }
01183
#else
01184
#define MaxBufferSize 65541
01185
long
01186 i;
01187
01188
unsigned char
01189 *buffer;
01190
01191 size_t
01192 length;
01193
01194
ssize_t
01195 count;
01196
01197 buffer=(
unsigned char *)
AcquireMagickMemory(
MaxBufferSize);
01198
if (buffer != (
unsigned char *) NULL)
01199 {
01200 i=0;
01201
while ((length=
ReadBlob(image,
MaxBufferSize,buffer)) != 0)
01202 {
01203 count=0;
01204
for (i=0; i < (
long) length; i+=count)
01205 {
01206 count=
WriteBlob(buff,length-i,buffer+i);
01207
if (count <= 0)
01208
break;
01209 }
01210
if (i < (
long) length)
01211
break;
01212 }
01213 buffer=(
unsigned char *)
RelinquishMagickMemory(buffer);
01214 }
01215
#endif
01216
}
01217 profile=
AcquireStringInfo(
GetBlobSize(buff));
01218
SetStringInfoDatum(profile,
GetBlobStreamData(buff));
01219 status=
SetImageProfile(image,
name,profile);
01220 profile=
DestroyStringInfo(profile);
01221
if (status ==
MagickFalse)
01222
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01223 blob=
DetachBlob(buff->
blob);
01224 blob=(
char *)
RelinquishMagickMemory(blob);
01225 buff=
DestroyImage(buff);
01226 }
01227
if ((
LocaleCompare(image_info->
magick,
"ICC") == 0) ||
01228 (
LocaleCompare(image_info->
magick,
"ICM") == 0))
01229 {
01230 buff=
AllocateImage((
ImageInfo *) NULL);
01231
if (buff == (
Image *) NULL)
01232
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01233 blob=(
unsigned char *)
AcquireMagickMemory(length);
01234
if (blob == (
unsigned char *) NULL)
01235 {
01236 buff=
DestroyImage(buff);
01237
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01238 }
01239
AttachBlob(buff->
blob,blob,length);
01240
for ( ; ; )
01241 {
01242 c=
ReadBlobByte(image);
01243
if (c == EOF)
01244
break;
01245
WriteBlobByte(buff,c);
01246 }
01247 profile=
AcquireStringInfo(
GetBlobSize(buff));
01248
SetStringInfoDatum(profile,
GetBlobStreamData(buff));
01249 (
void)
SetImageProfile(image,
"icc",profile);
01250 profile=
DestroyStringInfo(profile);
01251 blob=
DetachBlob(buff->
blob);
01252 blob=(
unsigned char *)
RelinquishMagickMemory(blob);
01253 buff=
DestroyImage(buff);
01254 }
01255
if (
LocaleCompare(image_info->
magick,
"IPTC") == 0)
01256 {
01257 buff=
AllocateImage((
ImageInfo *) NULL);
01258
if (buff == (
Image *) NULL)
01259
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01260 blob=(
unsigned char *)
AcquireMagickMemory(length);
01261
if (blob == (
unsigned char *) NULL)
01262 {
01263 buff=
DestroyImage(buff);
01264
ThrowReaderException(
ResourceLimitError,
"MemoryAllocationFailed");
01265 }
01266
AttachBlob(buff->
blob,blob,length);
01267
01268
WriteBlob(buff,12,(
unsigned char *)
"8BIM\04\04\0\0\0\0\0\0");
01269
if (
LocaleCompare(image_info->
magick,
"IPTCTEXT") == 0)
01270 {
01271 length=
parse8BIM(image, buff);
01272
if (length & 1)
01273
WriteBlobByte(buff,0x0);
01274 }
01275
else if (
LocaleCompare(image_info->
magick,
"IPTCWTEXT") == 0)
01276 {
01277 }
01278
else
01279 {
01280
for ( ; ; )
01281 {
01282 c=
ReadBlobByte(image);
01283
if (c == EOF)
01284
break;
01285
WriteBlobByte(buff,c);
01286 }
01287 }
01288 profile=
AcquireStringInfo(
GetBlobSize(buff));
01289
01290
01291
01292 length=profile->
length-12;
01293 profile->
datum[10]=length >> 8;
01294 profile->
datum[11]=length & 0xff;
01295
SetStringInfoDatum(profile,
GetBlobStreamData(buff));
01296 (
void)
SetImageProfile(image,
"iptc",profile);
01297 profile=
DestroyStringInfo(profile);
01298 blob=
DetachBlob(buff->
blob);
01299 blob=(
unsigned char *)
RelinquishMagickMemory(blob);
01300 buff=
DestroyImage(buff);
01301 }
01302
CloseBlob(image);
01303
return(
GetFirstImageInList(image));
01304 }
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329 ModuleExport void RegisterMETAImage(
void)
01330 {
01331
MagickInfo
01332 *entry;
01333
01334 entry=
SetMagickInfo(
"8BIM");
01335 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01336 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01337 entry->
adjoin=
MagickFalse;
01338 entry->
stealth=
MagickTrue;
01339 entry->
seekable_stream=
MagickTrue;
01340 entry->
description=
AcquireString(
"Photoshop resource format");
01341 entry->
module=
AcquireString(
"META");
01342 (
void)
RegisterMagickInfo(entry);
01343
01344 entry=
SetMagickInfo(
"8BIMTEXT");
01345 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01346 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01347 entry->
adjoin=
MagickFalse;
01348 entry->
stealth=
MagickTrue;
01349 entry->
seekable_stream=
MagickTrue;
01350 entry->
description=
AcquireString(
"Photoshop resource text format");
01351 entry->
module=
AcquireString(
"META");
01352 (
void)
RegisterMagickInfo(entry);
01353
01354 entry=
SetMagickInfo(
"8BIMWTEXT");
01355 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01356 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01357 entry->
adjoin=
MagickFalse;
01358 entry->
stealth=
MagickTrue;
01359 entry->
seekable_stream=
MagickTrue;
01360 entry->
description=
AcquireString(
"Photoshop resource wide text format");
01361 entry->
module=
AcquireString(
"META");
01362 (
void)
RegisterMagickInfo(entry);
01363
01364 entry=
SetMagickInfo(
"APP1");
01365 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01366 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01367 entry->
adjoin=
MagickFalse;
01368 entry->
stealth=
MagickTrue;
01369 entry->
seekable_stream=
MagickTrue;
01370 entry->
description=
AcquireString(
"Raw application information");
01371 entry->
module=
AcquireString(
"META");
01372 (
void)
RegisterMagickInfo(entry);
01373
01374 entry=
SetMagickInfo(
"APP1JPEG");
01375 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01376 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01377 entry->
adjoin=
MagickFalse;
01378 entry->
stealth=
MagickTrue;
01379 entry->
seekable_stream=
MagickTrue;
01380 entry->
description=
AcquireString(
"Raw JPEG binary data");
01381 entry->
module=
AcquireString(
"META");
01382 (
void)
RegisterMagickInfo(entry);
01383
01384 entry=
SetMagickInfo(
"EXIF");
01385 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01386 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01387 entry->
adjoin=
MagickFalse;
01388 entry->
stealth=
MagickTrue;
01389 entry->
seekable_stream=
MagickTrue;
01390 entry->
description=
AcquireString(
"Exif digital camera binary data");
01391 entry->
module=
AcquireString(
"META");
01392 (
void)
RegisterMagickInfo(entry);
01393
01394 entry=
SetMagickInfo(
"XMP");
01395 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01396 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01397 entry->
adjoin=
MagickFalse;
01398 entry->
stealth=
MagickTrue;
01399 entry->
seekable_stream=
MagickTrue;
01400 entry->
description=
AcquireString(
"Adobe XML metadata");
01401 entry->
module=
AcquireString(
"META");
01402 (
void)
RegisterMagickInfo(entry);
01403
01404 entry=
SetMagickInfo(
"ICM");
01405 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01406 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01407 entry->
adjoin=
MagickFalse;
01408 entry->
stealth=
MagickTrue;
01409 entry->
seekable_stream=
MagickTrue;
01410 entry->
description=
AcquireString(
"ICC Color Profile");
01411 entry->
module=
AcquireString(
"META");
01412 (
void)
RegisterMagickInfo(entry);
01413
01414 entry=
SetMagickInfo(
"ICC");
01415 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01416 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01417 entry->
adjoin=
MagickFalse;
01418 entry->
stealth=
MagickTrue;
01419 entry->
seekable_stream=
MagickTrue;
01420 entry->
description=
AcquireString(
"ICC Color Profile");
01421 entry->
module=
AcquireString(
"META");
01422 (
void)
RegisterMagickInfo(entry);
01423
01424 entry=
SetMagickInfo(
"IPTC");
01425 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01426 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01427 entry->
adjoin=
MagickFalse;
01428 entry->
stealth=
MagickTrue;
01429 entry->
seekable_stream=
MagickTrue;
01430 entry->
description=
AcquireString(
"IPTC Newsphoto");
01431 entry->
module=
AcquireString(
"META");
01432 (
void)
RegisterMagickInfo(entry);
01433
01434 entry=
SetMagickInfo(
"IPTCTEXT");
01435 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01436 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01437 entry->
adjoin=
MagickFalse;
01438 entry->
stealth=
MagickTrue;
01439 entry->
seekable_stream=
MagickTrue;
01440 entry->
description=
AcquireString(
"IPTC Newsphoto text format");
01441 entry->
module=
AcquireString(
"META");
01442 (
void)
RegisterMagickInfo(entry);
01443
01444 entry=
SetMagickInfo(
"IPTCWTEXT");
01445 entry->
decoder=(
DecoderHandler *)
ReadMETAImage;
01446 entry->
encoder=(
EncoderHandler *)
WriteMETAImage;
01447 entry->
adjoin=
MagickFalse;
01448 entry->
stealth=
MagickTrue;
01449 entry->
seekable_stream=
MagickTrue;
01450 entry->
description=
AcquireString(
"IPTC Newsphoto text format");
01451 entry->
module=
AcquireString(
"META");
01452 (
void)
RegisterMagickInfo(entry);
01453 }
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 ModuleExport void UnregisterMETAImage(
void)
01475 {
01476 (
void)
UnregisterMagickInfo(
"8BIM");
01477 (
void)
UnregisterMagickInfo(
"8BIMTEXT");
01478 (
void)
UnregisterMagickInfo(
"8BIMWTEXT");
01479 (
void)
UnregisterMagickInfo(
"EXIF");
01480 (
void)
UnregisterMagickInfo(
"APP1");
01481 (
void)
UnregisterMagickInfo(
"APP1JPEG");
01482 (
void)
UnregisterMagickInfo(
"ICCTEXT");
01483 (
void)
UnregisterMagickInfo(
"ICM");
01484 (
void)
UnregisterMagickInfo(
"ICC");
01485 (
void)
UnregisterMagickInfo(
"IPTC");
01486 (
void)
UnregisterMagickInfo(
"IPTCTEXT");
01487 (
void)
UnregisterMagickInfo(
"IPTCWTEXT");
01488 (
void)
UnregisterMagickInfo(
"XMP");
01489 }
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 static long GetIPTCStream(
unsigned char