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