• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            SSSSS  FFFFF  W   W                              %
7 %                            SS     F      W   W                              %
8 %                             SSS   FFF    W   W                              %
9 %                               SS  F      W W W                              %
10 %                            SSSSS  F       W W                               %
11 %                                                                             %
12 %                                                                             %
13 %                    Read/Write ImageMagick Image Format                      %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                   Cristy                                    %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
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.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40   Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/constitute.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/resource_.h"
54 #include "MagickCore/quantum-private.h"
55 #include "MagickCore/static.h"
56 #include "MagickCore/string_.h"
57 #include "MagickCore/module.h"
58 #include "MagickCore/transform.h"
59 #include "MagickCore/utility.h"
60 #include "MagickCore/utility-private.h"
61 
62 /*
63 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
64 %                                                                             %
65 %                                                                             %
66 %                                                                             %
67 %   I s S F W                                                                 %
68 %                                                                             %
69 %                                                                             %
70 %                                                                             %
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 %
73 %  IsSFW() returns MagickTrue if the image format type, identified by the
74 %  magick string, is SFW.
75 %
76 %  The format of the IsSFW method is:
77 %
78 %      MagickBooleanType IsSFW(const unsigned char *magick,const size_t length)
79 %
80 %  A description of each parameter follows:
81 %
82 %    o magick: compare image format pattern against these bytes.
83 %
84 %    o length: Specifies the length of the magick string.
85 %
86 */
IsSFW(const unsigned char * magick,const size_t length)87 static MagickBooleanType IsSFW(const unsigned char *magick,const size_t length)
88 {
89   if (length < 5)
90     return(MagickFalse);
91   if (LocaleNCompare((const char *) magick,"SFW94",5) == 0)
92     return(MagickTrue);
93   return(MagickFalse);
94 }
95 
96 /*
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 %                                                                             %
99 %                                                                             %
100 %                                                                             %
101 %   R e a d S F W I m a g e                                                   %
102 %                                                                             %
103 %                                                                             %
104 %                                                                             %
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %
107 %  ReadSFWImage() reads a Seattle Film Works image file and returns it.
108 %  It allocates the memory necessary for the new Image structure and returns a
109 %  pointer to the new image.
110 %
111 %  The format of the ReadSFWImage method is:
112 %
113 %      Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception)
114 %
115 %  A description of each parameter follows:
116 %
117 %    o image_info: the image info.
118 %
119 %    o exception: return any errors or warnings in this structure.
120 %
121 */
122 
SFWScan(const unsigned char * p,const unsigned char * q,const unsigned char * target,const size_t length)123 static unsigned char *SFWScan(const unsigned char *p,const unsigned char *q,
124   const unsigned char *target,const size_t length)
125 {
126   register ssize_t
127     i;
128 
129   if ((p+length) < q)
130     while (p < q)
131     {
132       for (i=0; i < (ssize_t) length; i++)
133         if (p[i] != target[i])
134           break;
135       if (i == (ssize_t) length)
136         return((unsigned char *) p);
137       p++;
138     }
139   return((unsigned char *) NULL);
140 }
141 
TranslateSFWMarker(unsigned char * marker)142 static void TranslateSFWMarker(unsigned char *marker)
143 {
144   switch (marker[1])
145   {
146     case 0xc8: marker[1]=0xd8; break;  /* soi */
147     case 0xd0: marker[1]=0xe0; break;  /* app */
148     case 0xcb: marker[1]=0xdb; break;  /* dqt */
149     case 0xa0: marker[1]=0xc0; break;  /* sof */
150     case 0xa4: marker[1]=0xc4; break;  /* sof */
151     case 0xca: marker[1]=0xda; break;  /* sos */
152     case 0xc9: marker[1]=0xd9; break;  /* eoi */
153     default: break;
154   }
155 }
156 
ReadSFWImage(const ImageInfo * image_info,ExceptionInfo * exception)157 static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception)
158 {
159   static unsigned char
160     HuffmanTable[] =
161     {
162       0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
163       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
165       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
166       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
167       0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
168       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
169       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21,
170       0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
171       0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1,
172       0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18,
173       0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36,
174       0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
175       0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
176       0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
177       0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A,
178       0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3,
179       0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5,
180       0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
181       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
182       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
183       0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11,
184       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
185       0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
186       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
187       0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09,
188       0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
189       0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28,
190       0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
191       0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
192       0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73,
193       0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
194       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
195       0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
196       0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2,
197       0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
198       0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
199       0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
200       0xF9, 0xFA
201     };
202 
203   FILE
204     *file;
205 
206   Image
207     *flipped_image,
208     *jpeg_image,
209     *image;
210 
211   ImageInfo
212     *read_info;
213 
214   int
215     unique_file;
216 
217   MagickBooleanType
218     status;
219 
220   register unsigned char
221     *header,
222     *data;
223 
224   size_t
225     extent;
226 
227   ssize_t
228     count;
229 
230   unsigned char
231     *buffer,
232     *offset;
233 
234   /*
235     Open image file.
236   */
237   assert(image_info != (const ImageInfo *) NULL);
238   assert(image_info->signature == MagickCoreSignature);
239   if (image_info->debug != MagickFalse)
240     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
241       image_info->filename);
242   assert(exception != (ExceptionInfo *) NULL);
243   assert(exception->signature == MagickCoreSignature);
244   image=AcquireImage(image_info,exception);
245   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
246   if (status == MagickFalse)
247     {
248       image=DestroyImageList(image);
249       return((Image *) NULL);
250     }
251   /*
252     Read image into a buffer.
253   */
254   if (GetBlobSize(image) != (size_t) GetBlobSize(image))
255     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
256   buffer=(unsigned char *) AcquireQuantumMemory((size_t) GetBlobSize(image),
257     sizeof(*buffer));
258   if (buffer == (unsigned char *) NULL)
259     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
260   count=ReadBlob(image,(size_t) GetBlobSize(image),buffer);
261   if ((count != (ssize_t) GetBlobSize(image)) ||
262       (LocaleNCompare((char *) buffer,"SFW",3) != 0))
263     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
264   (void) CloseBlob(image);
265   /*
266     Find the start of the JFIF data
267   */
268   header=SFWScan(buffer,buffer+count-1,(const unsigned char *)
269     "\377\310\377\320",4);
270   if (header == (unsigned char *) NULL)
271     {
272       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
273       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
274     }
275   TranslateSFWMarker(header);  /* translate soi and app tags */
276   TranslateSFWMarker(header+2);
277   (void) CopyMagickMemory(header+6,"JFIF\0\001\0",7);  /* JFIF magic */
278   /*
279     Translate remaining markers.
280   */
281   offset=header+2;
282   offset+=(((unsigned int) offset[2]) << 8)+offset[3]+2;
283   for ( ; ; )
284   {
285     if ((offset+4) > (buffer+count-1))
286       {
287         buffer=(unsigned char *) RelinquishMagickMemory(buffer);
288         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
289       }
290     TranslateSFWMarker(offset);
291     if (offset[1] == 0xda)
292       break;
293     offset+=(((unsigned int) offset[2]) << 8)+offset[3]+2;
294   }
295   offset--;
296   data=SFWScan(offset,buffer+count-1,(const unsigned char *) "\377\311",2);
297   if (data == (unsigned char *) NULL)
298     {
299       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
300       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
301     }
302   TranslateSFWMarker(data++);  /* translate eoi marker */
303   /*
304     Write JFIF file.
305   */
306   read_info=CloneImageInfo(image_info);
307   SetImageInfoBlob(read_info,(void *) NULL,0);
308   file=(FILE *) NULL;
309   unique_file=AcquireUniqueFileResource(read_info->filename);
310   if (unique_file != -1)
311     file=fopen_utf8(read_info->filename,"wb");
312   if ((unique_file == -1) || (file == (FILE *) NULL))
313     {
314       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
315       read_info=DestroyImageInfo(read_info);
316       (void) CopyMagickString(image->filename,read_info->filename,
317         MagickPathExtent);
318       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
319         image->filename);
320       image=DestroyImageList(image);
321       return((Image *) NULL);
322     }
323   extent=fwrite(header,(size_t) (offset-header+1),1,file);
324   (void) extent;
325   extent=fwrite(HuffmanTable,1,sizeof(HuffmanTable)/sizeof(*HuffmanTable),file);
326   extent=fwrite(offset+1,(size_t) (data-offset),1,file);
327   status=ferror(file) == -1 ? MagickFalse : MagickTrue;
328   (void) fclose(file);
329   (void) close(unique_file);
330   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
331   if (status == MagickFalse)
332     {
333       char
334         *message;
335 
336       (void) remove_utf8(read_info->filename);
337       read_info=DestroyImageInfo(read_info);
338       message=GetExceptionMessage(errno);
339       (void) ThrowMagickException(exception,GetMagickModule(),FileOpenError,
340         "UnableToWriteFile","`%s': %s",image->filename,message);
341       message=DestroyString(message);
342       image=DestroyImageList(image);
343       return((Image *) NULL);
344     }
345   /*
346     Read JPEG image.
347   */
348   jpeg_image=ReadImage(read_info,exception);
349   (void) RelinquishUniqueFileResource(read_info->filename);
350   read_info=DestroyImageInfo(read_info);
351   if (jpeg_image == (Image *) NULL)
352     {
353       image=DestroyImageList(image);
354       return(jpeg_image);
355     }
356   (void) CopyMagickString(jpeg_image->filename,image->filename,MagickPathExtent);
357   (void) CopyMagickString(jpeg_image->magick,image->magick,MagickPathExtent);
358   image=DestroyImageList(image);
359   image=jpeg_image;
360   /*
361     Correct image orientation.
362   */
363   flipped_image=FlipImage(image,exception);
364   if (flipped_image != (Image *) NULL)
365     {
366       DuplicateBlob(flipped_image,image);
367       image=DestroyImage(image);
368       image=flipped_image;
369     }
370   return(GetFirstImageInList(image));
371 }
372 
373 /*
374 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
375 %                                                                             %
376 %                                                                             %
377 %                                                                             %
378 %   R e g i s t e r S F W I m a g e                                           %
379 %                                                                             %
380 %                                                                             %
381 %                                                                             %
382 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
383 %
384 %  RegisterSFWImage() adds attributes for the SFW image format to
385 %  the list of supported formats.  The attributes include the image format
386 %  tag, a method to read and/or write the format, whether the format
387 %  supports the saving of more than one frame to the same file or blob,
388 %  whether the format supports native in-memory I/O, and a brief
389 %  description of the format.
390 %
391 %  The format of the RegisterSFWImage method is:
392 %
393 %      size_t RegisterSFWImage(void)
394 %
395 */
RegisterSFWImage(void)396 ModuleExport size_t RegisterSFWImage(void)
397 {
398   MagickInfo
399     *entry;
400 
401   entry=AcquireMagickInfo("SFW","SFW","Seattle Film Works");
402   entry->decoder=(DecodeImageHandler *) ReadSFWImage;
403   entry->magick=(IsImageFormatHandler *) IsSFW;
404   entry->flags^=CoderAdjoinFlag;
405   (void) RegisterMagickInfo(entry);
406   return(MagickImageCoderSignature);
407 }
408 
409 /*
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 %                                                                             %
412 %                                                                             %
413 %                                                                             %
414 %   U n r e g i s t e r S F W I m a g e                                       %
415 %                                                                             %
416 %                                                                             %
417 %                                                                             %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 %
420 %  UnregisterSFWImage() removes format registrations made by the
421 %  SFW module from the list of supported formats.
422 %
423 %  The format of the UnregisterSFWImage method is:
424 %
425 %      UnregisterSFWImage(void)
426 %
427 */
UnregisterSFWImage(void)428 ModuleExport void UnregisterSFWImage(void)
429 {
430   (void) UnregisterMagickInfo("SFW");
431 }
432