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