root / ImageMagick / trunk / coders / raw.c

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