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