2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % M M EEEEE TTTTT AAA %
13 % Read/Write Embedded Image Profiles. %
20 % Copyright 1999-2013 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.
143 #define BUFFER_SZ 4096
145 typedef struct _html_code
154 static 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) strcpy(s+1,s+1+o);
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) strcpy(s+1,s+html_codes[i].len);
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;
288 #define BUFFER_SZ 4096
290 #define THUMBNAIL_ID 1033
292 static ssize_t parse8BIM(Image *ifile, Image *ofile)
313 inputlen = BUFFER_SZ;
328 line = (char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
329 name = token = (char *)NULL;
331 token_info=AcquireTokenInfo();
332 while (super_fgets(&line,&inputlen,ifile)!=NULL)
337 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
338 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
339 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
340 &brkused,&next,"ed)==0)
354 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
355 "", 0,&brkused,&next,"ed)==0)
360 if (strcmp(newstr,"8BIM")==0)
363 dataset = (unsigned char) StringToLong(newstr);
366 recnum = (unsigned int) StringToUnsignedLong(newstr);
369 name=(char *) AcquireQuantumMemory(strlen(newstr)+MaxTextExtent,
372 (void) strcpy(name,newstr);
392 len = (ssize_t) strlen(token);
393 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
394 "",0,&brkused,&next,"ed)==0)
396 if (brkused && next > 0)
401 len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
418 ssize_t diff = outputlen - savedolen;
419 currentpos = TellBlob(ofile);
420 offset=SeekBlob(ofile,savedpos,SEEK_SET);
423 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
424 offset=SeekBlob(ofile,currentpos,SEEK_SET);
431 (void) WriteBlobByte(ofile,0x00);
434 (void) WriteBlobString(ofile,"8BIM");
435 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
438 nlen = (unsigned char) strlen(name);
439 (void) WriteBlobByte(ofile,nlen);
441 for (i=0; i<nlen; i++)
442 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
444 if ((nlen & 0x01) == 0)
446 (void) WriteBlobByte(ofile,0x00);
449 if (recnum != IPTC_ID)
451 (void) WriteBlobMSBLong(ofile, (unsigned int) len);
457 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
461 (void) WriteBlobByte(ofile,0x00);
467 /* patch in a fake length for now and fix it later */
468 savedpos = TellBlob(ofile);
469 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
471 savedolen = outputlen;
478 (void) WriteBlobByte(ofile,0x1c);
479 (void) WriteBlobByte(ofile,(unsigned char) dataset);
480 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
481 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
486 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
492 token=DestroyString(token);
493 newstr=DestroyString(newstr);
494 if (name != (char *) NULL)
495 name=DestroyString(name);
497 token_info=DestroyTokenInfo(token_info);
498 line=DestroyString(line);
504 ssize_t diff = outputlen - savedolen;
506 currentpos = TellBlob(ofile);
507 offset=SeekBlob(ofile,savedpos,SEEK_SET);
510 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
511 offset=SeekBlob(ofile,currentpos,SEEK_SET);
519 static char *super_fgets_w(char **b, int *blen, Image *file)
530 p=(unsigned char *) (*b);
533 c=(int) ReadBlobLSBShort(file);
534 if ((c == -1) || (c == '\n'))
538 if ((q-p+1) >= (int) len)
545 p=(unsigned char *) ResizeQuantumMemory(p,(size_t) (len+2),sizeof(*p));
547 if (p == (unsigned char *) NULL)
551 *q=(unsigned char) c;
554 if ((*b) != (char *) NULL)
561 return (char *) NULL;
568 static ssize_t parse8BIMW(Image *ifile, Image *ofile)
589 inputlen = BUFFER_SZ;
604 line=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*line));
605 name = token = (char *)NULL;
607 token_info=AcquireTokenInfo();
608 while (super_fgets_w(&line,&inputlen,ifile) != NULL)
613 token=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*token));
614 newstr=(char *) AcquireQuantumMemory((size_t) inputlen,sizeof(*newstr));
615 while (Tokenizer(token_info,0,token,(size_t) inputlen,line,"","=","\"",0,
616 &brkused,&next,"ed)==0)
630 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","#",
631 "",0,&brkused,&next,"ed)==0)
636 if (strcmp(newstr,"8BIM")==0)
639 dataset = (unsigned char) StringToLong(newstr);
642 recnum=(unsigned int) StringToUnsignedLong(newstr);
645 name=(char *) AcquireQuantumMemory(strlen(newstr)+MaxTextExtent,
648 (void) CopyMagickString(name,newstr,strlen(newstr)+MaxTextExtent);
668 len = (ssize_t) strlen(token);
669 while (Tokenizer(token_info,0,newstr,(size_t) inputlen,token,"","&",
670 "",0,&brkused,&next,"ed)==0)
672 if (brkused && next > 0)
677 len -= (ssize_t) convertHTMLcodes(s,(int) strlen(s));
694 ssize_t diff = outputlen - savedolen;
695 currentpos = TellBlob(ofile);
696 offset=SeekBlob(ofile,savedpos,SEEK_SET);
699 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
700 offset=SeekBlob(ofile,currentpos,SEEK_SET);
707 (void) WriteBlobByte(ofile,0x00);
710 (void) WriteBlobString(ofile,"8BIM");
711 (void) WriteBlobMSBShort(ofile,(unsigned short) recnum);
714 nlen = (unsigned char) strlen(name);
715 (void) WriteBlobByte(ofile,(unsigned char) nlen);
717 for (i=0; i<nlen; i++)
718 (void) WriteBlobByte(ofile,(unsigned char) name[i]);
720 if ((nlen & 0x01) == 0)
722 (void) WriteBlobByte(ofile,0x00);
725 if (recnum != IPTC_ID)
727 (void) WriteBlobMSBLong(ofile,(unsigned int) len);
733 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
737 (void) WriteBlobByte(ofile,0x00);
743 /* patch in a fake length for now and fix it later */
744 savedpos = TellBlob(ofile);
745 (void) WriteBlobMSBLong(ofile,0xFFFFFFFFU);
747 savedolen = outputlen;
754 (void) WriteBlobByte(ofile,0x1c);
755 (void) WriteBlobByte(ofile,dataset);
756 (void) WriteBlobByte(ofile,(unsigned char) (recnum & 0xff));
757 (void) WriteBlobMSBShort(ofile,(unsigned short) len);
762 (void) WriteBlobByte(ofile,(unsigned char) token[next++]);
768 token=DestroyString(token);
769 newstr=DestroyString(newstr);
770 name=DestroyString(name);
772 token_info=DestroyTokenInfo(token_info);
773 line=DestroyString(line);
779 ssize_t diff = outputlen - savedolen;
781 currentpos = TellBlob(ofile);
782 offset=SeekBlob(ofile,savedpos,SEEK_SET);
785 (void) WriteBlobMSBLong(ofile,(unsigned int) diff);
786 offset=SeekBlob(ofile,currentpos,SEEK_SET);
794 /* some defines for the different JPEG block types */
795 #define M_SOF0 0xC0 /* Start Of Frame N */
796 #define M_SOF1 0xC1 /* N indicates which compression process */
797 #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
799 #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
809 #define M_EOI 0xD9 /* End Of Image (end of datastream) */
810 #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
828 static int jpeg_transfer_1(Image *ifile, Image *ofile)
832 c = ReadBlobByte(ifile);
835 (void) WriteBlobByte(ofile,(unsigned char) c);
840 static int jpeg_skip_1(Image *ifile)
844 c = ReadBlobByte(ifile);
851 static int jpeg_read_remaining(Image *ifile, Image *ofile)
855 while ((c = jpeg_transfer_1(ifile, ofile)) != EOF)
860 static int jpeg_skip_variable(Image *ifile, Image *ofile)
865 if ((c1 = jpeg_transfer_1(ifile, ofile)) == EOF)
867 if ((c2 = jpeg_transfer_1(ifile, ofile)) == EOF)
870 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
874 if (jpeg_transfer_1(ifile, ofile) == EOF)
880 static int jpeg_skip_variable2(Image *ifile, Image *ofile)
886 if ((c1 = ReadBlobByte(ifile)) == EOF) return M_EOI;
887 if ((c2 = ReadBlobByte(ifile)) == EOF) return M_EOI;
889 length = (((unsigned char) c1) << 8) + ((unsigned char) c2);
893 if (ReadBlobByte(ifile) == EOF)
899 static int jpeg_nextmarker(Image *ifile, Image *ofile)
903 /* transfer anything until we hit 0xff */
906 c = ReadBlobByte(ifile);
908 return M_EOI; /* we hit EOF */
911 (void) WriteBlobByte(ofile,(unsigned char) c);
914 /* get marker byte, swallowing possible padding */
917 c = ReadBlobByte(ifile);
919 return M_EOI; /* we hit EOF */
926 static int jpeg_skip_till_marker(Image *ifile, int marker)
932 /* skip anything until we hit 0xff */
936 c = ReadBlobByte(ifile);
939 return M_EOI; /* we hit EOF */
942 /* get marker byte, swallowing possible padding */
945 c = ReadBlobByte(ifile);
947 return M_EOI; /* we hit EOF */
949 } while (c != marker);
954 /* Embed binary IPTC data into a JPEG image. */
955 static int jpeg_embed(Image *ifile, Image *ofile, Image *iptc)
958 unsigned int done = 0;
962 if (jpeg_transfer_1(ifile, ofile) != 0xFF)
964 if (jpeg_transfer_1(ifile, ofile) != M_SOI)
967 while (done == MagickFalse)
969 marker=(unsigned int) jpeg_nextmarker(ifile, ofile);
976 if (marker != M_APP13)
978 (void) WriteBlobByte(ofile,0xff);
979 (void) WriteBlobByte(ofile,(unsigned char) marker);
986 /* we are going to write a new APP13 marker, so don't output the old one */
987 jpeg_skip_variable2(ifile, ofile);
991 /* APP0 is in each and every JPEG, so when we hit APP0 we insert our new APP13! */
992 jpeg_skip_variable(ifile, ofile);
994 if (iptc != (Image *)NULL)
997 psheader[] = "\xFF\xED\0\0Photoshop 3.0\0" "8BIM\x04\x04\0\0\0\0";
999 len=(unsigned int) GetBlobSize(iptc);
1001 len++; /* make the length even */
1002 psheader[2]=(char) ((len+16)>>8);
1003 psheader[3]=(char) ((len+16)&0xff);
1004 for (inx = 0; inx < 18; inx++)
1005 (void) WriteBlobByte(ofile,(unsigned char) psheader[inx]);
1006 jpeg_read_remaining(iptc, ofile);
1007 len=(unsigned int) GetBlobSize(iptc);
1009 (void) WriteBlobByte(ofile,0);
1014 /* we hit data, no more marker-inserting can be done! */
1015 jpeg_read_remaining(ifile, ofile);
1020 jpeg_skip_variable(ifile, ofile);
1027 /* handle stripping the APP13 data out of a JPEG */
1029 static void jpeg_strip(Image *ifile, Image *ofile)
1031 unsigned int marker;
1033 marker = jpeg_skip_till_marker(ifile, M_SOI);
1034 if (marker == M_SOI)
1036 (void) WriteBlobByte(ofile,0xff);
1037 (void) WriteBlobByte(ofile,M_SOI);
1038 jpeg_read_remaining(ifile, ofile);
1042 /* Extract any APP13 binary data into a file. */
1043 static int jpeg_extract(Image *ifile, Image *ofile)
1045 unsigned int marker;
1046 unsigned int done = 0;
1048 if (jpeg_skip_1(ifile) != 0xff)
1050 if (jpeg_skip_1(ifile) != M_SOI)
1053 while (done == MagickFalse)
1055 marker = jpeg_skip_till_marker(ifile, M_APP13);
1056 if (marker == M_APP13)
1058 marker = jpeg_nextmarker(ifile, ofile);
1066 static Image *ReadMETAImage(const ImageInfo *image_info,
1067 ExceptionInfo *exception)
1089 Open file containing binary metadata
1091 assert(image_info != (const ImageInfo *) NULL);
1092 assert(image_info->signature == MagickSignature);
1093 if (image_info->debug != MagickFalse)
1094 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1095 image_info->filename);
1096 assert(exception != (ExceptionInfo *) NULL);
1097 assert(exception->signature == MagickSignature);
1098 image=AcquireImage(image_info,exception);
1099 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1100 if (status == MagickFalse)
1102 image=DestroyImageList(image);
1103 return((Image *) NULL);
1107 if (SetImageBackgroundColor(image,exception) == MagickFalse)
1109 image=DestroyImageList(image);
1110 return((Image *) NULL);
1113 if (LocaleNCompare(image_info->magick,"8BIM",4) == 0)
1116 Read 8BIM binary metadata.
1118 buff=AcquireImage((ImageInfo *) NULL,exception);
1119 if (buff == (Image *) NULL)
1120 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1121 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1122 if (blob == (unsigned char *) NULL)
1124 buff=DestroyImage(buff);
1125 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1127 AttachBlob(buff->blob,blob,length);
1128 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
1130 length=(size_t) parse8BIM(image, buff);
1132 (void) WriteBlobByte(buff,0x0);
1134 else if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
1136 length=(size_t) parse8BIMW(image, buff);
1138 (void) WriteBlobByte(buff,0x0);
1144 c=ReadBlobByte(image);
1147 (void) WriteBlobByte(buff,(unsigned char) c);
1150 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1152 if (profile == (StringInfo *) NULL)
1153 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1154 status=SetImageProfile(image,"8bim",profile,exception);
1155 profile=DestroyStringInfo(profile);
1156 if (status == MagickFalse)
1157 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1158 blob=DetachBlob(buff->blob);
1159 blob=(unsigned char *) RelinquishMagickMemory(blob);
1160 buff=DestroyImage(buff);
1162 if (LocaleNCompare(image_info->magick,"APP1",4) == 0)
1165 name[MaxTextExtent];
1167 (void) FormatLocaleString(name,MaxTextExtent,"APP%d",1);
1168 buff=AcquireImage((ImageInfo *) NULL,exception);
1169 if (buff == (Image *) NULL)
1170 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1171 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1172 if (blob == (unsigned char *) NULL)
1174 buff=DestroyImage(buff);
1175 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1177 AttachBlob(buff->blob,blob,length);
1178 if (LocaleCompare(image_info->magick,"APP1JPEG") == 0)
1186 if (image_info->profile == (void *) NULL)
1188 blob=DetachBlob(buff->blob);
1189 blob=RelinquishMagickMemory(blob);
1190 buff=DestroyImage(buff);
1191 ThrowReaderException(CoderError,"NoIPTCProfileAvailable");
1193 profile=CloneStringInfo((StringInfo *) image_info->profile);
1194 iptc=AcquireImage((ImageInfo *) NULL,exception);
1195 if (iptc == (Image *) NULL)
1197 blob=DetachBlob(buff->blob);
1198 blob=RelinquishMagickMemory(blob);
1199 buff=DestroyImage(buff);
1200 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1202 AttachBlob(iptc->blob,GetStringInfoDatum(profile),
1203 GetStringInfoLength(profile));
1204 result=jpeg_embed(image,buff,iptc);
1205 blob=DetachBlob(iptc->blob);
1206 blob=RelinquishMagickMemory(blob);
1207 iptc=DestroyImage(iptc);
1210 blob=DetachBlob(buff->blob);
1211 blob=RelinquishMagickMemory(blob);
1212 buff=DestroyImage(buff);
1213 ThrowReaderException(CoderError,"JPEGEmbeddingFailed");
1221 /* Really - really slow - FIX ME PLEASE!!!! */
1222 c=ReadBlobByte(image);
1225 (void) WriteBlobByte(buff,c);
1238 buffer=(unsigned char *) AcquireQuantumMemory(MagickMaxBufferExtent,
1240 if (buffer != (unsigned char *) NULL)
1243 while ((length=ReadBlob(image,MagickMaxBufferExtent,buffer)) != 0)
1246 for (i=0; i < (ssize_t) length; i+=count)
1248 count=WriteBlob(buff,(size_t) (length-i),buffer+i);
1252 if (i < (ssize_t) length)
1255 buffer=(unsigned char *) RelinquishMagickMemory(buffer);
1259 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1261 if (profile == (StringInfo *) NULL)
1262 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1263 status=SetImageProfile(image,name,profile,exception);
1264 profile=DestroyStringInfo(profile);
1265 if (status == MagickFalse)
1266 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1267 blob=DetachBlob(buff->blob);
1268 blob=RelinquishMagickMemory(blob);
1269 buff=DestroyImage(buff);
1271 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
1272 (LocaleCompare(image_info->magick,"ICM") == 0))
1274 buff=AcquireImage((ImageInfo *) NULL,exception);
1275 if (buff == (Image *) NULL)
1276 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1277 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1278 if (blob == (unsigned char *) NULL)
1280 buff=DestroyImage(buff);
1281 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1283 AttachBlob(buff->blob,blob,length);
1286 c=ReadBlobByte(image);
1289 (void) WriteBlobByte(buff,(unsigned char) c);
1291 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1293 if (profile == (StringInfo *) NULL)
1294 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1295 (void) SetImageProfile(image,"icc",profile,exception);
1296 profile=DestroyStringInfo(profile);
1297 blob=DetachBlob(buff->blob);
1298 blob=(unsigned char *) RelinquishMagickMemory(blob);
1299 buff=DestroyImage(buff);
1301 if (LocaleCompare(image_info->magick,"IPTC") == 0)
1303 register unsigned char
1306 buff=AcquireImage((ImageInfo *) NULL,exception);
1307 if (buff == (Image *) NULL)
1308 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1309 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1310 if (blob == (unsigned char *) NULL)
1312 buff=DestroyImage(buff);
1313 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1315 AttachBlob(buff->blob,blob,length);
1316 /* write out the header - length field patched below */
1317 (void) WriteBlob(buff,11,(unsigned char *) "8BIM\04\04\0\0\0\0\0");
1318 (void) WriteBlobByte(buff,0xc6);
1319 if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0)
1321 length=(size_t) parse8BIM(image,buff);
1323 (void) WriteBlobByte(buff,0x00);
1325 else if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0)
1332 c=ReadBlobByte(image);
1335 (void) WriteBlobByte(buff,(unsigned char) c);
1338 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1340 if (profile == (StringInfo *) NULL)
1341 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1343 subtract off the length of the 8BIM stuff.
1345 length=GetStringInfoLength(profile)-12;
1346 p=GetStringInfoDatum(profile);
1347 p[10]=(unsigned char) (length >> 8);
1348 p[11]=(unsigned char) (length & 0xff);
1349 SetStringInfoDatum(profile,GetBlobStreamData(buff));
1350 (void) SetImageProfile(image,"8bim",profile,exception);
1351 profile=DestroyStringInfo(profile);
1352 blob=DetachBlob(buff->blob);
1353 blob=(unsigned char *) RelinquishMagickMemory(blob);
1354 buff=DestroyImage(buff);
1356 if (LocaleCompare(image_info->magick,"XMP") == 0)
1358 buff=AcquireImage((ImageInfo *) NULL,exception);
1359 if (buff == (Image *) NULL)
1360 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1361 blob=(unsigned char *) AcquireQuantumMemory(length,sizeof(unsigned char));
1362 if (blob == (unsigned char *) NULL)
1364 buff=DestroyImage(buff);
1365 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1367 AttachBlob(buff->blob,blob,length);
1370 c=ReadBlobByte(image);
1373 (void) WriteBlobByte(buff,(unsigned char) c);
1375 profile=BlobToStringInfo(GetBlobStreamData(buff),(size_t)
1377 if (profile == (StringInfo *) NULL)
1378 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1379 (void) SetImageProfile(image,"xmp",profile,exception);
1380 profile=DestroyStringInfo(profile);
1381 blob=DetachBlob(buff->blob);
1382 blob=(unsigned char *) RelinquishMagickMemory(blob);
1383 buff=DestroyImage(buff);
1385 (void) CloseBlob(image);
1386 return(GetFirstImageInList(image));
1390 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1394 % R e g i s t e r M E T A I m a g e %
1398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1400 % RegisterMETAImage() adds attributes for the META image format to
1401 % the list of supported formats. The attributes include the image format
1402 % tag, a method to read and/or write the format, whether the format
1403 % supports the saving of more than one frame to the same file or blob,
1404 % whether the format supports native in-memory I/O, and a brief
1405 % description of the format.
1407 % The format of the RegisterMETAImage method is:
1409 % size_t RegisterMETAImage(void)
1412 ModuleExport size_t RegisterMETAImage(void)
1417 entry=SetMagickInfo("8BIM");
1418 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1419 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1420 entry->adjoin=MagickFalse;
1421 entry->stealth=MagickTrue;
1422 entry->seekable_stream=MagickTrue;
1423 entry->description=ConstantString("Photoshop resource format");
1424 entry->module=ConstantString("META");
1425 (void) RegisterMagickInfo(entry);
1426 entry=SetMagickInfo("8BIMTEXT");
1427 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1428 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1429 entry->adjoin=MagickFalse;
1430 entry->stealth=MagickTrue;
1431 entry->seekable_stream=MagickTrue;
1432 entry->description=ConstantString("Photoshop resource text format");
1433 entry->module=ConstantString("META");
1434 (void) RegisterMagickInfo(entry);
1435 entry=SetMagickInfo("8BIMWTEXT");
1436 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1437 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1438 entry->adjoin=MagickFalse;
1439 entry->stealth=MagickTrue;
1440 entry->seekable_stream=MagickTrue;
1441 entry->description=ConstantString("Photoshop resource wide text format");
1442 entry->module=ConstantString("META");
1443 (void) RegisterMagickInfo(entry);
1444 entry=SetMagickInfo("APP1");
1445 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1446 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1447 entry->adjoin=MagickFalse;
1448 entry->stealth=MagickTrue;
1449 entry->seekable_stream=MagickTrue;
1450 entry->description=ConstantString("Raw application information");
1451 entry->module=ConstantString("META");
1452 (void) RegisterMagickInfo(entry);
1453 entry=SetMagickInfo("APP1JPEG");
1454 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1455 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1456 entry->adjoin=MagickFalse;
1457 entry->stealth=MagickTrue;
1458 entry->seekable_stream=MagickTrue;
1459 entry->description=ConstantString("Raw JPEG binary data");
1460 entry->module=ConstantString("META");
1461 (void) RegisterMagickInfo(entry);
1462 entry=SetMagickInfo("EXIF");
1463 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1464 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1465 entry->adjoin=MagickFalse;
1466 entry->stealth=MagickTrue;
1467 entry->seekable_stream=MagickTrue;
1468 entry->description=ConstantString("Exif digital camera binary data");
1469 entry->module=ConstantString("META");
1470 (void) RegisterMagickInfo(entry);
1471 entry=SetMagickInfo("XMP");
1472 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1473 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1474 entry->adjoin=MagickFalse;
1475 entry->stealth=MagickTrue;
1476 entry->seekable_stream=MagickTrue;
1477 entry->description=ConstantString("Adobe XML metadata");
1478 entry->module=ConstantString("META");
1479 (void) RegisterMagickInfo(entry);
1480 entry=SetMagickInfo("ICM");
1481 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1482 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1483 entry->adjoin=MagickFalse;
1484 entry->stealth=MagickTrue;
1485 entry->seekable_stream=MagickTrue;
1486 entry->description=ConstantString("ICC Color Profile");
1487 entry->module=ConstantString("META");
1488 (void) RegisterMagickInfo(entry);
1489 entry=SetMagickInfo("ICC");
1490 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1491 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1492 entry->adjoin=MagickFalse;
1493 entry->stealth=MagickTrue;
1494 entry->seekable_stream=MagickTrue;
1495 entry->description=ConstantString("ICC Color Profile");
1496 entry->module=ConstantString("META");
1497 (void) RegisterMagickInfo(entry);
1498 entry=SetMagickInfo("IPTC");
1499 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1500 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1501 entry->adjoin=MagickFalse;
1502 entry->stealth=MagickTrue;
1503 entry->seekable_stream=MagickTrue;
1504 entry->description=ConstantString("IPTC Newsphoto");
1505 entry->module=ConstantString("META");
1506 (void) RegisterMagickInfo(entry);
1507 entry=SetMagickInfo("IPTCTEXT");
1508 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1509 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1510 entry->adjoin=MagickFalse;
1511 entry->stealth=MagickTrue;
1512 entry->seekable_stream=MagickTrue;
1513 entry->description=ConstantString("IPTC Newsphoto text format");
1514 entry->module=ConstantString("META");
1515 (void) RegisterMagickInfo(entry);
1516 entry=SetMagickInfo("IPTCWTEXT");
1517 entry->decoder=(DecodeImageHandler *) ReadMETAImage;
1518 entry->encoder=(EncodeImageHandler *) WriteMETAImage;
1519 entry->adjoin=MagickFalse;
1520 entry->stealth=MagickTrue;
1521 entry->seekable_stream=MagickTrue;
1522 entry->description=ConstantString("IPTC Newsphoto text format");
1523 entry->module=ConstantString("META");
1524 (void) RegisterMagickInfo(entry);
1525 return(MagickImageCoderSignature);
1529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1533 % U n r e g i s t e r M E T A I m a g e %
1537 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1539 % UnregisterMETAImage() removes format registrations made by the
1540 % META module from the list of supported formats.
1542 % The format of the UnregisterMETAImage method is:
1544 % UnregisterMETAImage(void)
1547 ModuleExport void UnregisterMETAImage(void)
1549 (void) UnregisterMagickInfo("8BIM");
1550 (void) UnregisterMagickInfo("8BIMTEXT");
1551 (void) UnregisterMagickInfo("8BIMWTEXT");
1552 (void) UnregisterMagickInfo("EXIF");
1553 (void) UnregisterMagickInfo("APP1");
1554 (void) UnregisterMagickInfo("APP1JPEG");
1555 (void) UnregisterMagickInfo("ICCTEXT");
1556 (void) UnregisterMagickInfo("ICM");
1557 (void) UnregisterMagickInfo("ICC");
1558 (void) UnregisterMagickInfo("IPTC");
1559 (void) UnregisterMagickInfo("IPTCTEXT");
1560 (void) UnregisterMagickInfo("IPTCWTEXT");
1561 (void) UnregisterMagickInfo("XMP");
1565 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1569 % W r i t e M E T A I m a g e %
1573 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1575 % WriteMETAImage() writes a META image to a file.
1577 % The format of the WriteMETAImage method is:
1579 % MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
1580 % Image *image,ExceptionInfo *exception)
1582 % Compression code contributed by Kyle Shorter.
1584 % A description of each parameter follows:
1586 % o image_info: Specifies a pointer to an ImageInfo structure.
1588 % o image: A pointer to a Image structure.
1590 % o exception: return any errors or warnings in this structure.
1594 static size_t GetIPTCStream(unsigned char **info,size_t length)
1602 register unsigned char
1617 if ((*p == 0x1c) && (*(p+1) == 0x02))
1620 Extract IPTC from 8BIM resource block.
1622 while (extent >= 12)
1624 if (strncmp((const char *) p,"8BIM",4))
1628 marker=(unsigned int) (*p) << 8 | *(p+1);
1634 if ((size_t) c >= extent)
1640 tag_length=(((size_t) *p) << 24) | (((size_t) *(p+1)) << 16) |
1641 (((size_t) *(p+2)) << 8) | ((size_t) *(p+3));
1644 if (tag_length > extent)
1646 if (marker == IPTC_ID)
1651 if ((tag_length & 0x01) != 0)
1657 Find the beginning of the IPTC info.
1673 *info=p; /* let the caller know were it is */
1678 Determine the length of the IPTC info.
1695 Found the 0x1c tag; skip the dataset and record number tags.
1697 c=(*p++); /* should be 2 */
1701 if ((info_length == 1) && (c != 2))
1704 c=(*p++); /* should be 0 */
1708 if ((info_length == 2) && (c != 0))
1712 Decode the length of the block that follows - ssize_t or short format.
1719 if ((c & 0x80) != 0)
1725 for (i=0; i < 4; i++)
1740 tag_length=((long) c) << 8;
1746 tag_length|=(long) c;
1748 if (tag_length > (length+1))
1754 info_length+=tag_length;
1756 return(info_length);
1759 static void formatString(Image *ofile, const char *s, int len)
1762 temp[MaxTextExtent];
1764 (void) WriteBlobByte(ofile,'"');
1765 for (; len > 0; len--, s++) {
1769 (void) WriteBlobString(ofile,"&");
1773 (void) WriteBlobString(ofile,"<");
1776 (void) WriteBlobString(ofile,">");
1780 (void) WriteBlobString(ofile,""");
1784 (void) WriteBlobByte(ofile,(unsigned char) *s);
1787 (void) FormatLocaleString(temp,MaxTextExtent,"&#%d;", c & 255);
1788 (void) WriteBlobString(ofile,temp);
1793 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1794 (void) WriteBlobString(ofile,"\"\r\n");
1796 #if defined(macintosh)
1797 (void) WriteBlobString(ofile,"\"\r");
1799 (void) WriteBlobString(ofile,"\"\n");
1804 typedef struct _tag_spec
1813 static const tag_spec tags[] = {
1814 { 5, "Image Name" },
1815 { 7, "Edit Status" },
1818 { 20, "Supplemental Category" },
1819 { 22, "Fixture Identifier" },
1821 { 30, "Release Date" },
1822 { 35, "Release Time" },
1823 { 40, "Special Instructions" },
1824 { 45, "Reference Service" },
1825 { 47, "Reference Date" },
1826 { 50, "Reference Number" },
1827 { 55, "Created Date" },
1828 { 60, "Created Time" },
1829 { 65, "Originating Program" },
1830 { 70, "Program Version" },
1831 { 75, "Object Cycle" },
1833 { 85, "Byline Title" },
1835 { 95, "Province State" },
1836 { 100, "Country Code" },
1838 { 103, "Original Transmission Reference" },
1839 { 105, "Headline" },
1842 { 116, "Copyright String" },
1844 { 121, "Image Orientation" },
1845 { 122, "Caption Writer" },
1846 { 131, "Local Caption" },
1847 { 200, "Custom Field 1" },
1848 { 201, "Custom Field 2" },
1849 { 202, "Custom Field 3" },
1850 { 203, "Custom Field 4" },
1851 { 204, "Custom Field 5" },
1852 { 205, "Custom Field 6" },
1853 { 206, "Custom Field 7" },
1854 { 207, "Custom Field 8" },
1855 { 208, "Custom Field 9" },
1856 { 209, "Custom Field 10" },
1857 { 210, "Custom Field 11" },
1858 { 211, "Custom Field 12" },
1859 { 212, "Custom Field 13" },
1860 { 213, "Custom Field 14" },
1861 { 214, "Custom Field 15" },
1862 { 215, "Custom Field 16" },
1863 { 216, "Custom Field 17" },
1864 { 217, "Custom Field 18" },
1865 { 218, "Custom Field 19" },
1866 { 219, "Custom Field 20" }
1869 static int formatIPTC(Image *ifile, Image *ofile)
1872 temp[MaxTextExtent];
1892 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
1897 foundiptc = 0; /* found the IPTC-Header */
1898 tagsfound = 0; /* number of tags found */
1900 c = ReadBlobByte(ifile);
1913 /* we found the 0x1c tag and now grab the dataset and record number tags */
1914 c = ReadBlobByte(ifile);
1915 if (c == EOF) return -1;
1916 dataset = (unsigned char) c;
1917 c = ReadBlobByte(ifile);
1918 if (c == EOF) return -1;
1919 recnum = (unsigned char) c;
1920 /* try to match this record to one of the ones in our named table */
1921 for (i=0; i< tagcount; i++)
1923 if (tags[i].id == (short) recnum)
1927 readable = (unsigned char *) tags[i].name;
1929 readable = (unsigned char *) "";
1931 We decode the length of the block that follows - ssize_t or short fmt.
1933 c=ReadBlobByte(ifile);
1934 if (c == EOF) return -1;
1935 if (c & (unsigned char) 0x80)
1942 c0=ReadBlobByte(ifile);
1943 if (c0 == EOF) return -1;
1944 taglen = (c << 8) | c0;
1946 if (taglen < 0) return -1;
1947 /* make a buffer to hold the tag datand snag it from the input stream */
1948 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MaxTextExtent),
1950 if (str == (unsigned char *) NULL)
1952 printf("MemoryAllocationFailed");
1955 for (tagindx=0; tagindx<taglen; tagindx++)
1957 c=ReadBlobByte(ifile);
1958 if (c == EOF) return -1;
1959 str[tagindx] = (unsigned char) c;
1963 /* now finish up by formatting this binary data into ASCII equivalent */
1964 if (strlen((char *)readable) > 0)
1965 (void) FormatLocaleString(temp,MaxTextExtent,"%d#%d#%s=",
1966 (unsigned int) dataset, (unsigned int) recnum, readable);
1968 (void) FormatLocaleString(temp,MaxTextExtent,"%d#%d=",
1969 (unsigned int) dataset,(unsigned int) recnum);
1970 (void) WriteBlobString(ofile,temp);
1971 formatString( ofile, (char *)str, taglen );
1972 str=(unsigned char *) RelinquishMagickMemory(str);
1976 c=ReadBlobByte(ifile);
1978 return((int) tagsfound);
1981 static int readWordFromBuffer(char **s, ssize_t *len)
1992 c = *(*s)++; (*len)--;
1993 if (*len < 0) return -1;
1994 buffer[i] = (unsigned char) c;
1996 return (((int) buffer[ 0 ]) << 8) |
1997 (((int) buffer[ 1 ]));
2000 static int formatIPTCfromBuffer(Image *ofile, char *s, ssize_t len)
2003 temp[MaxTextExtent];
2023 tagcount = (int) (sizeof(tags) / sizeof(tag_spec));
2028 foundiptc = 0; /* found the IPTC-Header */
2029 tagsfound = 0; /* number of tags found */
2044 We found the 0x1c tag and now grab the dataset and record number tags.
2047 if (len < 0) return -1;
2048 dataset = (unsigned char) c;
2050 if (len < 0) return -1;
2051 recnum = (unsigned char) c;
2052 /* try to match this record to one of the ones in our named table */
2053 for (i=0; i< tagcount; i++)
2054 if (tags[i].id == (short) recnum)
2057 readable=(unsigned char *) tags[i].name;
2059 readable=(unsigned char *) "";
2061 We decode the length of the block that follows - ssize_t or short fmt.
2067 if (c & (unsigned char) 0x80)
2073 taglen=readWordFromBuffer(&s, &len);
2077 /* make a buffer to hold the tag datand snag it from the input stream */
2078 str=(unsigned char *) AcquireQuantumMemory((size_t) (taglen+MaxTextExtent),
2080 if (str == (unsigned char *) NULL)
2082 printf("MemoryAllocationFailed");
2085 for (tagindx=0; tagindx<taglen; tagindx++)
2090 str[tagindx]=(unsigned char) c;
2094 /* now finish up by formatting this binary data into ASCII equivalent */
2095 if (strlen((char *)readable) > 0)
2096 (void) FormatLocaleString(temp,MaxTextExtent,"%d#%d#%s=",
2097 (unsigned int) dataset,(unsigned int) recnum, readable);
2099 (void) FormatLocaleString(temp,MaxTextExtent,"%d#%d=",
2100 (unsigned int) dataset,(unsigned int) recnum);
2101 (void) WriteBlobString(ofile,temp);
2102 formatString( ofile, (char *)str, taglen );
2103 str=(unsigned char *) RelinquishMagickMemory(str);
2107 return ((int) tagsfound);
2110 static int format8BIM(Image *ifile, Image *ofile)
2113 temp[MaxTextExtent];
2132 foundOSType=0; /* found the OSType */
2134 c=ReadBlobByte(ifile);
2142 buffer[0]=(unsigned char) c;
2145 c=ReadBlobByte(ifile);
2148 buffer[i] = (unsigned char) c;
2151 if (strcmp((const char *)buffer, "8BIM") == 0)
2158 c=ReadBlobByte(ifile);
2162 We found the OSType (8BIM) and now grab the ID, PString, and Size fields.
2164 ID=(int) ReadBlobMSBShort(ifile);
2171 c=ReadBlobByte(ifile);
2174 plen = (unsigned char) c;
2175 PString=(unsigned char *) AcquireQuantumMemory((size_t) (plen+
2176 MaxTextExtent),sizeof(*PString));
2177 if (PString == (unsigned char *) NULL)
2179 printf("MemoryAllocationFailed");
2182 for (i=0; i<plen; i++)
2184 c=ReadBlobByte(ifile);
2185 if (c == EOF) return -1;
2186 PString[i] = (unsigned char) c;
2188 PString[ plen ] = 0;
2189 if ((plen & 0x01) == 0)
2191 c=ReadBlobByte(ifile);
2196 count = (int) ReadBlobMSBLong(ifile);
2197 if (count < 0) return -1;
2198 /* make a buffer to hold the datand snag it from the input stream */
2199 str=(unsigned char *) AcquireQuantumMemory((size_t) count,sizeof(*str));
2200 if (str == (unsigned char *) NULL)
2202 printf("MemoryAllocationFailed");
2205 for (i=0; i < (ssize_t) count; i++)
2207 c=ReadBlobByte(ifile);
2210 str[i]=(unsigned char) c;
2213 /* we currently skip thumbnails, since it does not make
2214 * any sense preserving them in a real world application
2216 if (ID != THUMBNAIL_ID)
2218 /* now finish up by formatting this binary data into
2221 if (strlen((const char *)PString) > 0)
2222 (void) FormatLocaleString(temp,MaxTextExtent,"8BIM#%d#%s=",ID,
2225 (void) FormatLocaleString(temp,MaxTextExtent,"8BIM#%d=",ID);
2226 (void) WriteBlobString(ofile,temp);
2229 formatString(ofile, "IPTC", 4);
2230 formatIPTCfromBuffer(ofile, (char *)str, (ssize_t) count);
2233 formatString(ofile, (char *)str, (ssize_t) count);
2235 str=(unsigned char *) RelinquishMagickMemory(str);
2236 PString=(unsigned char *) RelinquishMagickMemory(PString);
2238 c=ReadBlobByte(ifile);
2243 static MagickBooleanType WriteMETAImage(const ImageInfo *image_info,
2244 Image *image,ExceptionInfo *exception)
2258 assert(image_info != (const ImageInfo *) NULL);
2259 assert(image_info->signature == MagickSignature);
2260 assert(image != (Image *) NULL);
2261 assert(image->signature == MagickSignature);
2262 if (image->debug != MagickFalse)
2263 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
2265 if (LocaleCompare(image_info->magick,"8BIM") == 0)
2270 profile=GetImageProfile(image,"8bim");
2271 if (profile == (StringInfo *) NULL)
2272 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2273 assert(exception != (ExceptionInfo *) NULL);
2274 assert(exception->signature == MagickSignature);
2275 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2276 if (status == MagickFalse)
2278 (void) WriteBlob(image,GetStringInfoLength(profile),
2279 GetStringInfoDatum(profile));
2280 (void) CloseBlob(image);
2283 if (LocaleCompare(image_info->magick,"iptc") == 0)
2291 profile=GetImageProfile(image,"iptc");
2292 if (profile == (StringInfo *) NULL)
2293 profile=GetImageProfile(image,"8bim");
2294 if (profile == (StringInfo *) NULL)
2295 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2296 assert(exception != (ExceptionInfo *) NULL);
2297 assert(exception->signature == MagickSignature);
2298 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2299 info=GetStringInfoDatum(profile);
2300 length=GetStringInfoLength(profile);
2301 length=GetIPTCStream(&info,length);
2303 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2304 (void) WriteBlob(image,length,info);
2305 (void) CloseBlob(image);
2308 if (LocaleCompare(image_info->magick,"8BIMTEXT") == 0)
2313 profile=GetImageProfile(image,"8bim");
2314 if (profile == (StringInfo *) NULL)
2315 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2316 assert(exception != (ExceptionInfo *) NULL);
2317 assert(exception->signature == MagickSignature);
2318 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2319 if (status == MagickFalse)
2321 buff=AcquireImage((ImageInfo *) NULL,exception);
2322 if (buff == (Image *) NULL)
2323 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2324 AttachBlob(buff->blob,GetStringInfoDatum(profile),
2325 GetStringInfoLength(profile));
2326 format8BIM(buff,image);
2327 (void) DetachBlob(buff->blob);
2328 buff=DestroyImage(buff);
2329 (void) CloseBlob(image);
2332 if (LocaleCompare(image_info->magick,"8BIMWTEXT") == 0)
2333 return(MagickFalse);
2334 if (LocaleCompare(image_info->magick,"IPTCTEXT") == 0)
2342 profile=GetImageProfile(image,"8bim");
2343 if (profile == (StringInfo *) NULL)
2344 ThrowWriterException(CoderError,"No8BIMDataIsAvailable");
2345 info=GetStringInfoDatum(profile);
2346 length=GetStringInfoLength(profile);
2347 length=GetIPTCStream(&info,length);
2349 ThrowWriterException(CoderError,"NoIPTCProfileAvailable");
2350 assert(exception != (ExceptionInfo *) NULL);
2351 assert(exception->signature == MagickSignature);
2352 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2353 if (status == MagickFalse)
2355 buff=AcquireImage((ImageInfo *) NULL,exception);
2356 if (buff == (Image *) NULL)
2357 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
2358 AttachBlob(buff->blob,info,length);
2359 formatIPTC(buff,image);
2360 (void) DetachBlob(buff->blob);
2361 buff=DestroyImage(buff);
2362 (void) CloseBlob(image);
2365 if (LocaleCompare(image_info->magick,"IPTCWTEXT") == 0)
2366 return(MagickFalse);
2367 if ((LocaleCompare(image_info->magick,"APP1") == 0) ||
2368 (LocaleCompare(image_info->magick,"EXIF") == 0) ||
2369 (LocaleCompare(image_info->magick,"XMP") == 0))
2372 (void) Write APP1 image.
2374 profile=GetImageProfile(image,image_info->magick);
2375 if (profile == (StringInfo *) NULL)
2376 ThrowWriterException(CoderError,"NoAPP1DataIsAvailable");
2377 assert(exception != (ExceptionInfo *) NULL);
2378 assert(exception->signature == MagickSignature);
2379 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2380 if (status == MagickFalse)
2382 (void) WriteBlob(image,GetStringInfoLength(profile),
2383 GetStringInfoDatum(profile));
2384 (void) CloseBlob(image);
2387 if ((LocaleCompare(image_info->magick,"ICC") == 0) ||
2388 (LocaleCompare(image_info->magick,"ICM") == 0))
2393 profile=GetImageProfile(image,"icc");
2394 if (profile == (StringInfo *) NULL)
2395 ThrowWriterException(CoderError,"NoColorProfileIsAvailable");
2396 assert(exception != (ExceptionInfo *) NULL);
2397 assert(exception->signature == MagickSignature);
2398 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
2399 if (status == MagickFalse)
2401 (void) WriteBlob(image,GetStringInfoLength(profile),
2402 GetStringInfoDatum(profile));
2403 (void) CloseBlob(image);
2406 return(MagickFalse);