2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M EEEEE TTTTT AAA %
13 % Read/Write Embedded Image Profiles. %
20 % Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/channel.h"
46 #include "MagickCore/exception.h"
47 #include "MagickCore/exception-private.h"
48 #include "MagickCore/image.h"
49 #include "MagickCore/image-private.h"
50 #include "MagickCore/list.h"
51 #include "MagickCore/magick.h"
52 #include "MagickCore/memory_.h"
53 #include "MagickCore/module.h"
54 #include "MagickCore/profile.h"
55 #include "MagickCore/splay-tree.h"
56 #include "MagickCore/quantum-private.h"
57 #include "MagickCore/static.h"
58 #include "MagickCore/string_.h"
59 #include "MagickCore/string-private.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/utility.h"
66 static MagickBooleanType
67 WriteMETAImage(const ImageInfo *,Image *,ExceptionInfo *);
70 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 % IsMETA() returns MagickTrue if the image format type, identified by the
81 % magick string, is META.
83 % The format of the IsMETA method is:
85 % MagickBooleanType IsMETA(const unsigned char *magick,const size_t length)
87 % A description of each parameter follows:
89 % o magick: compare image format pattern against these bytes.
91 % o length: Specifies the length of the magick string.
95 #ifdef IMPLEMENT_IS_FUNCTION
96 static MagickBooleanType IsMETA(const unsigned char *magick,const size_t length)
100 if (LocaleNCompare((char *) magick,"8BIM",4) == 0)
102 if (LocaleNCompare((char *) magick,"APP1",4) == 0)
104 if (LocaleNCompare((char *) magick,"\034\002",2) == 0)
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
115 % R e a d M E T A I m a g e %
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
121 % ReadMETAImage() reads a META image file and returns it. It
122 % allocates the memory necessary for the new Image structure and returns a
123 % pointer to the new image.
125 % The format of the ReadMETAImage method is:
127 % Image *ReadMETAImage(const ImageInfo *image_info,
128 % ExceptionInfo *exception)
130 % Decompression code contributed by Kyle Shorter.
132 % A description of each parameter follows:
134 % o image: Method ReadMETAImage returns a pointer to the image after
135 % reading. A null image is returned if there is a memory shortage or
136 % if the image cannot be read.
138 % o image_info: Specifies a pointer to an ImageInfo structure.
140 % o exception: return any errors or warnings in this structure.
144 typedef struct _html_code
154 static const html_code html_codes[] = {
164 static int stringnicmp(const char *p,const char *q,size_t n)
172 if (p == (char *) NULL)
174 if (q == (char *) NULL)
176 while ((*p != '\0') && (*q != '\0'))
178 if ((*p == '\0') || (*q == '\0'))
194 return(toupper((int) *p)-toupper((int) *q));
197 static int convertHTMLcodes(char *s, int len)
199 if (len <=0 || s==(char*) NULL || *s=='\0')
206 if (sscanf(s,"&#%d;",&val) == 1)
216 (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
225 codes = (int) (sizeof(html_codes) / sizeof(html_code));
227 for (i=0; i < codes; i++)
229 if (html_codes[i].len <= len)
230 if (stringnicmp(s,html_codes[i].code,(size_t) html_codes[i].len) == 0)
232 (void) memmove(s+1,s+html_codes[i].len,
233 strlen(s+html_codes[i].len)+1);
234 *s=html_codes[i].val;
235 return html_codes[i].len-1;
242 static char *super_fgets(char **b, int *blen, Image *file)
253 p=(unsigned char *) (*b);
256 c=ReadBlobByte(file);
257 if (c == EOF || c == '\n')
259 if ((q-p+1) >= (int) len)
266 p=(unsigned char *) ResizeQuantumMemory(p,(size_t) len+2UL,sizeof(*p));
268 if (p == (unsigned char *) NULL)
272 *q=(unsigned char) c;
275 if (p != (unsigned char *) NULL)
282 return (char *) NULL;
290 #define THUMBNAIL_ID 1033
292 static ssize_t parse8BIM(Image *ifile, Image *ofile)
313 inputlen = MagickPathExtent;
328 line = (char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
329 if (line == (char *) NULL)
331 newstr = name = token = (char *) NULL;
333 token_info=AcquireTokenInfo();
334 while (super_fgets(&line,&inputlen,ifile)!=NULL)
339 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
340 if (token == (char *) NULL)
342 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
343 if (newstr == (char *) NULL)
345 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
346 &brkused,&next,"ed)==0)
360 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
361 "", 0,&brkused,&next,"ed)==0)
366 if (strcmp(newstr,"8BIM")==0)
369 dataset = (unsigned char) StringToLong(newstr);
372 recnum = (unsigned int) StringToUnsignedLong(newstr);
375 name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
378 (void) strcpy(name,newstr);
398 len = (ssize_t) strlen(token);
399 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
400 "",0,&brkused,&next,"ed)==0)
402 if (brkused && next > 0)
407 len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
424 ssize_t diff = outputlen - savedolen;
425 currentpos = TellBlob(ofile);
428 offset=SeekBlob(ofile,savedpos,SEEK_SET);
431 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
432 offset=SeekBlob(ofile,currentpos,SEEK_SET);
439 (void) WriteBlobByte(ofile,0x00);
442 (void) WriteBlobString(ofile,"8BIM");
443 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
446 nlen = (unsigned char) strlen(name);
447 (void) WriteBlobByte(ofile,nlen);
449 for (i=0; i<nlen; i++)
450 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
452 if ((nlen & 0x01) == 0)
454 (void) WriteBlobByte(ofile,0x00);
457 if (recnum != IPTC_ID)
459 (void) WriteBlobMSBLong(ofile, (unsigned int) len);
465 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
469 (void) WriteBlobByte(ofile,0x00);
475 /* patch in a fake length for now and fix it later */
476 savedpos = TellBlob(ofile);
479 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
481 savedolen = outputlen;
488 (void) WriteBlobByte(ofile,0x1c);
489 (void) WriteBlobByte(ofile,(unsigned char) dataset);
490 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
491 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
496 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
502 if (token != (char *) NULL)
503 token=DestroyString(token);
504 if (newstr != (char *) NULL)
505 newstr=DestroyString(newstr);
506 if (name != (char *) NULL)
507 name=DestroyString(name);
509 token_info=DestroyTokenInfo(token_info);
510 if (token != (char *) NULL)
511 token=DestroyString(token);
512 if (newstr != (char *) NULL)
513 newstr=DestroyString(newstr);
514 if (name != (char *) NULL)
515 name=DestroyString(name);
516 line=DestroyString(line);
522 ssize_t diff = outputlen - savedolen;
524 currentpos = TellBlob(ofile);
527 offset=SeekBlob(ofile,savedpos,SEEK_SET);
530 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
531 offset=SeekBlob(ofile,currentpos,SEEK_SET);
539 static char *super_fgets_w(char **b, int *blen, Image *file)
550 p=(unsigned char *) (*b);
553 c=(int) ReadBlobLSBShort(file);
554 if ((c == -1) || (c == '\n'))
558 if ((q-p+1) >= (int) len)
565 p=(unsigned char *) ResizeQuantumMemory(p,(size_t) (len+2),sizeof(*p));
567 if (p == (unsigned char *) NULL)
571 *q=(unsigned char) c;
574 if ((*b) != (char *) NULL)
581 return (char *) NULL;
588 static ssize_t parse8BIMW(Image *ifile, Image *ofile)
609 inputlen = MagickPathExtent;
624 line=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
625 if (line == (char *) NULL)
627 newstr = name = token = (char *) NULL;
629 token_info=AcquireTokenInfo();
630 while (super_fgets_w(&line,&inputlen,ifile) != NULL)
635 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
636 if (token == (char *) NULL)
638 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
639 if (newstr == (char *) NULL)
641 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
642 &brkused,&next,"ed)==0)
656 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
657 "",0,&brkused,&next,"ed)==0)
662 if (strcmp(newstr,"8BIM")==0)
665 dataset = (unsigned char) StringToLong(newstr);
668 recnum=(unsigned int) StringToUnsignedLong(newstr);
671 name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
674 (void) CopyMagickString(name,newstr,strlen(newstr)+MagickPathExtent);
694 len = (ssize_t) strlen(token);
695 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
696 "",0,&brkused,&next,"ed)==0)
698 if (brkused && next > 0)
703 len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
720 ssize_t diff = outputlen - savedolen;
721 currentpos = TellBlob(ofile);
724 offset=SeekBlob(ofile,savedpos,SEEK_SET);
727 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
728 offset=SeekBlob(ofile,currentpos,SEEK_SET);
735 (void) WriteBlobByte(ofile,0x00);
738 (void) WriteBlobString(ofile,"8BIM");
739 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
742 nlen = (unsigned char) strlen(name);
743 (void) WriteBlobByte(ofile,(unsigned char) nlen);
745 for (i=0; i<nlen; i++)
746 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
748 if ((nlen & 0x01) == 0)
750 (void) WriteBlobByte(ofile,0x00);
753 if (recnum != IPTC_ID)
755 (void) WriteBlobMSBLong(ofile,(unsigned int) len);
761 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
765 (void) WriteBlobByte(ofile,0x00);
771 /* patch in a fake length for now and fix it later */
772 savedpos = TellBlob(ofile);
775 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
777 savedolen = outputlen;
784 (void) WriteBlobByte(ofile,0x1c);
785 (void) WriteBlobByte(ofile,dataset);
786 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
787 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
792 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
798 if (token != (char *) NULL)
799 token=DestroyString(token);
800 if (newstr != (char *) NULL)
801 newstr=DestroyString(newstr);
802 if (name != (char *) NULL)
803 name=DestroyString(name);
805 token_info=DestroyTokenInfo(token_info);
806 if (token != (char *) NULL)
807 token=DestroyString(token);
808 if (newstr != (char *) NULL)
809 newstr=DestroyString(newstr);
810 if (name != (char *) NULL)
811 name=DestroyString(name);
812 line=DestroyString(line);
818 ssize_t diff = outputlen - savedolen;
820 currentpos = TellBlob(ofile);
823 offset=SeekBlob(ofile,savedpos,SEEK_SET);
826 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
827 offset=SeekBlob(ofile,currentpos,SEEK_SET);
835 /* some defines for the different JPEG block types */
836 #define M_SOF0 0xC0 /* Start Of Frame N */
837 #define M_SOF1 0xC1 /* N indicates which compression process */
838 #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
840 #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
850 #define M_EOI 0xD9 /* End Of Image (end of datastream) */
851 #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
869 static int jpeg_transfer_1(Image *ifile, Image *ofile)
873 c = ReadBlobByte(ifile);
876 (void) WriteBlobByte(ofile,(unsigned char) c);
881 static int jpeg_skip_1(Image *ifile)
885 c = ReadBlobByte(ifile);
892 static int jpeg_read_remaining(Image *ifile, Image *ofile)
896 while ((c = jpeg_transfer_1(ifile, ofile)) != EOF)
901 static int jpeg_skip_variable(Image *ifile, Image *ofile)
906 if ((c1 = jpeg_transfer_1(ifile, ofile)) == EOF)
908 if ((c2 = jpeg_transfer_1(ifile, ofile)) == EOF)
911 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
915 if (jpeg_transfer_1(ifile, ofile) == EOF)
921 static int jpeg_skip_variable2(Image *ifile, Image *ofile)
927 if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
928 if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
930 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
934 if (ReadBlobByte(ifile) == EOF)
940 static int jpeg_nextmarker(Image *ifile, Image *ofile)
944 /* transfer anything until we hit 0xff */
947 c = ReadBlobByte(ifile);
949 return M_EOI; /* we hit EOF */
952 (void) WriteBlobByte(ofile,(unsigned char) c);
955 /* get marker byte, swallowing possible padding */
958 c = ReadBlobByte(ifile);
960 return M_EOI; /* we hit EOF */
967 static int jpeg_skip_till_marker(Image *ifile, int marker)
973 /* skip anything until we hit 0xff */
977 c = ReadBlobByte(ifile);
980 return M_EOI; /* we hit EOF */
983 /* get marker byte, swallowing possible padding */
986 c = ReadBlobByte(ifile);
988 return M_EOI; /* we hit EOF */
990 } while (c != marker);
995 /* Embed binary IPTC data into a JPEG image. */
996 static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
999 unsigned int done = 0;
1003 if (jpeg_transfer_1(ifile, ofile) != 0xFF)
1005 if (jpeg_transfer_1(ifile, ofile) != M_SOI)
1008 while (done == MagickFalse)
1010 marker=(unsigned int) jpeg_nextmarker(ifile, ofile);
1011 if (marker == M_EOI)
1017 if (marker != M_APP13)
1019 (void) WriteBlobByte(ofile,0xff);
1020 (void) WriteBlobByte(ofile,(unsigned char) marker);
1027 /* we are going to write a new APP13 marker, so don't output the old one */
1028 jpeg_skip_variable2(ifile, ofile);
1032 /* APP0 is in each and every JPEG, so when we hit APP0 we insert our new APP13! */
1033 jpeg_skip_variable(ifile, ofile);
1035 if (iptc != (Image *) NULL)
1038 psheader[] = "\xFF\xED\0\0Photoshop 3.0\0" "8BIM\x04\x04\0\0\0\0";
1040 len=(unsigned int) GetBlobSize(iptc);
1042 len++; /* make the length even */
1043 psheader[2]=(char) ((len+16)>>8);
1044 psheader[3]=(char) ((len+16)&0xff);
1045 for (inx = 0; inx < 18; inx++)
1046 (void) WriteBlobByte(ofile,(unsigned char) psheader[inx]);
1047 jpeg_read_remaining(iptc, ofile);
1048 len=(unsigned int) GetBlobSize(iptc);
1050 (void) WriteBlobByte(ofile,0);
1055 /* we hit data, no more marker-inserting can be done! */
1056 jpeg_read_remaining(ifile, ofile);
1061 jpeg_skip_variable(ifile, ofile);
1068 /* handle stripping the APP13 data out of a JPEG */
1070 static void jpeg_strip(Image *ifile, Image *ofile)
1072 unsigned int marker;
1074 marker = jpeg_skip_till_marker(ifile, M_SOI);
1075 if (marker == M_SOI)
1077 (void) WriteBlobByte(ofile,0xff);
1078 (void) WriteBlobByte(ofile,M_SOI);
1079 jpeg_read_remaining(ifile, ofile);
1083 /* Extract any APP13 binary data into a file. */
1084 static int jpeg_extract(Image *ifile, Image *ofile)
1086 unsigned int marker;
1087 unsigned int done = 0;
1089 if (jpeg_skip_1(ifile) != 0xff)
1091 if (jpeg_skip_1(ifile) != M_SOI)
1094 while (done == MagickFalse)
1096 marker = jpeg_skip_till_marker(ifile, M_APP13);
1097 if (marker == M_APP13)
1099 marker = jpeg_nextmarker(ifile, ofile);
1107 static inline void CopyBlob(Image *source,Image *destination)
1119 buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1121 if (buffer != (unsigned char *) NULL)
1124 while ((length=ReadBlob(source,MagickMaxBufferExtent,buffer)) != 0)
1127 for (i=0; i < (ssize_t) length; i+=count)
1129 count=WriteBlob(destination,(size_t) (length-i),buffer+i);
1133 if (i < (ssize_t) length)
1136 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1140 static Image *ReadMETAImage(const ImageInfo *image_info,
1141 ExceptionInfo *exception)
1160 Open file containing binary metadata
1162 assert(image_info != (const ImageInfo *) NULL);
1163 assert(image_info->signature == MagickCoreSignature);
1164 if (image_info->debug != MagickFalse)
1165 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1166 image_info->filename);
1167 assert(exception != (ExceptionInfo *) NULL);
1168 assert(exception->signature == MagickCoreSignature);
1169 image=AcquireImage(image_info,exception);
1170 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1171 if (status == MagickFalse)
1173 image=DestroyImageList(image);
1174 return((Image *) NULL);
1178 if (SetImageBackgroundColor(image,exception) == MagickFalse)
1180 image=DestroyImageList(image);
1181 return((Image *) NULL);
1184 if (LocaleNCompare(image_info->magick,"8BIM",4) == 0)
1187 Read 8BIM binary metadata.
1189 buff=AcquireImage((ImageInfo *) NULL,exception);
1190 if (buff == (Image *) NULL)
1191 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1192 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1193 if (blob == (unsigned char *) NULL)
1195 buff=DestroyImage(buff);
1196 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1198 AttachBlob(buff->blob,blob,length);
1199 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
1201 length=(size_t) parse8BIM(image, buff);
1203 (void) WriteBlobByte(buff,0x0);
1205 else if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
1207 length=(size_t) parse8BIMW(image, buff);
1209 (void) WriteBlobByte(buff,0x0);
1212 CopyBlob(image,buff);
1213 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1215 if (profile == (StringInfo *) NULL)
1216 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1217 status=SetImageProfile(image,"8bim",profile,exception);
1218 profile=DestroyStringInfo(profile);
1219 if (status == MagickFalse)
1220 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1221 blob=DetachBlob(buff->blob);
1222 blob=(unsigned char *) RelinquishMagickMemory(blob);
1223 buff=DestroyImage(buff);
1225 if (LocaleNCompare(image_info->magick,"APP1",4) == 0)
1228 name[MagickPathExtent];
1230 (void) FormatLocaleString(name,MagickPathExtent,"APP%d",1);
1231 buff=AcquireImage((ImageInfo *) NULL,exception);
1232 if (buff == (Image *) NULL)
1233 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1234 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1235 if (blob == (unsigned char *) NULL)
1237 buff=DestroyImage(buff);
1238 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1240 AttachBlob(buff->blob,blob,length);
1241 if (LocaleCompare(image_info->magick,"APP1JPEG") == 0)
1249 if (image_info->profile == (void *) NULL)
1251 blob=DetachBlob(buff->blob);
1252 blob=RelinquishMagickMemory(blob);
1253 buff=DestroyImage(buff);
1254 ThrowReaderException(CoderError,"NoIPTCProfileAvailable");
1256 profile=CloneStringInfo((StringInfo *) image_info->profile);
1257 iptc=AcquireImage((ImageInfo *) NULL,exception);
1258 if (iptc == (Image *) NULL)
1260 blob=DetachBlob(buff->blob);
1261 blob=RelinquishMagickMemory(blob);
1262 buff=DestroyImage(buff);
1263 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1265 AttachBlob(iptc->blob,GetStringInfoDatum(profile),
1266 GetStringInfoLength(profile));
1267 result=jpeg_embed(image,buff,iptc);
1268 blob=DetachBlob(iptc->blob);
1269 blob=RelinquishMagickMemory(blob);
1270 iptc=DestroyImage(iptc);
1273 blob=DetachBlob(buff->blob);
1274 blob=RelinquishMagickMemory(blob);
1275 buff=DestroyImage(buff);
1276 ThrowReaderException(CoderError,"JPEGEmbeddingFailed");
1280 CopyBlob(image,buff);
1281 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1283 if (profile == (StringInfo *) NULL)
1284 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1285 status=SetImageProfile(image,name,profile,exception);
1286 profile=DestroyStringInfo(profile);
1287 if (status == MagickFalse)
1288 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1289 blob=DetachBlob(buff->blob);
1290 blob=RelinquishMagickMemory(blob);
1291 buff=DestroyImage(buff);
1293 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
1294 (LocaleCompare(image_info->magick,"ICM") == 0))
1296 buff=AcquireImage((ImageInfo *) NULL,exception);
1297 if (buff == (Image *) NULL)
1298 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1299 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1300 if (blob == (unsigned char *) NULL)
1302 buff=DestroyImage(buff);
1303 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1305 AttachBlob(buff->blob,blob,length);
1306 CopyBlob(image,buff);
1307 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1309 if (profile == (StringInfo *) NULL)
1310 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1311 (void) SetImageProfile(image,"icc",profile,exception);
1312 profile=DestroyStringInfo(profile);
1313 blob=DetachBlob(buff->blob);
1314 blob=(unsigned char *) RelinquishMagickMemory(blob);
1315 buff=DestroyImage(buff);
1317 if (LocaleCompare(image_info->magick,"IPTC") == 0)
1319 buff=AcquireImage((ImageInfo *) NULL,exception);
1320 if (buff == (Image *) NULL)
1321 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1322 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1323 if (blob == (unsigned char *) NULL)
1325 buff=DestroyImage(buff);
1326 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1328 AttachBlob(buff->blob,blob,length);
1329 CopyBlob(image,buff);
1330 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1332 if (profile == (StringInfo *) NULL)
1333 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1334 (void) SetImageProfile(image,"8bim",profile,exception);
1335 profile=DestroyStringInfo(profile);
1336 blob=DetachBlob(buff->blob);
1337 blob=(unsigned char *) RelinquishMagickMemory(blob);
1338 buff=DestroyImage(buff);
1340 if (LocaleCompare(image_info->magick,"XMP") == 0)
1342 buff=AcquireImage((ImageInfo *) NULL,exception);
1343 if (buff == (Image *) NULL)
1344 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1345 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1346 if (blob == (unsigned char *) NULL)
1348 buff=DestroyImage(buff);
1349 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1351 AttachBlob(buff->blob,blob,length);
1352 CopyBlob(image,buff);
1353 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1355 if (profile == (StringInfo *) NULL)
1356 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1357 (void) SetImageProfile(image,"xmp",profile,exception);
1358 profile=DestroyStringInfo(profile);
1359 blob=DetachBlob(buff->blob);
1360 blob=(unsigned char *) RelinquishMagickMemory(blob);
1361 buff=DestroyImage(buff);
1363 (void) CloseBlob(image);
1364 return(GetFirstImageInList(image));
1368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1372 % R e g i s t e r M E T A I m a g e %
1376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1378 % RegisterMETAImage() adds attributes for the META image format to
1379 % the list of supported formats. The attributes include the image format
1380 % tag, a method to read and/or write the format, whether the format
1381 % supports the saving of more than one frame to the same file or blob,
1382 % whether the format supports native in-memory I/O, and a brief
1383 % description of the format.
1385 % The format of the RegisterMETAImage method is:
1387 % size_t RegisterMETAImage(void)
1390 ModuleExport size_t RegisterMETAImage(void)
1395 entry=AcquireMagickInfo("META","8BIM","Photoshop resource format");
1396 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1397 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1398 entry->flags^=CoderAdjoinFlag;
1399 entry->flags|=CoderStealthFlag;
1400 entry->flags|=CoderSeekableStreamFlag;
1401 (void) RegisterMagickInfo(entry);
1402 entry=AcquireMagickInfo("META","8BIMTEXT","Photoshop resource text format");
1403 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1404 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1405 entry->flags^=CoderAdjoinFlag;
1406 entry->flags|=CoderStealthFlag;
1407 entry->flags|=CoderSeekableStreamFlag;
1408 (void) RegisterMagickInfo(entry);
1409 entry=AcquireMagickInfo("META","8BIMWTEXT",
1410 "Photoshop resource wide text format");
1411 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1412 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1413 entry->flags^=CoderAdjoinFlag;
1414 entry->flags|=CoderStealthFlag;
1415 entry->flags|=CoderSeekableStreamFlag;
1416 (void) RegisterMagickInfo(entry);
1417 entry=AcquireMagickInfo("META","APP1","Raw application information");
1418 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1419 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1420 entry->flags^=CoderAdjoinFlag;
1421 entry->flags|=CoderStealthFlag;
1422 entry->flags|=CoderSeekableStreamFlag;
1423 (void) RegisterMagickInfo(entry);
1424 entry=AcquireMagickInfo("META","APP1JPEG","Raw JPEG binary data");
1425 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1426 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1427 entry->flags^=CoderAdjoinFlag;
1428 entry->flags|=CoderStealthFlag;
1429 entry->flags|=CoderSeekableStreamFlag;
1430 (void) RegisterMagickInfo(entry);
1431 entry=AcquireMagickInfo("META","EXIF","Exif digital camera binary data");
1432 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1433 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1434 entry->flags^=CoderAdjoinFlag;
1435 entry->flags|=CoderStealthFlag;
1436 entry->flags|=CoderSeekableStreamFlag;
1437 (void) RegisterMagickInfo(entry);
1438 entry=AcquireMagickInfo("META","XMP","Adobe XML metadata");
1439 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1440 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1441 entry->flags^=CoderAdjoinFlag;
1442 entry->flags|=CoderStealthFlag;
1443 entry->flags|=CoderSeekableStreamFlag;
1444 (void) RegisterMagickInfo(entry);
1445 entry=AcquireMagickInfo("META","ICM","ICC Color Profile");
1446 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1447 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1448 entry->flags^=CoderAdjoinFlag;
1449 entry->flags|=CoderStealthFlag;
1450 entry->flags|=CoderSeekableStreamFlag;
1451 (void) RegisterMagickInfo(entry);
1452 entry=AcquireMagickInfo("META","ICC","ICC Color Profile");
1453 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1454 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1455 entry->flags^=CoderAdjoinFlag;
1456 entry->flags|=CoderStealthFlag;
1457 entry->flags|=CoderSeekableStreamFlag;
1458 (void) RegisterMagickInfo(entry);
1459 entry=AcquireMagickInfo("META","IPTC","IPTC Newsphoto");
1460 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1461 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1462 entry->flags^=CoderAdjoinFlag;
1463 entry->flags|=CoderStealthFlag;
1464 entry->flags|=CoderSeekableStreamFlag;
1465 (void) RegisterMagickInfo(entry);
1466 entry=AcquireMagickInfo("META","IPTCTEXT","IPTC Newsphoto text format");
1467 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1468 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1469 entry->flags^=CoderAdjoinFlag;
1470 entry->flags|=CoderStealthFlag;
1471 entry->flags|=CoderSeekableStreamFlag;
1472 (void) RegisterMagickInfo(entry);
1473 entry=AcquireMagickInfo("META","IPTCWTEXT","IPTC Newsphoto text format");
1474 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1475 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1476 entry->flags^=CoderAdjoinFlag;
1477 entry->flags|=CoderStealthFlag;
1478 entry->flags|=CoderSeekableStreamFlag;
1479 (void) RegisterMagickInfo(entry);
1480 return(MagickImageCoderSignature);
1484 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1488 % U n r e g i s t e r M E T A I m a g e %
1492 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494 % UnregisterMETAImage() removes format registrations made by the
1495 % META module from the list of supported formats.
1497 % The format of the UnregisterMETAImage method is:
1499 % UnregisterMETAImage(void)
1502 ModuleExport void UnregisterMETAImage(void)
1504 (void) UnregisterMagickInfo("8BIM");
1505 (void) UnregisterMagickInfo("8BIMTEXT");
1506 (void) UnregisterMagickInfo("8BIMWTEXT");
1507 (void) UnregisterMagickInfo("EXIF");
1508 (void) UnregisterMagickInfo("APP1");
1509 (void) UnregisterMagickInfo("APP1JPEG");
1510 (void) UnregisterMagickInfo("ICCTEXT");
1511 (void) UnregisterMagickInfo("ICM");
1512 (void) UnregisterMagickInfo("ICC");
1513 (void) UnregisterMagickInfo("IPTC");
1514 (void) UnregisterMagickInfo("IPTCTEXT");
1515 (void) UnregisterMagickInfo("IPTCWTEXT");
1516 (void) UnregisterMagickInfo("XMP");
1520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1524 % W r i t e M E T A I m a g e %
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1530 % WriteMETAImage() writes a META image to a file.
1532 % The format of the WriteMETAImage method is:
1534 % MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
1535 % Image *image,ExceptionInfo *exception)
1537 % Compression code contributed by Kyle Shorter.
1539 % A description of each parameter follows:
1541 % o image_info: Specifies a pointer to an ImageInfo structure.
1543 % o image: A pointer to a Image structure.
1545 % o exception: return any errors or warnings in this structure.
1549 static size_t GetIPTCStream(unsigned char **info,size_t length)
1557 register unsigned char
1572 if ((*p == 0x1c) && (*(p+1) == 0x02))
1575 Extract IPTC from 8BIM resource block.
1577 while (extent >= 12)
1579 if (strncmp((const char *) p,"8BIM",4))
1583 marker=(unsigned int) (*p) << 8 | *(p+1);
1589 if ((size_t) c >= extent)
1595 tag_length=(((size_t) *p) << 24) | (((size_t) *(p+1)) << 16) |
1596 (((size_t) *(p+2)) << 8) | ((size_t) *(p+3));
1599 if (tag_length > extent)
1601 if (marker == IPTC_ID)
1606 if ((tag_length & 0x01) != 0)
1612 Find the beginning of the IPTC info.
1628 *info=p; /* let the caller know were it is */
1633 Determine the length of the IPTC info.
1650 Found the 0x1c tag; skip the dataset and record number tags.
1652 c=(*p++); /* should be 2 */
1656 if ((info_length == 1) && (c != 2))
1659 c=(*p++); /* should be 0 */
1663 if ((info_length == 2) && (c != 0))
1667 Decode the length of the block that follows - ssize_t or short format.
1674 if ((c & 0x80) != 0)
1680 for (i=0; i < 4; i++)
1695 tag_length=((long) c) << 8;
1701 tag_length|=(long) c;
1703 if (tag_length > (length+1))
1709 info_length+=tag_length;
1711 return(info_length);
1714 static void formatString(Image *ofile, const char *s, int len)
1717 temp[MagickPathExtent];
1719 (void) WriteBlobByte(ofile,'"');
1720 for (; len > 0; len--, s++) {
1724 (void) WriteBlobString(ofile,"&");
1728 (void) WriteBlobString(ofile,"<");
1731 (void) WriteBlobString(ofile,">");
1735 (void) WriteBlobString(ofile,""");
1739 (void) WriteBlobByte(ofile,(unsigned char) *s);
1742 (void) FormatLocaleString(temp,MagickPathExtent,"&#%d;", c & 255);
1743 (void) WriteBlobString(ofile,temp);
1748 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1749 (void) WriteBlobString(ofile,"\"\r\n");
1751 #if defined(macintosh)
1752 (void) WriteBlobString(ofile,"\"\r");
1754 (void) WriteBlobString(ofile,"\"\n");
1759 typedef struct _tag_spec
1768 static const tag_spec tags[] = {
1769 { 5, "Image Name" },
1770 { 7, "Edit Status" },
1773 { 20, "Supplemental Category" },
1774 { 22, "Fixture Identifier" },
1776 { 30, "Release Date" },
1777 { 35, "Release Time" },
1778 { 40, "Special Instructions" },
1779 { 45, "Reference Service" },
1780 { 47, "Reference Date" },
1781 { 50, "Reference Number" },
1782 { 55, "Created Date" },
1783 { 60, "Created Time" },
1784 { 65, "Originating Program" },
1785 { 70, "Program Version" },
1786 { 75, "Object Cycle" },
1788 { 85, "Byline Title" },
1790 { 92, "Sub-Location" },
1791 { 95, "Province State" },
1792 { 100, "Country Code" },
1794 { 103, "Original Transmission Reference" },
1795 { 105, "Headline" },
1798 { 116, "Copyright String" },
1800 { 121, "Image Orientation" },
1801 { 122, "Caption Writer" },
1802 { 131, "Local Caption" },
1803 { 200, "Custom Field 1" },
1804 { 201, "Custom Field 2" },
1805 { 202, "Custom Field 3" },
1806 { 203, "Custom Field 4" },
1807 { 204, "Custom Field 5" },
1808 { 205, "Custom Field 6" },
1809 { 206, "Custom Field 7" },
1810 { 207, "Custom Field 8" },
1811 { 208, "Custom Field 9" },
1812 { 209, "Custom Field 10" },
1813 { 210, "Custom Field 11" },
1814 { 211, "Custom Field 12" },
1815 { 212, "Custom Field 13" },
1816 { 213, "Custom Field 14" },
1817 { 214, "Custom Field 15" },
1818 { 215, "Custom Field 16" },
1819 { 216, "Custom Field 17" },
1820 { 217, "Custom Field 18" },
1821 { 218, "Custom Field 19" },
1822 { 219, "Custom Field 20" }
1825 static int formatIPTC(Image *ifile, Image *ofile)
1828 temp[MagickPathExtent];
1848 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
1853 foundiptc = 0; /* found the IPTC-Header */
1854 tagsfound = 0; /* number of tags found */
1856 c = ReadBlobByte(ifile);
1872 /* we found the 0x1c tag and now grab the dataset and record number tags */
1873 c = ReadBlobByte(ifile);
1874 if (c == EOF) return -1;
1875 dataset = (unsigned char) c;
1876 c = ReadBlobByte(ifile);
1877 if (c == EOF) return -1;
1878 recnum = (unsigned char) c;
1879 /* try to match this record to one of the ones in our named table */
1880 for (i=0; i< tagcount; i++)
1882 if (tags[i].id == (short) recnum)
1886 readable = (unsigned char *) tags[i].name;
1888 readable = (unsigned char *) "";
1890 We decode the length of the block that follows - ssize_t or short fmt.
1892 c=ReadBlobByte(ifile);
1893 if (c == EOF) return -1;
1894 if (c & (unsigned char) 0x80)
1901 c0=ReadBlobByte(ifile);
1902 if (c0 == EOF) return -1;
1903 taglen = (c << 8) | c0;
1905 if (taglen < 0) return -1;
1906 /* make a buffer to hold the tag datand snag it from the input stream */
1907 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MagickPathExtent),
1909 if (str == (unsigned char *) NULL)
1911 printf("MemoryAllocationFailed");
1914 for (tagindx=0; tagindx<taglen; tagindx++)
1916 c=ReadBlobByte(ifile);
1917 if (c == EOF) return -1;
1918 str[tagindx] = (unsigned char) c;
1922 /* now finish up by formatting this binary data into ASCII equivalent */
1923 if (strlen((char *)readable) > 0)
1924 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
1925 (unsigned int) dataset, (unsigned int) recnum, readable);
1927 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
1928 (unsigned int) dataset,(unsigned int) recnum);
1929 (void) WriteBlobString(ofile,temp);
1930 formatString( ofile, (char *)str, taglen );
1931 str=(unsigned char *) RelinquishMagickMemory(str);
1935 c=ReadBlobByte(ifile);
1937 return((int) tagsfound);
1940 static int readWordFromBuffer(char **s, ssize_t *len)
1951 c = *(*s)++; (*len)--;
1952 if (*len < 0) return -1;
1953 buffer[i] = (unsigned char) c;
1955 return (((int) buffer[ 0 ]) << 8) |
1956 (((int) buffer[ 1 ]));
1959 static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
1962 temp[MagickPathExtent];
1982 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
1987 foundiptc = 0; /* found the IPTC-Header */
1988 tagsfound = 0; /* number of tags found */
2003 We found the 0x1c tag and now grab the dataset and record number tags.
2006 if (len < 0) return -1;
2007 dataset = (unsigned char) c;
2009 if (len < 0) return -1;
2010 recnum = (unsigned char) c;
2011 /* try to match this record to one of the ones in our named table */
2012 for (i=0; i< tagcount; i++)
2013 if (tags[i].id == (short) recnum)
2016 readable=(unsigned char *) tags[i].name;
2018 readable=(unsigned char *) "";
2020 We decode the length of the block that follows - ssize_t or short fmt.
2026 if (c & (unsigned char) 0x80)
2032 taglen=readWordFromBuffer(&s, &len);
2038 /* make a buffer to hold the tag datand snag it from the input stream */
2039 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MagickPathExtent),
2041 if (str == (unsigned char *) NULL)
2043 printf("MemoryAllocationFailed");
2046 for (tagindx=0; tagindx<taglen; tagindx++)
2051 str[tagindx]=(unsigned char) c;
2055 /* now finish up by formatting this binary data into ASCII equivalent */
2056 if (strlen((char *)readable) > 0)
2057 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
2058 (unsigned int) dataset,(unsigned int) recnum, readable);
2060 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
2061 (unsigned int) dataset,(unsigned int) recnum);
2062 (void) WriteBlobString(ofile,temp);
2063 formatString( ofile, (char *)str, taglen );
2064 str=(unsigned char *) RelinquishMagickMemory(str);
2068 return ((int) tagsfound);
2071 static int format8BIM(Image *ifile, Image *ofile)
2074 temp[MagickPathExtent];
2093 foundOSType=0; /* found the OSType */
2095 c=ReadBlobByte(ifile);
2103 buffer[0]=(unsigned char) c;
2106 c=ReadBlobByte(ifile);
2109 buffer[i] = (unsigned char) c;
2112 if (strcmp((const char *)buffer, "8BIM") == 0)
2119 c=ReadBlobByte(ifile);
2123 We found the OSType (8BIM) and now grab the ID, PString, and Size fields.
2125 ID=(int) ReadBlobMSBShort(ifile);
2132 c=ReadBlobByte(ifile);
2135 plen = (unsigned char) c;
2136 PString=(unsigned char *) AcquireQuantumMemory((size_t) (plen+
2137 MagickPathExtent),sizeof(*PString));
2138 if (PString == (unsigned char *) NULL)
2140 printf("MemoryAllocationFailed");
2143 for (i=0; i<plen; i++)
2145 c=ReadBlobByte(ifile);
2146 if (c == EOF) return -1;
2147 PString[i] = (unsigned char) c;
2149 PString[ plen ] = 0;
2150 if ((plen & 0x01) == 0)
2152 c=ReadBlobByte(ifile);
2157 count = (int) ReadBlobMSBLong(ifile);
2158 if (count < 0) return -1;
2159 /* make a buffer to hold the datand snag it from the input stream */
2160 str=(unsigned char *) AcquireQuantumMemory((size_t) count,sizeof(*str));
2161 if (str == (unsigned char *) NULL)
2163 printf("MemoryAllocationFailed");
2166 for (i=0; i < (ssize_t) count; i++)
2168 c=ReadBlobByte(ifile);
2171 str[i]=(unsigned char) c;
2174 /* we currently skip thumbnails, since it does not make
2175 * any sense preserving them in a real world application
2177 if (ID != THUMBNAIL_ID)
2179 /* now finish up by formatting this binary data into
2182 if (strlen((const char *)PString) > 0)
2183 (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d#%s=",ID,
2186 (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d=",ID);
2187 (void) WriteBlobString(ofile,temp);
2190 formatString(ofile, "IPTC", 4);
2191 formatIPTCfromBuffer(ofile, (char *)str, (ssize_t) count);
2194 formatString(ofile, (char *)str, (ssize_t) count);
2196 str=(unsigned char *) RelinquishMagickMemory(str);
2197 PString=(unsigned char *) RelinquishMagickMemory(PString);
2199 c=ReadBlobByte(ifile);
2204 static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
2205 Image *image,ExceptionInfo *exception)
2219 assert(image_info != (const ImageInfo *) NULL);
2220 assert(image_info->signature == MagickCoreSignature);
2221 assert(image != (Image *) NULL);
2222 assert(image->signature == MagickCoreSignature);
2223 if (image->debug != MagickFalse)
2224 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2226 if (LocaleCompare(image_info->magick,"8BIM") == 0)
2231 profile=GetImageProfile(image,"8bim");
2232 if (profile == (StringInfo *) NULL)
2233 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2234 assert(exception != (ExceptionInfo *) NULL);
2235 assert(exception->signature == MagickCoreSignature);
2236 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2237 if (status == MagickFalse)
2239 (void) WriteBlob(image,GetStringInfoLength(profile),
2240 GetStringInfoDatum(profile));
2241 (void) CloseBlob(image);
2244 if (LocaleCompare(image_info->magick,"iptc") == 0)
2252 profile=GetImageProfile(image,"iptc");
2253 if (profile == (StringInfo *) NULL)
2254 profile=GetImageProfile(image,"8bim");
2255 if (profile == (StringInfo *) NULL)
2256 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2257 assert(exception != (ExceptionInfo *) NULL);
2258 assert(exception->signature == MagickCoreSignature);
2259 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2260 info=GetStringInfoDatum(profile);
2261 length=GetStringInfoLength(profile);
2262 length=GetIPTCStream(&info,length);
2264 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2265 (void) WriteBlob(image,length,info);
2266 (void) CloseBlob(image);
2269 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
2274 profile=GetImageProfile(image,"8bim");
2275 if (profile == (StringInfo *) NULL)
2276 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2277 assert(exception != (ExceptionInfo *) NULL);
2278 assert(exception->signature == MagickCoreSignature);
2279 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2280 if (status == MagickFalse)
2282 buff=AcquireImage((ImageInfo *) NULL,exception);
2283 if (buff == (Image *) NULL)
2284 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2285 AttachBlob(buff->blob,GetStringInfoDatum(profile),
2286 GetStringInfoLength(profile));
2287 format8BIM(buff,image);
2288 (void) DetachBlob(buff->blob);
2289 buff=DestroyImage(buff);
2290 (void) CloseBlob(image);
2293 if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
2294 return(MagickFalse);
2295 if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0)
2303 profile=GetImageProfile(image,"8bim");
2304 if (profile == (StringInfo *) NULL)
2305 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2306 info=GetStringInfoDatum(profile);
2307 length=GetStringInfoLength(profile);
2308 length=GetIPTCStream(&info,length);
2310 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2311 assert(exception != (ExceptionInfo *) NULL);
2312 assert(exception->signature == MagickCoreSignature);
2313 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2314 if (status == MagickFalse)
2316 buff=AcquireImage((ImageInfo *) NULL,exception);
2317 if (buff == (Image *) NULL)
2318 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2319 AttachBlob(buff->blob,info,length);
2320 formatIPTC(buff,image);
2321 (void) DetachBlob(buff->blob);
2322 buff=DestroyImage(buff);
2323 (void) CloseBlob(image);
2326 if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0)
2327 return(MagickFalse);
2328 if ((LocaleCompare(image_info->magick,"APP1") == 0) ||
2329 (LocaleCompare(image_info->magick,"EXIF") == 0) ||
2330 (LocaleCompare(image_info->magick,"XMP") == 0))
2333 (void) Write APP1 image.
2335 profile=GetImageProfile(image,image_info->magick);
2336 if (profile == (StringInfo *) NULL)
2337 ThrowWriterException(CoderError,"NoAPP1DataIsAvailable");
2338 assert(exception != (ExceptionInfo *) NULL);
2339 assert(exception->signature == MagickCoreSignature);
2340 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2341 if (status == MagickFalse)
2343 (void) WriteBlob(image,GetStringInfoLength(profile),
2344 GetStringInfoDatum(profile));
2345 (void) CloseBlob(image);
2348 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
2349 (LocaleCompare(image_info->magick,"ICM") == 0))
2354 profile=GetImageProfile(image,"icc");
2355 if (profile == (StringInfo *) NULL)
2356 ThrowWriterException(CoderError,"NoColorProfileIsAvailable");
2357 assert(exception != (ExceptionInfo *) NULL);
2358 assert(exception->signature == MagickCoreSignature);
2359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2360 if (status == MagickFalse)
2362 (void) WriteBlob(image,GetStringInfoLength(profile),
2363 GetStringInfoDatum(profile));
2364 (void) CloseBlob(image);
2367 return(MagickFalse);