]> granicus.if.org Git - imagemagick/blob - coders/sfw.c
9db762bea9884fe400fa3e9f52ca895ec5fae358
[imagemagick] / coders / sfw.c
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 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2011 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 \f
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 \f
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 */
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 \f
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
123 static unsigned char *SFWScan(unsigned char *p,const unsigned char *q,
124   const unsigned char *target,const int length)
125 {
126   register ssize_t
127     i;
128
129   for ( ; p < q; p++)
130   {
131     if (*p != *target)
132       continue;
133     if (length == 1)
134       return(p);
135     for (i=1; i < length; i++)
136       if (*(p+i) != *(target+i))
137         break;
138     if (i == length)
139       return(p);
140   }
141   return((unsigned char *) NULL);
142 }
143
144 static void TranslateSFWMarker(unsigned char *marker)
145 {
146   switch (marker[1])
147   {
148     case 0xc8: marker[1]=0xd8; break;  /* soi */
149     case 0xd0: marker[1]=0xe0; break;  /* app */
150     case 0xcb: marker[1]=0xdb; break;  /* dqt */
151     case 0xa0: marker[1]=0xc0; break;  /* sof */
152     case 0xa4: marker[1]=0xc4; break;  /* sof */
153     case 0xca: marker[1]=0xda; break;  /* sos */
154     case 0xc9: marker[1]=0xd9; break;  /* eoi */
155     default: break;
156   }
157 }
158
159 static Image *ReadSFWImage(const ImageInfo *image_info,ExceptionInfo *exception)
160 {
161   static unsigned char
162     HuffmanTable[] =
163     {
164       0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01,
165       0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166       0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
167       0x01, 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
168       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04,
169       0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x00, 0x02, 0x01,
170       0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00,
171       0x01, 0x7D, 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21,
172       0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32,
173       0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1,
174       0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18,
175       0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, 0x36,
176       0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
177       0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64,
178       0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77,
179       0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A,
180       0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3,
181       0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5,
182       0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
183       0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9,
184       0xDA, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA,
185       0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0x11,
186       0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04,
187       0x04, 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
188       0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, 0x13,
189       0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09,
190       0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24,
191       0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28,
192       0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45,
193       0x46, 0x47, 0x48, 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
194       0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x73,
195       0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85,
196       0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
197       0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9,
198       0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2,
199       0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4,
200       0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
201       0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
202       0xF9, 0xFA
203     };
204
205   FILE
206     *file;
207
208   Image
209     *flipped_image,
210     *image;
211
212   ImageInfo
213     *read_info;
214
215   int
216     unique_file;
217
218   MagickBooleanType
219     status;
220
221   register unsigned char
222     *header,
223     *data;
224
225   size_t
226     extent;
227
228   ssize_t
229     count;
230
231   unsigned char
232     *buffer,
233     *offset;
234
235   /*
236     Open image file.
237   */
238   assert(image_info != (const ImageInfo *) NULL);
239   assert(image_info->signature == MagickSignature);
240   if (image_info->debug != MagickFalse)
241     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
242       image_info->filename);
243   assert(exception != (ExceptionInfo *) NULL);
244   assert(exception->signature == MagickSignature);
245   image=AcquireImage(image_info);
246   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
247   if (status == MagickFalse)
248     {
249       image=DestroyImageList(image);
250       return((Image *) NULL);
251     }
252   /*
253     Read image into a buffer.
254   */
255   buffer=(unsigned char *) AcquireQuantumMemory((size_t) GetBlobSize(image),
256     sizeof(*buffer));
257   if (buffer == (unsigned char *) NULL)
258     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
259   count=ReadBlob(image,(size_t) GetBlobSize(image),buffer);
260   if ((count == 0) || (LocaleNCompare((char *) buffer,"SFW",3) != 0))
261     ThrowReaderException(CorruptImageError,"ImproperImageHeader");
262   (void) CloseBlob(image);
263   image=DestroyImage(image);
264   /*
265     Find the start of the JFIF data
266   */
267   header=SFWScan(buffer,buffer+count-1,(const unsigned char *)
268     "\377\310\377\320",4);
269   if (header == (unsigned char *) NULL)
270     {
271       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
272       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
273     }
274   TranslateSFWMarker(header);  /* translate soi and app tags */
275   TranslateSFWMarker(header+2);
276   (void) CopyMagickMemory(header+6,"JFIF\0\001\0",7);  /* JFIF magic */
277   /*
278     Translate remaining markers.
279   */
280   offset=header+2;
281   offset+=(offset[2] << 8)+offset[3]+2;
282   for ( ; ; )
283   {
284     TranslateSFWMarker(offset);
285     if (offset[1] == 0xda)
286       break;
287     offset+=(offset[2] << 8)+offset[3]+2;
288   }
289   offset--;
290   data=SFWScan(offset,buffer+count-1,(const unsigned char *) "\377\311",2);
291   if (data == (unsigned char *) NULL)
292     {
293       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
294       ThrowReaderException(CorruptImageError,"ImproperImageHeader");
295     }
296   TranslateSFWMarker(data++);  /* translate eoi marker */
297   /*
298     Write JFIF file.
299   */
300   read_info=CloneImageInfo(image_info);
301   SetImageInfoBlob(read_info,(void *) NULL,0);
302   file=(FILE *) NULL;
303   unique_file=AcquireUniqueFileResource(read_info->filename);
304   if (unique_file != -1)
305     file=fopen_utf8(read_info->filename,"wb");
306   if ((unique_file == -1) || (file == (FILE *) NULL))
307     {
308       buffer=(unsigned char *) RelinquishMagickMemory(buffer);
309       read_info=DestroyImageInfo(read_info);
310       (void) CopyMagickString(image->filename,read_info->filename,
311         MaxTextExtent);
312       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
313         image->filename);
314       image=DestroyImageList(image);
315       return((Image *) NULL);
316     }
317   extent=fwrite(header,(size_t) (offset-header+1),1,file);
318   (void) extent;
319   extent=fwrite(HuffmanTable,1,sizeof(HuffmanTable)/sizeof(*HuffmanTable),file);
320   extent=fwrite(offset+1,(size_t) (data-offset),1,file);
321   status=ferror(file) == -1 ? MagickFalse : MagickTrue;
322   (void) fclose(file);
323   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
324   if (status == MagickFalse)
325     {
326       char
327         *message;
328
329       (void) remove_utf8(read_info->filename);
330       read_info=DestroyImageInfo(read_info);
331       message=GetExceptionMessage(errno);
332       (void) ThrowMagickException(&image->exception,GetMagickModule(),
333         FileOpenError,"UnableToWriteFile","`%s': %s",image->filename,message);
334       message=DestroyString(message);
335       image=DestroyImageList(image);
336       return((Image *) NULL);
337     }
338   /*
339     Read JPEG image.
340   */
341   image=ReadImage(read_info,exception);
342   (void) RelinquishUniqueFileResource(read_info->filename);
343   read_info=DestroyImageInfo(read_info);
344   if (image == (Image *) NULL)
345     return(GetFirstImageInList(image));
346   /*
347     Correct image orientation.
348   */
349   flipped_image=FlipImage(image,exception);
350   if (flipped_image != (Image *) NULL)
351     {
352       DuplicateBlob(flipped_image,image);
353       image=DestroyImage(image);
354       image=flipped_image;
355     }
356   return(GetFirstImageInList(image));
357 }
358 \f
359 /*
360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
361 %                                                                             %
362 %                                                                             %
363 %                                                                             %
364 %   R e g i s t e r S F W I m a g e                                           %
365 %                                                                             %
366 %                                                                             %
367 %                                                                             %
368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
369 %
370 %  RegisterSFWImage() adds attributes for the SFW image format to
371 %  the list of supported formats.  The attributes include the image format
372 %  tag, a method to read and/or write the format, whether the format
373 %  supports the saving of more than one frame to the same file or blob,
374 %  whether the format supports native in-memory I/O, and a brief
375 %  description of the format.
376 %
377 %  The format of the RegisterSFWImage method is:
378 %
379 %      size_t RegisterSFWImage(void)
380 %
381 */
382 ModuleExport size_t RegisterSFWImage(void)
383 {
384   MagickInfo
385     *entry;
386
387   entry=SetMagickInfo("SFW");
388   entry->decoder=(DecodeImageHandler *) ReadSFWImage;
389   entry->magick=(IsImageFormatHandler *) IsSFW;
390   entry->adjoin=MagickFalse;
391   entry->description=ConstantString("Seattle Film Works");
392   entry->module=ConstantString("SFW");
393   (void) RegisterMagickInfo(entry);
394   return(MagickImageCoderSignature);
395 }
396 \f
397 /*
398 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %   U n r e g i s t e r S F W I m a g e                                       %
403 %                                                                             %
404 %                                                                             %
405 %                                                                             %
406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
407 %
408 %  UnregisterSFWImage() removes format registrations made by the
409 %  SFW module from the list of supported formats.
410 %
411 %  The format of the UnregisterSFWImage method is:
412 %
413 %      UnregisterSFWImage(void)
414 %
415 */
416 ModuleExport void UnregisterSFWImage(void)
417 {
418   (void) UnregisterMagickInfo("SFW");
419 }