]> granicus.if.org Git - imagemagick/blob - coders/raw.c
(no commit message)
[imagemagick] / coders / raw.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            RRRR    AAA   W   W                              %
7 %                            R   R  A   A  W   W                              %
8 %                            RRRR   AAAAA  W W W                              %
9 %                            R R    A   A  WW WW                              %
10 %                            R  R   A   A  W   W                              %
11 %                                                                             %
12 %                                                                             %
13 %                       Read/Write RAW Image Format                           %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 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/cache.h"
46 #include "magick/colorspace.h"
47 #include "magick/constitute.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/quantum-private.h"
58 #include "magick/quantum-private.h"
59 #include "magick/static.h"
60 #include "magick/statistic.h"
61 #include "magick/string_.h"
62 #include "magick/module.h"
63 \f
64 /*
65   Forward declarations.
66 */
67 static MagickBooleanType
68   WriteRAWImage(const ImageInfo *,Image *);
69 \f
70 /*
71 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 %                                                                             %
73 %                                                                             %
74 %                                                                             %
75 %   R e a d R A W I m a g e                                                   %
76 %                                                                             %
77 %                                                                             %
78 %                                                                             %
79 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80 %
81 %  ReadRAWImage() reads an image of raw samples and returns it.  It allocates
82 %  the memory necessary for the new Image structure and returns a pointer to
83 %  the new image.
84 %
85 %  The format of the ReadRAWImage method is:
86 %
87 %      Image *ReadRAWImage(const ImageInfo *image_info,ExceptionInfo *exception)
88 %
89 %  A description of each parameter follows:
90 %
91 %    o image_info: the image info.
92 %
93 %    o exception: return any errors or warnings in this structure.
94 %
95 */
96 static Image *ReadRAWImage(const ImageInfo *image_info,
97   ExceptionInfo *exception)
98 {
99   Image
100     *canvas_image,
101     *image;
102
103   long
104     y;
105
106   MagickBooleanType
107     status;
108
109   MagickOffsetType
110     scene;
111
112   QuantumInfo
113     *quantum_info;
114
115   QuantumType
116     quantum_type;
117
118   register long
119     i;
120
121   ssize_t
122     count;
123
124   size_t
125     length;
126
127   unsigned char
128     *pixels;
129
130   /*
131     Open image file.
132   */
133   assert(image_info != (const ImageInfo *) NULL);
134   assert(image_info->signature == MagickSignature);
135   if (image_info->debug != MagickFalse)
136     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
137       image_info->filename);
138   assert(exception != (ExceptionInfo *) NULL);
139   assert(exception->signature == MagickSignature);
140   image=AcquireImage(image_info);
141   if ((image->columns == 0) || (image->rows == 0))
142     ThrowReaderException(OptionError,"MustSpecifyImageSize");
143   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
144   if (status == MagickFalse)
145     {
146       image=DestroyImageList(image);
147       return((Image *) NULL);
148     }
149   for (i=0; i < image->offset; i++)
150     if (ReadBlobByte(image) == EOF)
151       {
152         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
153           image->filename);
154         break;
155       }
156   /*
157     Create virtual canvas to support cropping (i.e. image.gray[100x100+10+20]).
158   */
159   canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
160     exception);
161   (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
162   quantum_type=GrayQuantum;
163   quantum_info=AcquireQuantumInfo(image_info,canvas_image);
164   if (quantum_info == (QuantumInfo *) NULL)
165     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
166   pixels=GetQuantumPixels(quantum_info);
167   if (image_info->number_scenes != 0)
168     while (image->scene < image_info->scene)
169     {
170       /*
171         Skip to next image.
172       */
173       image->scene++;
174       length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
175       for (y=0; y < (long) image->rows; y++)
176       {
177         count=ReadBlob(image,length,pixels);
178         if (count != (ssize_t) length)
179           break;
180       }
181     }
182   scene=0;
183   count=0;
184   length=0;
185   do
186   {
187     /*
188       Read pixels to virtual canvas image then push to image.
189     */
190     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
191       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
192         break;
193     if (scene == 0)
194       {
195         length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
196         count=ReadBlob(image,length,pixels);
197       }
198     for (y=0; y < (long) image->extract_info.height; y++)
199     {
200       register const PixelPacket
201         *restrict p;
202
203       register long
204         x;
205
206       register PixelPacket
207         *restrict q;
208
209       if (count != (ssize_t) length)
210         {
211           ThrowFileException(exception,CorruptImageError,
212             "UnexpectedEndOfFile",image->filename);
213           break;
214         }
215       q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,exception);
216       if (q == (PixelPacket *) NULL)
217         break;
218       length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,quantum_info,
219         quantum_type,pixels,exception);
220       if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
221         break;
222       if (((y-image->extract_info.y) >= 0) && 
223           ((y-image->extract_info.y) < (long) image->rows))
224         {
225           p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
226             image->columns,1,exception);
227           q=QueueAuthenticPixels(image,0,y-image->extract_info.y,image->columns,
228             1,exception);
229           if ((p == (const PixelPacket *) NULL) || (q == (PixelPacket *) NULL))
230             break;
231           for (x=0; x < (long) image->columns; x++)
232           {
233             q->red=p->red;
234             q->green=p->green;
235             q->blue=p->blue;
236             p++;
237             q++;
238           }
239           if (SyncAuthenticPixels(image,exception) == MagickFalse)
240             break;
241         }
242       if (image->previous == (Image *) NULL)
243         {
244           status=SetImageProgress(image,LoadImageTag,y,image->rows);
245           if (status == MagickFalse)
246             break;
247         }
248       count=ReadBlob(image,length,pixels);
249     }
250     SetQuantumImageType(image,quantum_type);
251     /*
252       Proceed to next image.
253     */
254     if (image_info->number_scenes != 0)
255       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
256         break;
257     if (count == (ssize_t) length)
258       {
259         /*
260           Allocate next image structure.
261         */
262         AcquireNextImage(image_info,image);
263         if (GetNextImageInList(image) == (Image *) NULL)
264           {
265             image=DestroyImageList(image);
266             return((Image *) NULL);
267           }
268         image=SyncNextImageInList(image);
269         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
270           GetBlobSize(image));
271         if (status == MagickFalse)
272           break;
273       }
274     scene++;
275   } while (count == (ssize_t) length);
276   quantum_info=DestroyQuantumInfo(quantum_info);
277   InheritException(&image->exception,&canvas_image->exception);
278   canvas_image=DestroyImage(canvas_image);
279   (void) CloseBlob(image);
280   return(GetFirstImageInList(image));
281 }
282 \f
283 /*
284 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285 %                                                                             %
286 %                                                                             %
287 %                                                                             %
288 %   R e g i s t e r R A W I m a g e                                           %
289 %                                                                             %
290 %                                                                             %
291 %                                                                             %
292 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 %
294 %  RegisterRAWImage() adds attributes for the RAW image format to the list of
295 %  supported formats.  The attributes include the image format tag, a method to
296 %  read and/or write the format, whether the format supports the saving of
297 %  more than one frame to the same file or blob, whether the format supports
298 %  native in-memory I/O, and a brief description of the format.
299 %
300 %  The format of the RegisterRAWImage method is:
301 %
302 %      unsigned long RegisterRAWImage(void)
303 %
304 */
305 ModuleExport unsigned long RegisterRAWImage(void)
306 {
307   MagickInfo
308     *entry;
309
310   entry=SetMagickInfo("R");
311   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
312   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
313   entry->raw=MagickTrue;
314   entry->endian_support=MagickTrue;
315   entry->format_type=ExplicitFormatType;
316   entry->description=ConstantString("Raw red samples");
317   entry->module=ConstantString("RAW");
318   (void) RegisterMagickInfo(entry);
319   entry=SetMagickInfo("C");
320   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
321   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
322   entry->raw=MagickTrue;
323   entry->endian_support=MagickTrue;
324   entry->format_type=ExplicitFormatType;
325   entry->description=ConstantString("Raw cyan samples");
326   entry->module=ConstantString("RAW");
327   (void) RegisterMagickInfo(entry);
328   entry=SetMagickInfo("G");
329   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
330   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
331   entry->raw=MagickTrue;
332   entry->endian_support=MagickTrue;
333   entry->format_type=ExplicitFormatType;
334   entry->description=ConstantString("Raw green samples");
335   entry->module=ConstantString("RAW");
336   (void) RegisterMagickInfo(entry);
337   entry=SetMagickInfo("M");
338   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
339   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
340   entry->raw=MagickTrue;
341   entry->endian_support=MagickTrue;
342   entry->format_type=ExplicitFormatType;
343   entry->description=ConstantString("Raw magenta samples");
344   entry->module=ConstantString("RAW");
345   (void) RegisterMagickInfo(entry);
346   entry=SetMagickInfo("B");
347   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
348   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
349   entry->raw=MagickTrue;
350   entry->endian_support=MagickTrue;
351   entry->description=ConstantString("Raw blue samples");
352   entry->format_type=ExplicitFormatType;
353   entry->module=ConstantString("RAW");
354   (void) RegisterMagickInfo(entry);
355   entry=SetMagickInfo("Y");
356   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
357   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
358   entry->raw=MagickTrue;
359   entry->endian_support=MagickTrue;
360   entry->format_type=ExplicitFormatType;
361   entry->description=ConstantString("Raw yellow samples");
362   entry->module=ConstantString("RAW");
363   (void) RegisterMagickInfo(entry);
364   entry=SetMagickInfo("A");
365   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
366   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
367   entry->raw=MagickTrue;
368   entry->endian_support=MagickTrue;
369   entry->description=ConstantString("Raw alpha samples");
370   entry->module=ConstantString("RAW");
371   (void) RegisterMagickInfo(entry);
372   entry=SetMagickInfo("O");
373   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
374   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
375   entry->raw=MagickTrue;
376   entry->endian_support=MagickTrue;
377   entry->format_type=ExplicitFormatType;
378   entry->description=ConstantString("Raw opacity samples");
379   entry->module=ConstantString("RAW");
380   (void) RegisterMagickInfo(entry);
381   entry=SetMagickInfo("K");
382   entry->decoder=(DecodeImageHandler *) ReadRAWImage;
383   entry->encoder=(EncodeImageHandler *) WriteRAWImage;
384   entry->raw=MagickTrue;
385   entry->endian_support=MagickTrue;
386   entry->format_type=ExplicitFormatType;
387   entry->description=ConstantString("Raw black samples");
388   entry->module=ConstantString("RAW");
389   (void) RegisterMagickInfo(entry);
390   return(MagickImageCoderSignature);
391 }
392 \f
393 /*
394 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
395 %                                                                             %
396 %                                                                             %
397 %                                                                             %
398 %   U n r e g i s t e r R A W I m a g e                                       %
399 %                                                                             %
400 %                                                                             %
401 %                                                                             %
402 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
403 %
404 %  UnregisterRAWImage() removes format registrations made by the RAW module
405 %  from the list of supported formats.
406 %
407 %  The format of the UnregisterRAWImage method is:
408 %
409 %      UnregisterRAWImage(void)
410 %
411 */
412 ModuleExport void UnregisterRAWImage(void)
413 {
414   (void) UnregisterMagickInfo("R");
415   (void) UnregisterMagickInfo("C");
416   (void) UnregisterMagickInfo("G");
417   (void) UnregisterMagickInfo("M");
418   (void) UnregisterMagickInfo("B");
419   (void) UnregisterMagickInfo("Y");
420   (void) UnregisterMagickInfo("A");
421   (void) UnregisterMagickInfo("O");
422   (void) UnregisterMagickInfo("K");
423 }
424 \f
425 /*
426 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
427 %                                                                             %
428 %                                                                             %
429 %                                                                             %
430 %   W r i t e R A W I m a g e                                                 %
431 %                                                                             %
432 %                                                                             %
433 %                                                                             %
434 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
435 %
436 %  WriteRAWImage() writes an image to a file as raw intensity values.
437 %
438 %  The format of the WriteRAWImage method is:
439 %
440 %      MagickBooleanType WriteRAWImage(const ImageInfo *image_info,Image *image)
441 %
442 %  A description of each parameter follows.
443 %
444 %    o image_info: the image info.
445 %
446 %    o image:  The image.
447 %
448 */
449 static MagickBooleanType WriteRAWImage(const ImageInfo *image_info,Image *image)
450 {
451   long
452     y;
453
454   MagickOffsetType
455     scene;
456
457   QuantumInfo
458     *quantum_info;
459
460   QuantumType
461     quantum_type;
462
463   MagickBooleanType
464     status;
465
466   register const PixelPacket
467     *p;
468
469   ssize_t
470     count;
471
472   size_t
473     length;
474
475   unsigned char
476     *pixels;
477
478   /*
479     Open output image file.
480   */
481   assert(image_info != (const ImageInfo *) NULL);
482   assert(image_info->signature == MagickSignature);
483   assert(image != (Image *) NULL);
484   assert(image->signature == MagickSignature);
485   if (image->debug != MagickFalse)
486     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
487   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
488   if (status == MagickFalse)
489     return(status);
490   switch (*image->magick)
491   {
492     case 'A':
493     case 'a':
494     {
495       quantum_type=AlphaQuantum;
496       break;
497     }
498     case 'B':
499     case 'b':
500     {
501       quantum_type=BlueQuantum;
502       break;
503     }
504     case 'C':
505     case 'c':
506     {
507       quantum_type=CyanQuantum;
508       if (image->colorspace == CMYKColorspace)
509         break;
510       ThrowWriterException(ImageError,"ColorSeparatedImageRequired");
511     }
512     case 'g':
513     case 'G':
514     {
515       quantum_type=GreenQuantum;
516       break;
517     }
518     case 'I':
519     case 'i':
520     {
521       quantum_type=IndexQuantum;
522       break;
523     }
524     case 'K':
525     case 'k':
526     {
527       quantum_type=BlackQuantum;
528       if (image->colorspace == CMYKColorspace)
529         break;
530       ThrowWriterException(ImageError,"ColorSeparatedImageRequired");
531     }
532     case 'M':
533     case 'm':
534     {
535       quantum_type=MagentaQuantum;
536       if (image->colorspace == CMYKColorspace)
537         break;
538       ThrowWriterException(ImageError,"ColorSeparatedImageRequired");
539     }
540     case 'o':
541     case 'O':
542     {
543       quantum_type=OpacityQuantum;
544       break;
545     }
546     case 'R':
547     case 'r':
548     {
549       quantum_type=RedQuantum;
550       break;
551     }
552     case 'Y':
553     case 'y':
554     {
555       quantum_type=YellowQuantum;
556       if (image->colorspace == CMYKColorspace)
557         break;
558       ThrowWriterException(ImageError,"ColorSeparatedImageRequired");
559     }
560     default:
561     {
562       quantum_type=GrayQuantum;
563       break;
564     }
565   }
566   scene=0;
567   do
568   {
569     /*
570       Convert image to RAW raster pixels.
571     */
572     quantum_info=AcquireQuantumInfo(image_info,image);
573     if (quantum_info == (QuantumInfo *) NULL)
574       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
575     pixels=GetQuantumPixels(quantum_info);
576     for (y=0; y < (long) image->rows; y++)
577     {
578       p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
579       if (p == (const PixelPacket *) NULL)
580         break;
581       length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
582         quantum_type,pixels,&image->exception);
583       count=WriteBlob(image,length,pixels);
584       if (count != (ssize_t) length)
585         break;
586       if (image->previous == (Image *) NULL)
587         {
588           status=SetImageProgress(image,SaveImageTag,y,image->rows);
589           if (status == MagickFalse)
590             break;
591         }
592     }
593     quantum_info=DestroyQuantumInfo(quantum_info);
594     if (GetNextImageInList(image) == (Image *) NULL)
595       break;
596     image=SyncNextImageInList(image);
597     status=SetImageProgress(image,SaveImagesTag,scene++,
598       GetImageListLength(image));
599     if (status == MagickFalse)
600       break;
601   } while (image_info->adjoin != MagickFalse);
602   (void) CloseBlob(image);
603   return(MagickTrue);
604 }