root / ImageMagick / trunk / coders / rgb.c

Revision 12707, 46.5 kB (checked in by cristy, 2 days ago)
Line 
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%                            RRRR    GGGG  BBBB                               %
7%                            R   R  G      B   B                              %
8%                            RRRR   G  GG  BBBB                               %
9%                            R R    G   G  B   B                              %
10%                            R  R    GGG   BBBB                               %
11%                                                                             %
12%                                                                             %
13%                     Read/Write Raw RGB 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/pixel-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#include "magick/utility.h"
63
64/*
65  Forward declarations.
66*/
67static MagickBooleanType
68  WriteRGBImage(const ImageInfo *,Image *);
69
70/*
71%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72%                                                                             %
73%                                                                             %
74%                                                                             %
75%   R e a d R G B I m a g e                                                   %
76%                                                                             %
77%                                                                             %
78%                                                                             %
79%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80%
81%  ReadRGBImage() reads an image of raw RGB or RGBA samples and returns it. It
82%  allocates the memory necessary for the new Image structure and returns a
83%  pointer to the new image.
84%
85%  The format of the ReadRGBImage method is:
86%
87%      Image *ReadRGBImage(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*/
96static Image *ReadRGBImage(const ImageInfo *image_info,ExceptionInfo *exception)
97{
98  Image
99    *canvas_image,
100    *image;
101
102  long
103    y;
104
105  MagickBooleanType
106    status;
107
108  MagickOffsetType
109    scene;
110
111  QuantumInfo
112    *quantum_info;
113
114  QuantumType
115    quantum_type;
116
117  register const PixelPacket
118    *p;
119
120  register long
121    i,
122    x;
123
124  register PixelPacket
125    *q;
126
127  ssize_t
128    count;
129
130  size_t
131    length;
132
133  unsigned char
134    *pixels;
135
136  /*
137    Open image file.
138  */
139  assert(image_info != (const ImageInfo *) NULL);
140  assert(image_info->signature == MagickSignature);
141  if (image_info->debug != MagickFalse)
142    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
143      image_info->filename);
144  assert(exception != (ExceptionInfo *) NULL);
145  assert(exception->signature == MagickSignature);
146  image=AcquireImage(image_info);
147  if ((image->columns == 0) || (image->rows == 0))
148    ThrowReaderException(OptionError,"MustSpecifyImageSize");
149  if (image_info->interlace != PartitionInterlace)
150    {
151      status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
152      if (status == MagickFalse)
153        {
154          image=DestroyImageList(image);
155          return((Image *) NULL);
156        }
157      for (i=0; i < image->offset; i++)
158        if (ReadBlobByte(image) == EOF)
159          {
160            ThrowFileException(exception,CorruptImageError,
161              "UnexpectedEndOfFile",image->filename);
162            break;
163          }
164    }
165  /*
166    Create virtual canvas to support cropping (i.e. image.rgb[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_info=AcquireQuantumInfo(image_info,canvas_image);
172  pixels=GetQuantumPixels(quantum_info);
173  quantum_type=RGBQuantum;
174  if (LocaleCompare(image_info->magick,"RGBA") == 0)
175    {
176      quantum_type=RGBAQuantum;
177      image->matte=MagickTrue;
178    }
179  if (LocaleCompare(image_info->magick,"RGBO") == 0)
180    quantum_type=RGBOQuantum;
181  if (image_info->number_scenes != 0)
182    while (image->scene < image_info->scene)
183    {
184      /*
185        Skip to next image.
186      */
187      image->scene++;
188      length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
189      for (y=0; y < (long) image->rows; y++)
190      {
191        count=ReadBlob(image,length,pixels);
192        if (count != (ssize_t) length)
193          break;
194      }
195    }
196  count=0;
197  length=0;
198  scene=0;
199  do
200  {
201    /*
202      Read pixels to virtual canvas image then push to image.
203    */
204    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
205      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
206        break;
207    if ((SetImageExtent(image,0,0) == MagickFalse) ||
208        (SetImageExtent(canvas_image,0,0) == MagickFalse))
209      break;
210    switch (image_info->interlace)
211    {
212      case NoInterlace:
213      default:
214      {
215        /*
216          No interlacing:  RGBRGBRGBRGBRGBRGB...
217        */
218        if (scene == 0)
219          {
220            length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
221            count=ReadBlob(image,length,pixels);
222            if (count != (ssize_t) length)
223              break;
224          }
225        for (y=0; y < (long) image->extract_info.height; y++)
226        {
227          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
228          if (q == (PixelPacket *) NULL)
229            break;
230          length=ImportQuantumPixels(canvas_image,quantum_info,quantum_type,
231            pixels);
232          if (SyncImagePixels(canvas_image) == MagickFalse)
233            break;
234          if (((y-image->extract_info.y) >= 0) &&
235              ((y-image->extract_info.y) < (long) image->rows))
236            {
237              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
238                canvas_image->columns,1,exception);
239              q=SetImagePixels(image,0,y-image->extract_info.y,image->columns,
240                1);
241              if ((p == (const PixelPacket *) NULL) ||
242                  (q == (PixelPacket *) NULL))
243                break;
244              for (x=0; x < (long) image->columns; x++)
245              {
246                q->red=p->red;
247                q->green=p->green;
248                q->blue=p->blue;
249                if (image->matte != MagickFalse)
250                  q->opacity=p->opacity;
251                p++;
252                q++;
253              }
254              if (SyncImagePixels(image) == MagickFalse)
255                break;
256            }
257          if (image->previous == (Image *) NULL)
258            {
259              status=SetImageProgress(image,LoadImageTag,y,image->rows);
260              if (status == MagickFalse)
261                break;
262            }
263          count=ReadBlob(image,length,pixels);
264          if (count != (ssize_t) length)
265            break;
266        }
267        break;
268      }
269      case LineInterlace:
270      {
271        static QuantumType
272          quantum_types[4] =
273          {
274            RedQuantum,
275            GreenQuantum,
276            BlueQuantum,
277            OpacityQuantum
278          };
279
280        /*
281          Line interlacing:  RRR...GGG...BBB...RRR...GGG...BBB...
282        */
283        if (scene == 0)
284          {
285            length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
286            count=ReadBlob(image,length,pixels);
287            if (count != (ssize_t) length)
288              break;
289          }
290        for (y=0; y < (long) image->extract_info.height; y++)
291        {
292          for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
293          {
294            quantum_type=quantum_types[i];
295            q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
296            if (q == (PixelPacket *) NULL)
297              break;
298            length=ImportQuantumPixels(canvas_image,quantum_info,quantum_type,
299              pixels);
300            if (SyncImagePixels(canvas_image) == MagickFalse)
301              break;
302            if (((y-image->extract_info.y) >= 0) &&
303                ((y-image->extract_info.y) < (long) image->rows))
304              {
305                p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,
306                  0,canvas_image->columns,1,exception);
307                q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
308                  1);
309                if ((p == (const PixelPacket *) NULL) ||
310                    (q == (PixelPacket *) NULL))
311                  break;
312                for (x=0; x < (long) image->columns; x++)
313                {
314                  switch (quantum_type)
315                  {
316                    case RedQuantum: q->red=p->red; break;
317                    case GreenQuantum: q->green=p->green; break;
318                    case BlueQuantum: q->blue=p->blue; break;
319                    case OpacityQuantum: q->opacity=p->opacity; break;
320                    default: break;
321                  }
322                  p++;
323                  q++;
324                }
325                if (SyncImagePixels(image) == MagickFalse)
326                  break;
327              }
328            count=ReadBlob(image,length,pixels);
329            if (count != (ssize_t) length)
330              break;
331          }
332          if (image->previous == (Image *) NULL)
333            {
334              status=SetImageProgress(image,LoadImageTag,y,image->rows);
335              if (status == MagickFalse)
336                break;
337            }
338        }
339        break;
340      }
341      case PlaneInterlace:
342      {
343        /*
344          Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
345        */
346        if (scene == 0)
347          {
348            length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
349            count=ReadBlob(image,length,pixels);
350            if (count != (ssize_t) length)
351              break;
352          }
353        for (y=0; y < (long) image->extract_info.height; y++)
354        {
355          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
356          if (q == (PixelPacket *) NULL)
357            break;
358          length=ImportQuantumPixels(canvas_image,quantum_info,RedQuantum,
359            pixels);
360          if (SyncImagePixels(canvas_image) == MagickFalse)
361            break;
362          if (((y-image->extract_info.y) >= 0) &&
363              ((y-image->extract_info.y) < (long) image->rows))
364            {
365              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
366                canvas_image->columns,1,exception);
367              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
368                1);
369              if ((p == (const PixelPacket *) NULL) ||
370                  (q == (PixelPacket *) NULL))
371                break;
372              for (x=0; x < (long) image->columns; x++)
373              {
374                q->red=p->red;
375                p++;
376                q++;
377              }
378              if (SyncImagePixels(image) == MagickFalse)
379                break;
380            }
381          count=ReadBlob(image,length,pixels);
382          if (count != (ssize_t) length)
383            break;
384        }
385        if (image->previous == (Image *) NULL)
386          {
387            status=SetImageProgress(image,LoadImageTag,1,5);
388            if (status == MagickFalse)
389              break;
390          }
391        for (y=0; y < (long) image->extract_info.height; y++)
392        {
393          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
394          if (q == (PixelPacket *) NULL)
395            break;
396          length=ImportQuantumPixels(canvas_image,quantum_info,GreenQuantum,
397            pixels);
398          if (SyncImagePixels(canvas_image) == MagickFalse)
399            break;
400          if (((y-image->extract_info.y) >= 0) &&
401              ((y-image->extract_info.y) < (long) image->rows))
402            {
403              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
404                canvas_image->columns,1,exception);
405              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
406                1);
407              if ((p == (const PixelPacket *) NULL) ||
408                  (q == (PixelPacket *) NULL))
409                break;
410              for (x=0; x < (long) image->columns; x++)
411              {
412                q->green=p->green;
413                p++;
414                q++;
415              }
416              if (SyncImagePixels(image) == MagickFalse)
417                break;
418           }
419          count=ReadBlob(image,length,pixels);
420          if (count != (ssize_t) length)
421            break;
422        }
423        if (image->previous == (Image *) NULL)
424          {
425            status=SetImageProgress(image,LoadImageTag,2,5);
426            if (status == MagickFalse)
427              break;
428          }
429        for (y=0; y < (long) image->extract_info.height; y++)
430        {
431          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
432          if (q == (PixelPacket *) NULL)
433            break;
434          length=ImportQuantumPixels(canvas_image,quantum_info,BlueQuantum,
435            pixels);
436          if (SyncImagePixels(canvas_image) == MagickFalse)
437            break;
438          if (((y-image->extract_info.y) >= 0) &&
439              ((y-image->extract_info.y) < (long) image->rows))
440            {
441              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
442                canvas_image->columns,1,exception);
443              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
444                1);
445              if ((p == (const PixelPacket *) NULL) ||
446                  (q == (PixelPacket *) NULL))
447                break;
448              for (x=0; x < (long) image->columns; x++)
449              {
450                q->blue=p->blue;
451                p++;
452                q++;
453              }
454              if (SyncImagePixels(image) == MagickFalse)
455                break;
456            }
457          count=ReadBlob(image,length,pixels);
458          if (count != (ssize_t) length)
459            break;
460        }
461        if (image->previous == (Image *) NULL)
462          {
463            status=SetImageProgress(image,LoadImageTag,3,5);
464            if (status == MagickFalse)
465              break;
466          }
467        if (image->matte != MagickFalse)
468          {
469            for (y=0; y < (long) image->extract_info.height; y++)
470            {
471              q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
472              if (q == (PixelPacket *) NULL)
473                break;
474              length=ImportQuantumPixels(canvas_image,quantum_info,AlphaQuantum,
475                pixels);
476              if (SyncImagePixels(canvas_image) == MagickFalse)
477                break;
478              if (((y-image->extract_info.y) >= 0) &&
479                  ((y-image->extract_info.y) < (long) image->rows))
480                {
481                  p=AcquireImagePixels(canvas_image,
482                    canvas_image->extract_info.x,0,canvas_image->columns,1,
483                    exception);
484                  q=GetImagePixels(image,0,y-image->extract_info.y,
485                    image->columns,1);
486                  if ((p == (const PixelPacket *) NULL) ||
487                      (q == (PixelPacket *) NULL))
488                    break;
489                  for (x=0; x < (long) image->columns; x++)
490                  {
491                    q->opacity=p->opacity;
492                    p++;
493                    q++;
494                  }
495                  if (SyncImagePixels(image) == MagickFalse)
496                    break;
497                }
498              count=ReadBlob(image,length,pixels);
499              if (count != (ssize_t) length)
500                break;
501            }
502            if (image->previous == (Image *) NULL)
503              {
504                status=SetImageProgress(image,LoadImageTag,4,5);
505                if (status == MagickFalse)
506                  break;
507              }
508          }
509        if (image->previous == (Image *) NULL)
510          {
511            status=SetImageProgress(image,LoadImageTag,5,5);
512            if (status == MagickFalse)
513              break;
514          }
515        break;
516      }
517      case PartitionInterlace:
518      {
519        /*
520          Partition interlacing:  RRRRRR..., GGGGGG..., BBBBBB...
521        */
522        AppendImageFormat("R",image->filename);
523        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
524        if (status == MagickFalse)
525          {
526            canvas_image=DestroyImageList(canvas_image);
527            image=DestroyImageList(image);
528            return((Image *) NULL);
529          }
530        for (i=0; i < image->offset; i++)
531          if (ReadBlobByte(image) == EOF)
532            {
533              ThrowFileException(exception,CorruptImageError,
534                "UnexpectedEndOfFile",image->filename);
535              break;
536            }
537        length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
538        for (i=0; i < (long) scene; i++)
539          for (y=0; y < (long) image->extract_info.height; y++)
540            if (ReadBlob(image,length,pixels) != (ssize_t) length)
541              {
542                ThrowFileException(exception,CorruptImageError,
543                  "UnexpectedEndOfFile",image->filename);
544                break;
545              }
546        count=ReadBlob(image,length,pixels);
547        if (count != (ssize_t) length)
548          break;
549        for (y=0; y < (long) image->extract_info.height; y++)
550        {
551          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
552          if (q == (PixelPacket *) NULL)
553            break;
554          length=ImportQuantumPixels(canvas_image,quantum_info,RedQuantum,
555            pixels);
556          if (SyncImagePixels(canvas_image) == MagickFalse)
557            break;
558          if (((y-image->extract_info.y) >= 0) &&
559              ((y-image->extract_info.y) < (long) image->rows))
560            {
561              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
562                canvas_image->columns,1,exception);
563              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
564                1);
565              if ((p == (const PixelPacket *) NULL) ||
566                  (q == (PixelPacket *) NULL))
567                break;
568              for (x=0; x < (long) image->columns; x++)
569              {
570                q->red=p->red;
571                p++;
572                q++;
573              }
574              if (SyncImagePixels(image) == MagickFalse)
575                break;
576            }
577          count=ReadBlob(image,length,pixels);
578          if (count != (ssize_t) length)
579            break;
580        }
581        if (image->previous == (Image *) NULL)
582          {
583            status=SetImageProgress(image,LoadImageTag,1,5);
584            if (status == MagickFalse)
585              break;
586          }
587        (void) CloseBlob(image);
588        AppendImageFormat("G",image->filename);
589        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
590        if (status == MagickFalse)
591          {
592            canvas_image=DestroyImageList(canvas_image);
593            image=DestroyImageList(image);
594            return((Image *) NULL);
595          }
596        length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
597        for (i=0; i < (long) scene; i++)
598          for (y=0; y < (long) image->extract_info.height; y++)
599            if (ReadBlob(image,length,pixels) != (ssize_t) length)
600              {
601                ThrowFileException(exception,CorruptImageError,
602                  "UnexpectedEndOfFile",image->filename);
603                break;
604              }
605        count=ReadBlob(image,length,pixels);
606        if (count != (ssize_t) length)
607          break;
608        for (y=0; y < (long) image->extract_info.height; y++)
609        {
610          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
611          if (q == (PixelPacket *) NULL)
612            break;
613          length=ImportQuantumPixels(canvas_image,quantum_info,GreenQuantum,
614            pixels);
615          if (SyncImagePixels(canvas_image) == MagickFalse)
616            break;
617          if (((y-image->extract_info.y) >= 0) &&
618              ((y-image->extract_info.y) < (long) image->rows))
619            {
620              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
621                canvas_image->columns,1,exception);
622              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
623                1);
624              if ((p == (const PixelPacket *) NULL) ||
625                  (q == (PixelPacket *) NULL))
626                break;
627              for (x=0; x < (long) image->columns; x++)
628              {
629                q->green=p->green;
630                p++;
631                q++;
632              }
633              if (SyncImagePixels(image) == MagickFalse)
634                break;
635           }
636          count=ReadBlob(image,length,pixels);
637          if (count != (ssize_t) length)
638            break;
639        }
640        if (image->previous == (Image *) NULL)
641          {
642            status=SetImageProgress(image,LoadImageTag,2,5);
643            if (status == MagickFalse)
644              break;
645          }
646        (void) CloseBlob(image);
647        AppendImageFormat("B",image->filename);
648        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
649        if (status == MagickFalse)
650          {
651            canvas_image=DestroyImageList(canvas_image);
652            image=DestroyImageList(image);
653            return((Image *) NULL);
654          }
655        length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
656        for (i=0; i < (long) scene; i++)
657          for (y=0; y < (long) image->extract_info.height; y++)
658            if (ReadBlob(image,length,pixels) != (ssize_t) length)
659              {
660                ThrowFileException(exception,CorruptImageError,
661                  "UnexpectedEndOfFile",image->filename);
662                break;
663              }
664        count=ReadBlob(image,length,pixels);
665        if (count != (ssize_t) length)
666          break;
667        for (y=0; y < (long) image->extract_info.height; y++)
668        {
669          q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
670          if (q == (PixelPacket *) NULL)
671            break;
672          length=ImportQuantumPixels(canvas_image,quantum_info,BlueQuantum,
673            pixels);
674          if (SyncImagePixels(canvas_image) == MagickFalse)
675            break;
676          if (((y-image->extract_info.y) >= 0) &&
677              ((y-image->extract_info.y) < (long) image->rows))
678            {
679              p=AcquireImagePixels(canvas_image,canvas_image->extract_info.x,0,
680                canvas_image->columns,1,exception);
681              q=GetImagePixels(image,0,y-image->extract_info.y,image->columns,
682                1);
683              if ((p == (const PixelPacket *) NULL) ||
684                  (q == (PixelPacket *) NULL))
685                break;
686              for (x=0; x < (long) image->columns; x++)
687              {
688                q->blue=p->blue;
689                p++;
690                q++;
691              }
692              if (SyncImagePixels(image) == MagickFalse)
693                break;
694           }
695          count=ReadBlob(image,length,pixels);
696          if (count != (ssize_t) length)
697            break;
698        }
699        if (image->previous == (Image *) NULL)
700          {
701            status=SetImageProgress(image,LoadImageTag,3,5);
702            if (status == MagickFalse)
703              break;
704          }
705        if (image->matte != MagickFalse)
706          {
707            (void) CloseBlob(image);
708            AppendImageFormat("A",image->filename);
709            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
710            if (status == MagickFalse)
711              {
712                canvas_image=DestroyImageList(canvas_image);
713                image=DestroyImageList(image);
714                return((Image *) NULL);
715              }
716            length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
717            for (i=0; i < (long) scene; i++)
718              for (y=0; y < (long) image->extract_info.height; y++)
719                if (ReadBlob(image,length,pixels) != (ssize_t) length)
720                  {
721                    ThrowFileException(exception,CorruptImageError,
722                      "UnexpectedEndOfFile",image->filename);
723                    break;
724                  }
725            count=ReadBlob(image,length,pixels);
726            if (count != (ssize_t) length)
727              break;
728            for (y=0; y < (long) image->extract_info.height; y++)
729            {
730              q=GetImagePixels(canvas_image,0,0,canvas_image->columns,1);
731              if (q == (PixelPacket *) NULL)
732                break;
733              length=ImportQuantumPixels(canvas_image,quantum_info,BlueQuantum,
734                pixels);
735              if (SyncImagePixels(canvas_image) == MagickFalse)
736                break;
737              if (((y-image->extract_info.y) >= 0) &&
738                  ((y-image->extract_info.y) < (long) image->rows))
739                {
740                  p=AcquireImagePixels(canvas_image,
741                    canvas_image->extract_info.x,0,canvas_image->columns,1,
742                    exception);
743                  q=GetImagePixels(image,0,y-image->extract_info.y,
744                    image->columns,1);
745                  if ((p == (const PixelPacket *) NULL) ||
746                      (q == (PixelPacket *) NULL))
747                    break;
748                  for (x=0; x < (long) image->columns; x++)
749                  {
750                    q->opacity=p->opacity;
751                    p++;
752                    q++;
753                  }
754                  if (SyncImagePixels(image) == MagickFalse)
755                    break;
756               }
757              count=ReadBlob(image,length,pixels);
758              if (count != (ssize_t) length)
759                break;
760            }
761            if (image->previous == (Image *) NULL)
762              {
763                status=SetImageProgress(image,LoadImageTag,4,5);
764                if (status == MagickFalse)
765                  break;
766              }
767          }
768        if (image->previous == (Image *) NULL)
769          {
770            status=SetImageProgress(image,LoadImageTag,5,5);
771            if (status == MagickFalse)
772              break;
773          }
774        break;
775      }
776    }
777    SetQuantumImageType(image,quantum_type);
778    /*
779      Proceed to next image.
780    */
781    if (image_info->number_scenes != 0)
782      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
783        break;
784    if (count == (ssize_t) length)
785      {
786        /*
787          Allocate next image structure.
788        */
789        AcquireNextImage(image_info,image);
790        if (GetNextImageInList(image) == (Image *) NULL)
791          {
792            image=DestroyImageList(image);
793            return((Image *) NULL);
794          }
795        image=SyncNextImageInList(image);
796        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
797          GetBlobSize(image));
798        if (status == MagickFalse)
799          break;
800      }
801    scene++;
802  } while (count == (ssize_t) length);
803  InheritException(exception,&image->exception);
804  quantum_info=DestroyQuantumInfo(quantum_info);
805  canvas_image=DestroyImage(canvas_image);
806  (void) CloseBlob(image);
807  return(GetFirstImageInList(image));
808}
809
810/*
811%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
812%                                                                             %
813%                                                                             %
814%                                                                             %
815%   R e g i s t e r R G B I m a g e                                           %
816%                                                                             %
817%                                                                             %
818%                                                                             %
819%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
820%
821%  RegisterRGBImage() adds attributes for the RGB or RGBA image format to
822%  the list of supported formats.  The attributes include the image format
823%  tag, a method to read and/or write the format, whether the format
824%  supports the saving of more than one frame to the same file or blob,
825%  whether the format supports native in-memory I/O, and a brief
826%  description of the format.
827%
828%  The format of the RegisterRGBImage method is:
829%
830%      unsigned long RegisterRGBImage(void)
831%
832*/
833ModuleExport unsigned long RegisterRGBImage(void)
834{
835  MagickInfo
836    *entry;
837
838  entry=SetMagickInfo("RGB");
839  entry->decoder=(DecodeImageHandler *) ReadRGBImage;
840  entry->encoder=(EncodeImageHandler *) WriteRGBImage;
841  entry->raw=MagickTrue;
842  entry->endian_support=MagickTrue;
843  entry->description=ConstantString("Raw red, green, and blue samples");
844  entry->module=ConstantString("RGB");
845  (void) RegisterMagickInfo(entry);
846  entry=SetMagickInfo("RGBA");
847  entry->decoder=(DecodeImageHandler *) ReadRGBImage;
848  entry->encoder=(EncodeImageHandler *) WriteRGBImage;
849  entry->raw=MagickTrue;
850  entry->endian_support=MagickTrue;
851  entry->description=ConstantString("Raw red, green, blue, and alpha samples");
852  entry->module=ConstantString("RGB");
853  (void) RegisterMagickInfo(entry);
854  entry=SetMagickInfo("RGBO");
855  entry->decoder=(DecodeImageHandler *) ReadRGBImage;
856  entry->encoder=(EncodeImageHandler *) WriteRGBImage;
857  entry->raw=MagickTrue;
858  entry->endian_support=MagickTrue;
859  entry->description=ConstantString("Raw red, green, blue, and opacity "
860    "samples");
861  entry->module=ConstantString("RGB");
862  (void) RegisterMagickInfo(entry);
863  return(MagickImageCoderSignature);
864}
865
866/*
867%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868%                                                                             %
869%                                                                             %
870%                                                                             %
871%   U n r e g i s t e r R G B I m a g e                                       %
872%                                                                             %
873%                                                                             %
874%                                                                             %
875%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
876%
877%  UnregisterRGBImage() removes format registrations made by the
878%  RGB module from the list of supported formats.
879%
880%  The format of the UnregisterRGBImage method is:
881%
882%      UnregisterRGBImage(void)
883%
884*/
885ModuleExport void UnregisterRGBImage(void)
886{
887  (void) UnregisterMagickInfo("RGBO");
888  (void) UnregisterMagickInfo("RGBA");
889  (void) UnregisterMagickInfo("RGB");
890}
891
892/*
893%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
894%                                                                             %
895%                                                                             %
896%                                                                             %
897%   W r i t e R G B I m a g e                                                 %
898%                                                                             %
899%                                                                             %
900%                                                                             %
901%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902%
903%  WriteRGBImage() writes an image to a file in the RGB or RGBA rasterfile
904%  format.
905%
906%  The format of the WriteRGBImage method is:
907%
908%      MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image)
909%
910%  A description of each parameter follows.
911%
912%    o image_info: the image info.
913%
914%    o image:  The image.
915%
916*/
917static MagickBooleanType WriteRGBImage(const ImageInfo *image_info,Image *image)
918{
919  long
920    y;
921
922  MagickBooleanType
923    status;
924
925  MagickOffsetType
926    scene;
927
928  QuantumInfo
929    *quantum_info;
930
931  QuantumType
932    quantum_type;
933
934  register const PixelPacket
935    *p;
936
937  ssize_t
938    count;
939
940  size_t
941    length;
942
943  unsigned char
944    *pixels;
945
946  /*
947    Allocate memory for pixels.
948  */
949  assert(image_info != (const ImageInfo *) NULL);
950  assert(image_info->signature == MagickSignature);
951  assert(image != (Image *) NULL);
952  assert(image->signature == MagickSignature);
953  if (image->debug != MagickFalse)
954    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
955  if (image_info->interlace != PartitionInterlace)
956    {
957      /*
958        Open output image file.
959      */
960      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
961      if (status == MagickFalse)
962        return(status);
963    }
964  quantum_type=RGBQuantum;
965  if (LocaleCompare(image_info->magick,"RGBA") == 0)
966    {
967      quantum_type=RGBAQuantum;
968      image->matte=MagickTrue;
969    }
970  if (LocaleCompare(image_info->magick,"RGBO") == 0)
971    {
972      quantum_type=RGBOQuantum;
973      image->matte=MagickTrue;
974    }
975  scene=0;
976  do
977  {
978    /*
979      Convert MIFF to RGB raster pixels.
980    */
981    if (image->colorspace != RGBColorspace)
982      (void) SetImageColorspace(image,RGBColorspace);
983    if ((LocaleCompare(image_info->magick,"RGBA") == 0) &&
984        (image->matte == MagickFalse))
985      (void) SetImageAlphaChannel(image,ResetAlphaChannel);
986    quantum_info=AcquireQuantumInfo(image_info,image);
987    pixels=GetQuantumPixels(quantum_info);
988    switch (i