2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M EEEEE TTTTT AAA %
13 % Read/Write Embedded Image Profiles. %
20 % Copyright 1999-2018 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 % https://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 size_t convertHTMLcodes(char *s, const size_t len)
202 if ((len == 0) || (s == (char*) NULL) || (*s=='\0'))
204 if ((len > 3) && (s[1] == '#') && (strchr(s,';') != (char *) NULL) &&
205 (sscanf(s,"&#%d;",&value) == 1))
215 (void) memmove(s+1,s+1+o,strlen(s+1+o)+1);
225 codes=sizeof(html_codes)/sizeof(html_code);
226 for (i=0; i < codes; i++)
228 if (html_codes[i].len <= (ssize_t) len)
229 if (stringnicmp(s, html_codes[i].code,(size_t) (html_codes[i].len)) == 0)
231 (void) memmove(s+1,s+html_codes[i].len,
232 strlen(s+html_codes[i].len)+1);
233 *s=html_codes[i].val;
234 return(html_codes[i].len-1);
241 static char *super_fgets(char **b, int *blen, Image *file)
252 p=(unsigned char *) (*b);
255 c=ReadBlobByte(file);
256 if (c == EOF || c == '\n')
258 if ((q-p+1) >= (int) len)
265 p=(unsigned char *) ResizeQuantumMemory(p,(size_t) len+2UL,sizeof(*p));
267 if (p == (unsigned char *) NULL)
271 *q=(unsigned char) c;
274 if (p != (unsigned char *) NULL)
281 return (char *) NULL;
289 #define THUMBNAIL_ID 1033
291 static ssize_t parse8BIM(Image *ifile, Image *ofile)
312 inputlen = MagickPathExtent;
327 line = (char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
328 if (line == (char *) NULL)
330 newstr = name = token = (char *) NULL;
332 token_info=AcquireTokenInfo();
333 while (super_fgets(&line,&inputlen,ifile)!=NULL)
338 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
339 if (token == (char *) NULL)
341 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
342 if (newstr == (char *) NULL)
344 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
345 &brkused,&next,"ed)==0)
359 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
360 "", 0,&brkused,&next,"ed)==0)
365 if (strcmp(newstr,"8BIM")==0)
368 dataset = (unsigned char) StringToLong(newstr);
371 recnum = (unsigned int) StringToUnsignedLong(newstr);
374 name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
377 (void) strcpy(name,newstr);
397 len = (ssize_t) strlen(token);
398 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
399 "",0,&brkused,&next,"ed)==0)
401 if (brkused && next > 0)
409 codes_length=convertHTMLcodes(s, strlen(s));
410 if ((ssize_t) codes_length > len)
430 ssize_t diff = outputlen - savedolen;
431 currentpos = TellBlob(ofile);
434 line=DestroyString(line);
437 offset=SeekBlob(ofile,savedpos,SEEK_SET);
440 line=DestroyString(line);
443 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
444 offset=SeekBlob(ofile,currentpos,SEEK_SET);
447 line=DestroyString(line);
454 (void) WriteBlobByte(ofile,0x00);
457 (void) WriteBlobString(ofile,"8BIM");
458 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
461 nlen = (unsigned char) strlen(name);
462 (void) WriteBlobByte(ofile,nlen);
464 for (i=0; i<nlen; i++)
465 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
467 if ((nlen & 0x01) == 0)
469 (void) WriteBlobByte(ofile,0x00);
472 if (recnum != IPTC_ID)
474 (void) WriteBlobMSBLong(ofile, (unsigned int) len);
480 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
484 (void) WriteBlobByte(ofile,0x00);
490 /* patch in a fake length for now and fix it later */
491 savedpos = TellBlob(ofile);
494 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
496 savedolen = outputlen;
503 (void) WriteBlobByte(ofile,0x1c);
504 (void) WriteBlobByte(ofile,(unsigned char) dataset);
505 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
506 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
511 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
517 if (token != (char *) NULL)
518 token=DestroyString(token);
519 if (newstr != (char *) NULL)
520 newstr=DestroyString(newstr);
521 if (name != (char *) NULL)
522 name=DestroyString(name);
524 token_info=DestroyTokenInfo(token_info);
525 if (token != (char *) NULL)
526 token=DestroyString(token);
527 if (newstr != (char *) NULL)
528 newstr=DestroyString(newstr);
529 if (name != (char *) NULL)
530 name=DestroyString(name);
531 line=DestroyString(line);
537 ssize_t diff = outputlen - savedolen;
539 currentpos = TellBlob(ofile);
542 offset=SeekBlob(ofile,savedpos,SEEK_SET);
545 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
546 offset=SeekBlob(ofile,currentpos,SEEK_SET);
554 static char *super_fgets_w(char **b, int *blen, Image *file)
565 p=(unsigned char *) (*b);
568 c=ReadBlobLSBSignedShort(file);
569 if ((c == -1) || (c == '\n'))
573 if ((q-p+1) >= (int) len)
580 p=(unsigned char *) ResizeQuantumMemory(p,(size_t) (len+2),sizeof(*p));
582 if (p == (unsigned char *) NULL)
586 *q=(unsigned char) c;
589 if ((*b) != (char *) NULL)
596 return (char *) NULL;
603 static ssize_t parse8BIMW(Image *ifile, Image *ofile)
624 inputlen = MagickPathExtent;
639 line=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
640 if (line == (char *) NULL)
642 newstr = name = token = (char *) NULL;
644 token_info=AcquireTokenInfo();
645 while (super_fgets_w(&line,&inputlen,ifile) != NULL)
650 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
651 if (token == (char *) NULL)
653 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
654 if (newstr == (char *) NULL)
656 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
657 &brkused,&next,"ed)==0)
671 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
672 "",0,&brkused,&next,"ed)==0)
677 if (strcmp(newstr,"8BIM")==0)
680 dataset = (unsigned char) StringToLong(newstr);
683 recnum=(unsigned int) StringToUnsignedLong(newstr);
686 name=(char *) AcquireQuantumMemory(strlen(newstr)+MagickPathExtent,
689 (void) CopyMagickString(name,newstr,strlen(newstr)+MagickPathExtent);
709 len = (ssize_t) strlen(token);
710 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
711 "",0,&brkused,&next,"ed)==0)
713 if (brkused && next > 0)
721 codes_length=convertHTMLcodes(s, strlen(s));
722 if ((ssize_t) codes_length > len)
742 ssize_t diff = outputlen - savedolen;
743 currentpos = TellBlob(ofile);
746 offset=SeekBlob(ofile,savedpos,SEEK_SET);
749 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
750 offset=SeekBlob(ofile,currentpos,SEEK_SET);
757 (void) WriteBlobByte(ofile,0x00);
760 (void) WriteBlobString(ofile,"8BIM");
761 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
764 nlen = (unsigned char) strlen(name);
765 (void) WriteBlobByte(ofile,(unsigned char) nlen);
767 for (i=0; i<nlen; i++)
768 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
770 if ((nlen & 0x01) == 0)
772 (void) WriteBlobByte(ofile,0x00);
775 if (recnum != IPTC_ID)
777 (void) WriteBlobMSBLong(ofile,(unsigned int) len);
783 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
787 (void) WriteBlobByte(ofile,0x00);
793 /* patch in a fake length for now and fix it later */
794 savedpos = TellBlob(ofile);
797 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
799 savedolen = outputlen;
806 (void) WriteBlobByte(ofile,0x1c);
807 (void) WriteBlobByte(ofile,dataset);
808 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
809 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
814 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
820 if (token != (char *) NULL)
821 token=DestroyString(token);
822 if (newstr != (char *) NULL)
823 newstr=DestroyString(newstr);
824 if (name != (char *) NULL)
825 name=DestroyString(name);
827 token_info=DestroyTokenInfo(token_info);
828 if (token != (char *) NULL)
829 token=DestroyString(token);
830 if (newstr != (char *) NULL)
831 newstr=DestroyString(newstr);
832 if (name != (char *) NULL)
833 name=DestroyString(name);
834 line=DestroyString(line);
840 ssize_t diff = outputlen - savedolen;
842 currentpos = TellBlob(ofile);
845 offset=SeekBlob(ofile,savedpos,SEEK_SET);
848 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
849 offset=SeekBlob(ofile,currentpos,SEEK_SET);
857 /* some defines for the different JPEG block types */
858 #define M_SOF0 0xC0 /* Start Of Frame N */
859 #define M_SOF1 0xC1 /* N indicates which compression process */
860 #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
862 #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
872 #define M_EOI 0xD9 /* End Of Image (end of datastream) */
873 #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
891 static int jpeg_transfer_1(Image *ifile, Image *ofile)
895 c = ReadBlobByte(ifile);
898 (void) WriteBlobByte(ofile,(unsigned char) c);
903 static int jpeg_skip_1(Image *ifile)
907 c = ReadBlobByte(ifile);
914 static int jpeg_read_remaining(Image *ifile, Image *ofile)
918 while ((c = jpeg_transfer_1(ifile, ofile)) != EOF)
923 static int jpeg_skip_variable(Image *ifile, Image *ofile)
928 if ((c1 = jpeg_transfer_1(ifile, ofile)) == EOF)
930 if ((c2 = jpeg_transfer_1(ifile, ofile)) == EOF)
933 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
937 if (jpeg_transfer_1(ifile, ofile) == EOF)
943 static int jpeg_skip_variable2(Image *ifile, Image *ofile)
949 if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
950 if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
952 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
956 if (ReadBlobByte(ifile) == EOF)
962 static int jpeg_nextmarker(Image *ifile, Image *ofile)
966 /* transfer anything until we hit 0xff */
969 c = ReadBlobByte(ifile);
971 return M_EOI; /* we hit EOF */
974 (void) WriteBlobByte(ofile,(unsigned char) c);
977 /* get marker byte, swallowing possible padding */
980 c = ReadBlobByte(ifile);
982 return M_EOI; /* we hit EOF */
989 static int jpeg_skip_till_marker(Image *ifile, int marker)
995 /* skip anything until we hit 0xff */
999 c = ReadBlobByte(ifile);
1002 return M_EOI; /* we hit EOF */
1003 } while (c != 0xff);
1005 /* get marker byte, swallowing possible padding */
1008 c = ReadBlobByte(ifile);
1010 return M_EOI; /* we hit EOF */
1011 } while (c == 0xff);
1012 } while (c != marker);
1017 /* Embed binary IPTC data into a JPEG image. */
1018 static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
1020 unsigned int marker;
1021 unsigned int done = 0;
1025 if (jpeg_transfer_1(ifile, ofile) != 0xFF)
1027 if (jpeg_transfer_1(ifile, ofile) != M_SOI)
1030 while (done == MagickFalse)
1032 marker=(unsigned int) jpeg_nextmarker(ifile, ofile);
1033 if (marker == M_EOI)
1039 if (marker != M_APP13)
1041 (void) WriteBlobByte(ofile,0xff);
1042 (void) WriteBlobByte(ofile,(unsigned char) marker);
1049 /* we are going to write a new APP13 marker, so don't output the old one */
1050 jpeg_skip_variable2(ifile, ofile);
1054 /* APP0 is in each and every JPEG, so when we hit APP0 we insert our new APP13! */
1055 jpeg_skip_variable(ifile, ofile);
1057 if (iptc != (Image *) NULL)
1060 psheader[] = "\xFF\xED\0\0Photoshop 3.0\0" "8BIM\x04\x04\0\0\0\0";
1062 len=(unsigned int) GetBlobSize(iptc);
1064 len++; /* make the length even */
1065 psheader[2]=(char) ((len+16)>>8);
1066 psheader[3]=(char) ((len+16)&0xff);
1067 for (inx = 0; inx < 18; inx++)
1068 (void) WriteBlobByte(ofile,(unsigned char) psheader[inx]);
1069 jpeg_read_remaining(iptc, ofile);
1070 len=(unsigned int) GetBlobSize(iptc);
1072 (void) WriteBlobByte(ofile,0);
1077 /* we hit data, no more marker-inserting can be done! */
1078 jpeg_read_remaining(ifile, ofile);
1083 jpeg_skip_variable(ifile, ofile);
1090 /* handle stripping the APP13 data out of a JPEG */
1092 static void jpeg_strip(Image *ifile, Image *ofile)
1094 unsigned int marker;
1096 marker = jpeg_skip_till_marker(ifile, M_SOI);
1097 if (marker == M_SOI)
1099 (void) WriteBlobByte(ofile,0xff);
1100 (void) WriteBlobByte(ofile,M_SOI);
1101 jpeg_read_remaining(ifile, ofile);
1105 /* Extract any APP13 binary data into a file. */
1106 static int jpeg_extract(Image *ifile, Image *ofile)
1108 unsigned int marker;
1109 unsigned int done = 0;
1111 if (jpeg_skip_1(ifile) != 0xff)
1113 if (jpeg_skip_1(ifile) != M_SOI)
1116 while (done == MagickFalse)
1118 marker = jpeg_skip_till_marker(ifile, M_APP13);
1119 if (marker == M_APP13)
1121 marker = jpeg_nextmarker(ifile, ofile);
1129 static inline void CopyBlob(Image *source,Image *destination)
1141 buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1143 if (buffer != (unsigned char *) NULL)
1146 while ((length=ReadBlob(source,MagickMaxBufferExtent,buffer)) != 0)
1149 for (i=0; i < (ssize_t) length; i+=count)
1151 count=WriteBlob(destination,(size_t) (length-i),buffer+i);
1155 if (i < (ssize_t) length)
1158 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1162 static Image *ReadMETAImage(const ImageInfo *image_info,
1163 ExceptionInfo *exception)
1182 Open file containing binary metadata
1184 assert(image_info != (const ImageInfo *) NULL);
1185 assert(image_info->signature == MagickCoreSignature);
1186 if (image_info->debug != MagickFalse)
1187 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1188 image_info->filename);
1189 assert(exception != (ExceptionInfo *) NULL);
1190 assert(exception->signature == MagickCoreSignature);
1191 image=AcquireImage(image_info,exception);
1192 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1193 if (status == MagickFalse)
1195 image=DestroyImageList(image);
1196 return((Image *) NULL);
1200 if (SetImageBackgroundColor(image,exception) == MagickFalse)
1202 image=DestroyImageList(image);
1203 return((Image *) NULL);
1206 if (LocaleNCompare(image_info->magick,"8BIM",4) == 0)
1209 Read 8BIM binary metadata.
1211 buff=AcquireImage((ImageInfo *) NULL,exception);
1212 if (buff == (Image *) NULL)
1213 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1214 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1215 if (blob == (unsigned char *) NULL)
1217 buff=DestroyImage(buff);
1218 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1220 (void) memset(blob,0,length);
1221 AttachBlob(buff->blob,blob,length);
1222 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
1224 length=(size_t) parse8BIM(image, buff);
1227 blob=DetachBlob(buff->blob);
1228 blob=(unsigned char *) RelinquishMagickMemory(blob);
1229 buff=DestroyImage(buff);
1230 ThrowReaderException(CorruptImageError,"CorruptImage");
1233 (void) WriteBlobByte(buff,0x0);
1235 else if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
1237 length=(size_t) parse8BIMW(image, buff);
1240 blob=DetachBlob(buff->blob);
1241 blob=(unsigned char *) RelinquishMagickMemory(blob);
1242 buff=DestroyImage(buff);
1243 ThrowReaderException(CorruptImageError,"CorruptImage");
1246 (void) WriteBlobByte(buff,0x0);
1249 CopyBlob(image,buff);
1250 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1252 if (profile == (StringInfo *) NULL)
1254 blob=DetachBlob(buff->blob);
1255 blob=(unsigned char *) RelinquishMagickMemory(blob);
1256 buff=DestroyImage(buff);
1257 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1259 status=SetImageProfile(image,"8bim",profile,exception);
1260 profile=DestroyStringInfo(profile);
1261 blob=DetachBlob(buff->blob);
1262 blob=(unsigned char *) RelinquishMagickMemory(blob);
1263 buff=DestroyImage(buff);
1264 if (status == MagickFalse)
1265 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1267 if (LocaleNCompare(image_info->magick,"APP1",4) == 0)
1270 name[MagickPathExtent];
1272 (void) FormatLocaleString(name,MagickPathExtent,"APP%d",1);
1273 buff=AcquireImage((ImageInfo *) NULL,exception);
1274 if (buff == (Image *) NULL)
1275 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1276 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1277 if (blob == (unsigned char *) NULL)
1279 buff=DestroyImage(buff);
1280 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1282 AttachBlob(buff->blob,blob,length);
1283 if (LocaleCompare(image_info->magick,"APP1JPEG") == 0)
1291 if (image_info->profile == (void *) NULL)
1293 blob=DetachBlob(buff->blob);
1294 blob=(unsigned char *) RelinquishMagickMemory(blob);
1295 buff=DestroyImage(buff);
1296 ThrowReaderException(CoderError,"NoIPTCProfileAvailable");
1298 profile=CloneStringInfo((StringInfo *) image_info->profile);
1299 iptc=AcquireImage((ImageInfo *) NULL,exception);
1300 if (iptc == (Image *) NULL)
1302 blob=DetachBlob(buff->blob);
1303 blob=(unsigned char *) RelinquishMagickMemory(blob);
1304 buff=DestroyImage(buff);
1305 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1307 AttachBlob(iptc->blob,GetStringInfoDatum(profile),
1308 GetStringInfoLength(profile));
1309 result=jpeg_embed(image,buff,iptc);
1310 blob=DetachBlob(iptc->blob);
1311 blob=(unsigned char *) RelinquishMagickMemory(blob);
1312 iptc=DestroyImage(iptc);
1315 buff=DestroyImage(buff);
1316 ThrowReaderException(CoderError,"JPEGEmbeddingFailed");
1320 CopyBlob(image,buff);
1321 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1323 if (profile == (StringInfo *) NULL)
1325 blob=DetachBlob(buff->blob);
1326 blob=(unsigned char *) RelinquishMagickMemory(blob);
1327 buff=DestroyImage(buff);
1328 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1330 status=SetImageProfile(image,name,profile,exception);
1331 profile=DestroyStringInfo(profile);
1332 blob=DetachBlob(buff->blob);
1333 blob=(unsigned char *) RelinquishMagickMemory(blob);
1334 buff=DestroyImage(buff);
1335 if (status == MagickFalse)
1336 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1338 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
1339 (LocaleCompare(image_info->magick,"ICM") == 0))
1341 buff=AcquireImage((ImageInfo *) NULL,exception);
1342 if (buff == (Image *) NULL)
1343 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1344 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1345 if (blob == (unsigned char *) NULL)
1347 buff=DestroyImage(buff);
1348 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1350 AttachBlob(buff->blob,blob,length);
1351 CopyBlob(image,buff);
1352 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1354 if (profile == (StringInfo *) NULL)
1356 blob=DetachBlob(buff->blob);
1357 blob=(unsigned char *) RelinquishMagickMemory(blob);
1358 buff=DestroyImage(buff);
1359 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1361 (void) SetImageProfile(image,"icc",profile,exception);
1362 profile=DestroyStringInfo(profile);
1363 blob=DetachBlob(buff->blob);
1364 blob=(unsigned char *) RelinquishMagickMemory(blob);
1365 buff=DestroyImage(buff);
1367 if (LocaleCompare(image_info->magick,"IPTC") == 0)
1369 buff=AcquireImage((ImageInfo *) NULL,exception);
1370 if (buff == (Image *) NULL)
1371 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1372 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1373 if (blob == (unsigned char *) NULL)
1375 buff=DestroyImage(buff);
1376 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1378 AttachBlob(buff->blob,blob,length);
1379 CopyBlob(image,buff);
1380 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1382 if (profile == (StringInfo *) NULL)
1384 blob=DetachBlob(buff->blob);
1385 blob=(unsigned char *) RelinquishMagickMemory(blob);
1386 buff=DestroyImage(buff);
1387 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1389 (void) SetImageProfile(image,"8bim",profile,exception);
1390 profile=DestroyStringInfo(profile);
1391 blob=DetachBlob(buff->blob);
1392 blob=(unsigned char *) RelinquishMagickMemory(blob);
1393 buff=DestroyImage(buff);
1395 if (LocaleCompare(image_info->magick,"XMP") == 0)
1397 buff=AcquireImage((ImageInfo *) NULL,exception);
1398 if (buff == (Image *) NULL)
1399 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1400 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1401 if (blob == (unsigned char *) NULL)
1403 buff=DestroyImage(buff);
1404 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1406 AttachBlob(buff->blob,blob,length);
1407 CopyBlob(image,buff);
1408 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1410 if (profile == (StringInfo *) NULL)
1412 blob=DetachBlob(buff->blob);
1413 blob=(unsigned char *) RelinquishMagickMemory(blob);
1414 buff=DestroyImage(buff);
1415 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1417 (void) SetImageProfile(image,"xmp",profile,exception);
1418 profile=DestroyStringInfo(profile);
1419 blob=DetachBlob(buff->blob);
1420 blob=(unsigned char *) RelinquishMagickMemory(blob);
1421 buff=DestroyImage(buff);
1423 (void) CloseBlob(image);
1424 return(GetFirstImageInList(image));
1428 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1432 % R e g i s t e r M E T A I m a g e %
1436 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1438 % RegisterMETAImage() adds attributes for the META image format to
1439 % the list of supported formats. The attributes include the image format
1440 % tag, a method to read and/or write the format, whether the format
1441 % supports the saving of more than one frame to the same file or blob,
1442 % whether the format supports native in-memory I/O, and a brief
1443 % description of the format.
1445 % The format of the RegisterMETAImage method is:
1447 % size_t RegisterMETAImage(void)
1450 ModuleExport size_t RegisterMETAImage(void)
1455 entry=AcquireMagickInfo("META","8BIM","Photoshop resource format");
1456 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1457 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1458 entry->flags^=CoderAdjoinFlag;
1459 entry->flags|=CoderStealthFlag;
1460 entry->flags|=CoderDecoderSeekableStreamFlag;
1461 (void) RegisterMagickInfo(entry);
1462 entry=AcquireMagickInfo("META","8BIMTEXT","Photoshop resource text format");
1463 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1464 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1465 entry->flags^=CoderAdjoinFlag;
1466 entry->flags|=CoderStealthFlag;
1467 entry->flags|=CoderDecoderSeekableStreamFlag;
1468 (void) RegisterMagickInfo(entry);
1469 entry=AcquireMagickInfo("META","8BIMWTEXT",
1470 "Photoshop resource wide text format");
1471 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1472 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1473 entry->flags^=CoderAdjoinFlag;
1474 entry->flags|=CoderStealthFlag;
1475 entry->flags|=CoderDecoderSeekableStreamFlag;
1476 (void) RegisterMagickInfo(entry);
1477 entry=AcquireMagickInfo("META","APP1","Raw application information");
1478 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1479 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1480 entry->flags^=CoderAdjoinFlag;
1481 entry->flags|=CoderStealthFlag;
1482 entry->flags|=CoderDecoderSeekableStreamFlag;
1483 (void) RegisterMagickInfo(entry);
1484 entry=AcquireMagickInfo("META","APP1JPEG","Raw JPEG binary data");
1485 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1486 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1487 entry->flags^=CoderAdjoinFlag;
1488 entry->flags|=CoderStealthFlag;
1489 entry->flags|=CoderDecoderSeekableStreamFlag;
1490 (void) RegisterMagickInfo(entry);
1491 entry=AcquireMagickInfo("META","EXIF","Exif digital camera binary data");
1492 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1493 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1494 entry->flags^=CoderAdjoinFlag;
1495 entry->flags|=CoderStealthFlag;
1496 entry->flags|=CoderDecoderSeekableStreamFlag;
1497 (void) RegisterMagickInfo(entry);
1498 entry=AcquireMagickInfo("META","XMP","Adobe XML metadata");
1499 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1500 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1501 entry->flags^=CoderAdjoinFlag;
1502 entry->flags|=CoderStealthFlag;
1503 entry->flags|=CoderDecoderSeekableStreamFlag;
1504 (void) RegisterMagickInfo(entry);
1505 entry=AcquireMagickInfo("META","ICM","ICC Color Profile");
1506 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1507 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1508 entry->flags^=CoderAdjoinFlag;
1509 entry->flags|=CoderStealthFlag;
1510 entry->flags|=CoderDecoderSeekableStreamFlag;
1511 (void) RegisterMagickInfo(entry);
1512 entry=AcquireMagickInfo("META","ICC","ICC Color Profile");
1513 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1514 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1515 entry->flags^=CoderAdjoinFlag;
1516 entry->flags|=CoderStealthFlag;
1517 entry->flags|=CoderDecoderSeekableStreamFlag;
1518 (void) RegisterMagickInfo(entry);
1519 entry=AcquireMagickInfo("META","IPTC","IPTC Newsphoto");
1520 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1521 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1522 entry->flags^=CoderAdjoinFlag;
1523 entry->flags|=CoderStealthFlag;
1524 entry->flags|=CoderDecoderSeekableStreamFlag;
1525 (void) RegisterMagickInfo(entry);
1526 entry=AcquireMagickInfo("META","IPTCTEXT","IPTC Newsphoto text format");
1527 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1528 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1529 entry->flags^=CoderAdjoinFlag;
1530 entry->flags|=CoderStealthFlag;
1531 entry->flags|=CoderDecoderSeekableStreamFlag;
1532 (void) RegisterMagickInfo(entry);
1533 entry=AcquireMagickInfo("META","IPTCWTEXT","IPTC Newsphoto text format");
1534 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1535 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1536 entry->flags^=CoderAdjoinFlag;
1537 entry->flags|=CoderStealthFlag;
1538 entry->flags|=CoderDecoderSeekableStreamFlag;
1539 (void) RegisterMagickInfo(entry);
1540 return(MagickImageCoderSignature);
1544 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548 % U n r e g i s t e r M E T A I m a g e %
1552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1554 % UnregisterMETAImage() removes format registrations made by the
1555 % META module from the list of supported formats.
1557 % The format of the UnregisterMETAImage method is:
1559 % UnregisterMETAImage(void)
1562 ModuleExport void UnregisterMETAImage(void)
1564 (void) UnregisterMagickInfo("8BIM");
1565 (void) UnregisterMagickInfo("8BIMTEXT");
1566 (void) UnregisterMagickInfo("8BIMWTEXT");
1567 (void) UnregisterMagickInfo("EXIF");
1568 (void) UnregisterMagickInfo("APP1");
1569 (void) UnregisterMagickInfo("APP1JPEG");
1570 (void) UnregisterMagickInfo("ICCTEXT");
1571 (void) UnregisterMagickInfo("ICM");
1572 (void) UnregisterMagickInfo("ICC");
1573 (void) UnregisterMagickInfo("IPTC");
1574 (void) UnregisterMagickInfo("IPTCTEXT");
1575 (void) UnregisterMagickInfo("IPTCWTEXT");
1576 (void) UnregisterMagickInfo("XMP");
1580 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584 % W r i t e M E T A I m a g e %
1588 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1590 % WriteMETAImage() writes a META image to a file.
1592 % The format of the WriteMETAImage method is:
1594 % MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
1595 % Image *image,ExceptionInfo *exception)
1597 % Compression code contributed by Kyle Shorter.
1599 % A description of each parameter follows:
1601 % o image_info: Specifies a pointer to an ImageInfo structure.
1603 % o image: A pointer to a Image structure.
1605 % o exception: return any errors or warnings in this structure.
1609 static size_t GetIPTCStream(unsigned char **info,size_t length)
1617 register unsigned char
1632 if ((*p == 0x1c) && (*(p+1) == 0x02))
1635 Extract IPTC from 8BIM resource block.
1637 while (extent >= 12)
1639 if (strncmp((const char *) p,"8BIM",4))
1643 marker=(unsigned int) (*p) << 8 | *(p+1);
1649 if ((size_t) c >= extent)
1655 tag_length=(((size_t) *p) << 24) | (((size_t) *(p+1)) << 16) |
1656 (((size_t) *(p+2)) << 8) | ((size_t) *(p+3));
1659 if (tag_length > extent)
1661 if (marker == IPTC_ID)
1666 if ((tag_length & 0x01) != 0)
1672 Find the beginning of the IPTC info.
1688 *info=p; /* let the caller know were it is */
1693 Determine the length of the IPTC info.
1710 Found the 0x1c tag; skip the dataset and record number tags.
1712 c=(*p++); /* should be 2 */
1716 if ((info_length == 1) && (c != 2))
1719 c=(*p++); /* should be 0 */
1723 if ((info_length == 2) && (c != 0))
1727 Decode the length of the block that follows - ssize_t or short format.
1734 if ((c & 0x80) != 0)
1740 for (i=0; i < 4; i++)
1755 tag_length=((long) c) << 8;
1761 tag_length|=(long) c;
1763 if (tag_length > (length+1))
1769 info_length+=tag_length;
1771 return(info_length);
1774 static void formatString(Image *ofile, const char *s, int len)
1777 temp[MagickPathExtent];
1779 (void) WriteBlobByte(ofile,'"');
1780 for (; len > 0; len--, s++) {
1784 (void) WriteBlobString(ofile,"&");
1788 (void) WriteBlobString(ofile,"<");
1791 (void) WriteBlobString(ofile,">");
1795 (void) WriteBlobString(ofile,""");
1799 (void) WriteBlobByte(ofile,(unsigned char) *s);
1802 (void) FormatLocaleString(temp,MagickPathExtent,"&#%d;", c & 255);
1803 (void) WriteBlobString(ofile,temp);
1808 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1809 (void) WriteBlobString(ofile,"\"\r\n");
1811 #if defined(macintosh)
1812 (void) WriteBlobString(ofile,"\"\r");
1814 (void) WriteBlobString(ofile,"\"\n");
1819 typedef struct _tag_spec
1828 static const tag_spec tags[] = {
1829 { 5, "Image Name" },
1830 { 7, "Edit Status" },
1833 { 20, "Supplemental Category" },
1834 { 22, "Fixture Identifier" },
1836 { 30, "Release Date" },
1837 { 35, "Release Time" },
1838 { 40, "Special Instructions" },
1839 { 45, "Reference Service" },
1840 { 47, "Reference Date" },
1841 { 50, "Reference Number" },
1842 { 55, "Created Date" },
1843 { 60, "Created Time" },
1844 { 65, "Originating Program" },
1845 { 70, "Program Version" },
1846 { 75, "Object Cycle" },
1848 { 85, "Byline Title" },
1850 { 92, "Sub-Location" },
1851 { 95, "Province State" },
1852 { 100, "Country Code" },
1854 { 103, "Original Transmission Reference" },
1855 { 105, "Headline" },
1858 { 116, "Copyright String" },
1860 { 121, "Image Orientation" },
1861 { 122, "Caption Writer" },
1862 { 131, "Local Caption" },
1863 { 200, "Custom Field 1" },
1864 { 201, "Custom Field 2" },
1865 { 202, "Custom Field 3" },
1866 { 203, "Custom Field 4" },
1867 { 204, "Custom Field 5" },
1868 { 205, "Custom Field 6" },
1869 { 206, "Custom Field 7" },
1870 { 207, "Custom Field 8" },
1871 { 208, "Custom Field 9" },
1872 { 209, "Custom Field 10" },
1873 { 210, "Custom Field 11" },
1874 { 211, "Custom Field 12" },
1875 { 212, "Custom Field 13" },
1876 { 213, "Custom Field 14" },
1877 { 214, "Custom Field 15" },
1878 { 215, "Custom Field 16" },
1879 { 216, "Custom Field 17" },
1880 { 217, "Custom Field 18" },
1881 { 218, "Custom Field 19" },
1882 { 219, "Custom Field 20" }
1885 static int formatIPTC(Image *ifile, Image *ofile)
1888 temp[MagickPathExtent];
1908 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
1913 foundiptc = 0; /* found the IPTC-Header */
1914 tagsfound = 0; /* number of tags found */
1916 c = ReadBlobByte(ifile);
1932 /* we found the 0x1c tag and now grab the dataset and record number tags */
1933 c = ReadBlobByte(ifile);
1936 dataset = (unsigned char) c;
1937 c = ReadBlobByte(ifile);
1940 recnum = (unsigned char) c;
1941 /* try to match this record to one of the ones in our named table */
1942 for (i=0; i< tagcount; i++)
1944 if (tags[i].id == (short) recnum)
1948 readable = (unsigned char *) tags[i].name;
1950 readable = (unsigned char *) "";
1952 We decode the length of the block that follows - ssize_t or short fmt.
1954 c=ReadBlobByte(ifile);
1957 if (c & (unsigned char) 0x80)
1964 c0=ReadBlobByte(ifile);
1967 taglen = (c << 8) | c0;
1971 /* make a buffer to hold the tag datand snag it from the input stream */
1972 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+
1973 MagickPathExtent),sizeof(*str));
1974 if (str == (unsigned char *) NULL)
1976 for (tagindx=0; tagindx<taglen; tagindx++)
1978 c=ReadBlobByte(ifile);
1981 str=(unsigned char *) RelinquishMagickMemory(str);
1984 str[tagindx] = (unsigned char) c;
1988 /* now finish up by formatting this binary data into ASCII equivalent */
1989 if (strlen((char *)readable) > 0)
1990 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
1991 (unsigned int) dataset, (unsigned int) recnum, readable);
1993 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
1994 (unsigned int) dataset,(unsigned int) recnum);
1995 (void) WriteBlobString(ofile,temp);
1996 formatString( ofile, (char *)str, taglen );
1997 str=(unsigned char *) RelinquishMagickMemory(str);
2001 c=ReadBlobByte(ifile);
2003 return((int) tagsfound);
2006 static int readWordFromBuffer(char **s, ssize_t *len)
2017 c = *(*s)++; (*len)--;
2018 if (*len < 0) return -1;
2019 buffer[i] = (unsigned char) c;
2021 return (((int) buffer[ 0 ]) << 8) |
2022 (((int) buffer[ 1 ]));
2025 static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
2028 temp[MagickPathExtent];
2048 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
2053 foundiptc = 0; /* found the IPTC-Header */
2054 tagsfound = 0; /* number of tags found */
2069 We found the 0x1c tag and now grab the dataset and record number tags.
2072 if (len < 0) return -1;
2073 dataset = (unsigned char) c;
2075 if (len < 0) return -1;
2076 recnum = (unsigned char) c;
2077 /* try to match this record to one of the ones in our named table */
2078 for (i=0; i< tagcount; i++)
2079 if (tags[i].id == (short) recnum)
2082 readable=(unsigned char *) tags[i].name;
2084 readable=(unsigned char *) "";
2086 We decode the length of the block that follows - ssize_t or short fmt.
2092 if (c & (unsigned char) 0x80)
2098 taglen=readWordFromBuffer(&s, &len);
2104 /* make a buffer to hold the tag datand snag it from the input stream */
2105 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+
2106 MagickPathExtent),sizeof(*str));
2107 if (str == (unsigned char *) NULL)
2109 (void) printf("MemoryAllocationFailed");
2112 for (tagindx=0; tagindx<taglen; tagindx++)
2117 str=(unsigned char *) RelinquishMagickMemory(str);
2120 str[tagindx]=(unsigned char) c;
2124 /* now finish up by formatting this binary data into ASCII equivalent */
2125 if (strlen((char *)readable) > 0)
2126 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d#%s=",
2127 (unsigned int) dataset,(unsigned int) recnum, readable);
2129 (void) FormatLocaleString(temp,MagickPathExtent,"%d#%d=",
2130 (unsigned int) dataset,(unsigned int) recnum);
2131 (void) WriteBlobString(ofile,temp);
2132 formatString( ofile, (char *)str, taglen );
2133 str=(unsigned char *) RelinquishMagickMemory(str);
2137 return ((int) tagsfound);
2140 static int format8BIM(Image *ifile, Image *ofile)
2143 temp[MagickPathExtent];
2162 foundOSType=0; /* found the OSType */
2164 c=ReadBlobByte(ifile);
2172 buffer[0]=(unsigned char) c;
2175 c=ReadBlobByte(ifile);
2178 buffer[i] = (unsigned char) c;
2181 if (strcmp((const char *)buffer, "8BIM") == 0)
2188 c=ReadBlobByte(ifile);
2192 We found the OSType (8BIM) and now grab the ID, PString, and Size fields.
2194 ID=ReadBlobMSBSignedShort(ifile);
2201 c=ReadBlobByte(ifile);
2204 plen = (unsigned char) c;
2205 PString=(unsigned char *) AcquireQuantumMemory((size_t) (plen+
2206 MagickPathExtent),sizeof(*PString));
2207 if (PString == (unsigned char *) NULL)
2209 for (i=0; i<plen; i++)
2211 c=ReadBlobByte(ifile);
2214 PString=(unsigned char *) RelinquishMagickMemory(PString);
2217 PString[i] = (unsigned char) c;
2219 PString[ plen ] = 0;
2220 if ((plen & 0x01) == 0)
2222 c=ReadBlobByte(ifile);
2225 PString=(unsigned char *) RelinquishMagickMemory(PString);
2230 count=(ssize_t) ReadBlobMSBSignedLong(ifile);
2231 if ((count < 0) || (count > GetBlobSize(ifile)))
2233 PString=(unsigned char *) RelinquishMagickMemory(PString);
2236 /* make a buffer to hold the data and snag it from the input stream */
2237 str=(unsigned char *) AcquireQuantumMemory((size_t) count+1,sizeof(*str));
2238 if (str == (unsigned char *) NULL)
2240 PString=(unsigned char *) RelinquishMagickMemory(PString);
2243 for (i=0; i < (ssize_t) count; i++)
2245 c=ReadBlobByte(ifile);
2248 str=(unsigned char *) RelinquishMagickMemory(str);
2249 PString=(unsigned char *) RelinquishMagickMemory(PString);
2252 str[i]=(unsigned char) c;
2255 /* we currently skip thumbnails, since it does not make
2256 * any sense preserving them in a real world application
2258 if (ID != THUMBNAIL_ID)
2260 /* now finish up by formatting this binary data into
2263 if (strlen((const char *)PString) > 0)
2264 (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d#%s=",ID,
2267 (void) FormatLocaleString(temp,MagickPathExtent,"8BIM#%d=",ID);
2268 (void) WriteBlobString(ofile,temp);
2271 formatString(ofile, "IPTC", 4);
2272 formatIPTCfromBuffer(ofile, (char *)str, (ssize_t) count);
2275 formatString(ofile, (char *)str, (ssize_t) count);
2277 str=(unsigned char *) RelinquishMagickMemory(str);
2278 PString=(unsigned char *) RelinquishMagickMemory(PString);
2280 c=ReadBlobByte(ifile);
2285 static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
2286 Image *image,ExceptionInfo *exception)
2300 assert(image_info != (const ImageInfo *) NULL);
2301 assert(image_info->signature == MagickCoreSignature);
2302 assert(image != (Image *) NULL);
2303 assert(image->signature == MagickCoreSignature);
2304 if (image->debug != MagickFalse)
2305 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2307 if (LocaleCompare(image_info->magick,"8BIM") == 0)
2312 profile=GetImageProfile(image,"8bim");
2313 if (profile == (StringInfo *) NULL)
2314 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2315 assert(exception != (ExceptionInfo *) NULL);
2316 assert(exception->signature == MagickCoreSignature);
2317 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2318 if (status == MagickFalse)
2320 (void) WriteBlob(image,GetStringInfoLength(profile),
2321 GetStringInfoDatum(profile));
2322 (void) CloseBlob(image);
2325 if (LocaleCompare(image_info->magick,"iptc") == 0)
2333 profile=GetImageProfile(image,"iptc");
2334 if (profile == (StringInfo *) NULL)
2335 profile=GetImageProfile(image,"8bim");
2336 if (profile == (StringInfo *) NULL)
2337 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2338 assert(exception != (ExceptionInfo *) NULL);
2339 assert(exception->signature == MagickCoreSignature);
2340 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2341 info=GetStringInfoDatum(profile);
2342 length=GetStringInfoLength(profile);
2343 length=GetIPTCStream(&info,length);
2345 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2346 (void) WriteBlob(image,length,info);
2347 (void) CloseBlob(image);
2350 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
2355 profile=GetImageProfile(image,"8bim");
2356 if (profile == (StringInfo *) NULL)
2357 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2358 assert(exception != (ExceptionInfo *) NULL);
2359 assert(exception->signature == MagickCoreSignature);
2360 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2361 if (status == MagickFalse)
2363 buff=AcquireImage((ImageInfo *) NULL,exception);
2364 if (buff == (Image *) NULL)
2365 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2366 AttachBlob(buff->blob,GetStringInfoDatum(profile),
2367 GetStringInfoLength(profile));
2368 format8BIM(buff,image);
2369 (void) DetachBlob(buff->blob);
2370 buff=DestroyImage(buff);
2371 (void) CloseBlob(image);
2374 if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
2375 return(MagickFalse);
2376 if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0)
2384 profile=GetImageProfile(image,"8bim");
2385 if (profile == (StringInfo *) NULL)
2386 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2387 info=GetStringInfoDatum(profile);
2388 length=GetStringInfoLength(profile);
2389 length=GetIPTCStream(&info,length);
2391 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2392 assert(exception != (ExceptionInfo *) NULL);
2393 assert(exception->signature == MagickCoreSignature);
2394 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2395 if (status == MagickFalse)
2397 buff=AcquireImage((ImageInfo *) NULL,exception);
2398 if (buff == (Image *) NULL)
2399 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2400 AttachBlob(buff->blob,info,length);
2401 formatIPTC(buff,image);
2402 (void) DetachBlob(buff->blob);
2403 buff=DestroyImage(buff);
2404 (void) CloseBlob(image);
2407 if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0)
2408 return(MagickFalse);
2409 if ((LocaleCompare(image_info->magick,"APP1") == 0) ||
2410 (LocaleCompare(image_info->magick,"EXIF") == 0) ||
2411 (LocaleCompare(image_info->magick,"XMP") == 0))
2414 (void) Write APP1 image.
2416 profile=GetImageProfile(image,image_info->magick);
2417 if (profile == (StringInfo *) NULL)
2418 ThrowWriterException(CoderError,"NoAPP1DataIsAvailable");
2419 assert(exception != (ExceptionInfo *) NULL);
2420 assert(exception->signature == MagickCoreSignature);
2421 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2422 if (status == MagickFalse)
2424 (void) WriteBlob(image,GetStringInfoLength(profile),
2425 GetStringInfoDatum(profile));
2426 (void) CloseBlob(image);
2429 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
2430 (LocaleCompare(image_info->magick,"ICM") == 0))
2435 profile=GetImageProfile(image,"icc");
2436 if (profile == (StringInfo *) NULL)
2437 ThrowWriterException(CoderError,"NoColorProfileIsAvailable");
2438 assert(exception != (ExceptionInfo *) NULL);
2439 assert(exception->signature == MagickCoreSignature);
2440 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2441 if (status == MagickFalse)
2443 (void) WriteBlob(image,GetStringInfoLength(profile),
2444 GetStringInfoDatum(profile));
2445 (void) CloseBlob(image);
2448 return(MagickFalse);