]> granicus.if.org Git - imagemagick/blob - coders/ycbcr.c
(no commit message)
[imagemagick] / coders / ycbcr.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                     Y   Y   YYYC  BBBB    YYYC  RRRR                        %
7 %                      Y Y   C      B   B  C      R   R                       %
8 %                       Y    C      BBBB   C      RRRR                        %
9 %                       Y    C      B   B  C      R  R                        %
10 %                       Y     YYYC  BBBB    YYYC  R   R                       %
11 %                                                                             %
12 %                                                                             %
13 %                     Read/Write Raw YCbCr 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 "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/static.h"
60 #include "MagickCore/statistic.h"
61 #include "MagickCore/string_.h"
62 #include "MagickCore/module.h"
63 #include "MagickCore/utility.h"
64 \f
65 /*
66   Forward declarations.
67 */
68 static MagickBooleanType
69   WriteYCBCRImage(const ImageInfo *,Image *,ExceptionInfo *);
70 \f
71 /*
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 %                                                                             %
74 %                                                                             %
75 %                                                                             %
76 %   R e a d Y C b C r I m a g e                                               %
77 %                                                                             %
78 %                                                                             %
79 %                                                                             %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81 %
82 %  ReadYCBCRImage() reads an image of raw YCbCr or YCbCrA samples and returns
83 %  it. It allocates the memory necessary for the new Image structure and
84 %  returns a pointer to the new image.
85 %
86 %  The format of the ReadYCBCRImage method is:
87 %
88 %      Image *ReadYCBCRImage(const ImageInfo *image_info,
89 %        ExceptionInfo *exception)
90 %
91 %  A description of each parameter follows:
92 %
93 %    o image_info: the image info.
94 %
95 %    o exception: return any errors or warnings in this structure.
96 %
97 */
98 static Image *ReadYCBCRImage(const ImageInfo *image_info,
99   ExceptionInfo *exception)
100 {
101   Image
102     *canvas_image,
103     *image;
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 Quantum
118     *p;
119
120   register ssize_t
121     i,
122     x;
123
124   register Quantum
125     *q;
126
127   size_t
128     length;
129
130   ssize_t
131     count,
132     y;
133
134   unsigned char
135     *pixels;
136
137   /*
138     Open image file.
139   */
140   assert(image_info != (const ImageInfo *) NULL);
141   assert(image_info->signature == MagickSignature);
142   if (image_info->debug != MagickFalse)
143     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
144       image_info->filename);
145   assert(exception != (ExceptionInfo *) NULL);
146   assert(exception->signature == MagickSignature);
147   image=AcquireImage(image_info,exception);
148   if ((image->columns == 0) || (image->rows == 0))
149     ThrowReaderException(OptionError,"MustSpecifyImageSize");
150   image->colorspace=YCbCrColorspace;
151   if (image_info->interlace != PartitionInterlace)
152     {
153       status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
154       if (status == MagickFalse)
155         {
156           image=DestroyImageList(image);
157           return((Image *) NULL);
158         }
159       if (DiscardBlobBytes(image,image->offset) == MagickFalse)
160         ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
161           image->filename);
162     }
163   /*
164     Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
165   */
166   canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
167     exception);
168   (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
169   quantum_info=AcquireQuantumInfo(image_info,canvas_image);
170   if (quantum_info == (QuantumInfo *) NULL)
171     ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
172   pixels=GetQuantumPixels(quantum_info);
173   quantum_type=RGBQuantum;
174   if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
175     {
176       quantum_type=RGBAQuantum;
177       image->matte=MagickTrue;
178     }
179   if (image_info->number_scenes != 0)
180     while (image->scene < image_info->scene)
181     {
182       /*
183         Skip to next image.
184       */
185       image->scene++;
186       length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
187       for (y=0; y < (ssize_t) image->rows; y++)
188       {
189         count=ReadBlob(image,length,pixels);
190         if (count != (ssize_t) length)
191           break;
192       }
193     }
194   count=0;
195   length=0;
196   scene=0;
197   do
198   {
199     /*
200       Read pixels to virtual canvas image then push to image.
201     */
202     if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
203       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
204         break;
205     image->colorspace=YCbCrColorspace;
206     switch (image_info->interlace)
207     {
208       case NoInterlace:
209       default:
210       {
211         /*
212           No interlacing:  YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
213         */
214         if (scene == 0)
215           {
216             length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
217             count=ReadBlob(image,length,pixels);
218           }
219         for (y=0; y < (ssize_t) image->extract_info.height; y++)
220         {
221           if (count != (ssize_t) length)
222             {
223               ThrowFileException(exception,CorruptImageError,
224                 "UnexpectedEndOfFile",image->filename);
225               break;
226             }
227           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
228             exception);
229           if (q == (Quantum *) NULL)
230             break;
231           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
232             quantum_info,quantum_type,pixels,exception);
233           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
234             break;
235           if (((y-image->extract_info.y) >= 0) && 
236               ((y-image->extract_info.y) < (ssize_t) image->rows))
237             {
238               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
239                 canvas_image->columns,1,exception);
240               q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
241                 image->columns,1,exception);
242               if ((p == (const Quantum *) NULL) ||
243                   (q == (Quantum *) NULL))
244                 break;
245               for (x=0; x < (ssize_t) image->columns; x++)
246               {
247                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
248                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
249                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
250                 if (image->matte != MagickFalse)
251                   SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
252                 p+=GetPixelChannels(canvas_image);
253                 q+=GetPixelChannels(image);
254               }
255               if (SyncAuthenticPixels(image,exception) == MagickFalse)
256                 break;
257             }
258           if (image->previous == (Image *) NULL)
259             {
260               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
261                 image->rows);
262               if (status == MagickFalse)
263                 break;
264             }
265           count=ReadBlob(image,length,pixels);
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:  YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
282         */
283         if (scene == 0)
284           {
285             length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
286             count=ReadBlob(image,length,pixels);
287           }
288         for (y=0; y < (ssize_t) image->extract_info.height; y++)
289         {
290           for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
291           {
292             if (count != (ssize_t) length)
293               {
294                 ThrowFileException(exception,CorruptImageError,
295                   "UnexpectedEndOfFile",image->filename);
296                 break;
297               }
298             quantum_type=quantum_types[i];
299             q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
300               exception);
301             if (q == (Quantum *) NULL)
302               break;
303             length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
304               quantum_info,quantum_type,pixels,exception);
305             if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
306               break;
307             if (((y-image->extract_info.y) >= 0) && 
308                 ((y-image->extract_info.y) < (ssize_t) image->rows))
309               {
310                 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
311                   0,canvas_image->columns,1,exception);
312                 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
313                   image->columns,1,exception);
314                 if ((p == (const Quantum *) NULL) ||
315                     (q == (Quantum *) NULL))
316                   break;
317                 for (x=0; x < (ssize_t) image->columns; x++)
318                 {
319                   switch (quantum_type)
320                   {
321                     case RedQuantum:
322                     {
323                       SetPixelRed(image,GetPixelRed(canvas_image,p),q);
324                       break;
325                     }
326                     case GreenQuantum:
327                     {
328                       SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
329                       break;
330                     }
331                     case BlueQuantum:
332                     {
333                       SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
334                       break;
335                     }
336                     case OpacityQuantum:
337                     {
338                       SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
339                       break;
340                     }
341                     default:
342                       break;
343                   }
344                   p+=GetPixelChannels(canvas_image);
345                   q+=GetPixelChannels(image);
346                 }
347                 if (SyncAuthenticPixels(image,exception) == MagickFalse)
348                   break;
349               }
350             count=ReadBlob(image,length,pixels);
351           }
352           if (image->previous == (Image *) NULL)
353             {
354               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
355                 image->rows);
356               if (status == MagickFalse)
357                 break;
358             }
359         }
360         break;
361       }
362       case PlaneInterlace:
363       {
364         /*
365           Plane interlacing:  YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
366         */
367         if (scene == 0)
368           {
369             length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
370             count=ReadBlob(image,length,pixels);
371           }
372         for (y=0; y < (ssize_t) image->extract_info.height; y++)
373         {
374           if (count != (ssize_t) length)
375             {
376               ThrowFileException(exception,CorruptImageError,
377                 "UnexpectedEndOfFile",image->filename);
378               break;
379             }
380           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
381             exception);
382           if (q == (Quantum *) NULL)
383             break;
384           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
385             quantum_info,RedQuantum,pixels,exception);
386           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
387             break;
388           if (((y-image->extract_info.y) >= 0) && 
389               ((y-image->extract_info.y) < (ssize_t) image->rows))
390             {
391               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
392                 canvas_image->columns,1,exception);
393               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
394                 image->columns,1,exception);
395               if ((p == (const Quantum *) NULL) ||
396                   (q == (Quantum *) NULL))
397                 break;
398               for (x=0; x < (ssize_t) image->columns; x++)
399               {
400                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
401                 p+=GetPixelChannels(canvas_image);
402                 q+=GetPixelChannels(image);
403               }
404               if (SyncAuthenticPixels(image,exception) == MagickFalse)
405                 break;
406             }
407           count=ReadBlob(image,length,pixels);
408         }
409         if (image->previous == (Image *) NULL)
410           {
411             status=SetImageProgress(image,LoadImageTag,1,5);
412             if (status == MagickFalse)
413               break;
414           }
415         for (y=0; y < (ssize_t) image->extract_info.height; y++)
416         {
417           if (count != (ssize_t) length)
418             {
419               ThrowFileException(exception,CorruptImageError,
420                 "UnexpectedEndOfFile",image->filename);
421               break;
422             }
423           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
424             exception);
425           if (q == (Quantum *) NULL)
426             break;
427           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
428             quantum_info,GreenQuantum,pixels,exception);
429           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
430             break;
431           if (((y-image->extract_info.y) >= 0) && 
432               ((y-image->extract_info.y) < (ssize_t) image->rows))
433             {
434               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
435                 canvas_image->columns,1,exception);
436               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
437                 image->columns,1,exception);
438               if ((p == (const Quantum *) NULL) ||
439                   (q == (Quantum *) NULL))
440                 break;
441               for (x=0; x < (ssize_t) image->columns; x++)
442               {
443                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
444                 p+=GetPixelChannels(canvas_image);
445                 q+=GetPixelChannels(image);
446               }
447               if (SyncAuthenticPixels(image,exception) == MagickFalse)
448                 break;
449            }
450           count=ReadBlob(image,length,pixels);
451         }
452         if (image->previous == (Image *) NULL)
453           {
454             status=SetImageProgress(image,LoadImageTag,2,5);
455             if (status == MagickFalse)
456               break;
457           }
458         for (y=0; y < (ssize_t) image->extract_info.height; y++)
459         {
460           if (count != (ssize_t) length)
461             {
462               ThrowFileException(exception,CorruptImageError,
463                 "UnexpectedEndOfFile",image->filename);
464               break;
465             }
466           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
467             exception);
468           if (q == (Quantum *) NULL)
469             break;
470           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
471             quantum_info,BlueQuantum,pixels,exception);
472           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
473             break;
474           if (((y-image->extract_info.y) >= 0) && 
475               ((y-image->extract_info.y) < (ssize_t) image->rows))
476             {
477               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
478                 canvas_image->columns,1,exception);
479               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
480                 image->columns,1,exception);
481               if ((p == (const Quantum *) NULL) ||
482                   (q == (Quantum *) NULL))
483                 break;
484               for (x=0; x < (ssize_t) image->columns; x++)
485               {
486                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
487                 p+=GetPixelChannels(canvas_image);
488                 q+=GetPixelChannels(image);
489               }
490               if (SyncAuthenticPixels(image,exception) == MagickFalse)
491                 break;
492             }
493           count=ReadBlob(image,length,pixels);
494         }
495         if (image->previous == (Image *) NULL)
496           {
497             status=SetImageProgress(image,LoadImageTag,3,5);
498             if (status == MagickFalse)
499               break;
500           }
501         if (image->matte != MagickFalse)
502           {
503             for (y=0; y < (ssize_t) image->extract_info.height; y++)
504             {
505               if (count != (ssize_t) length)
506                 {
507                   ThrowFileException(exception,CorruptImageError,
508                     "UnexpectedEndOfFile",image->filename);
509                   break;
510                 }
511               q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
512                 exception);
513               if (q == (Quantum *) NULL)
514                 break;
515               length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
516                 quantum_info,AlphaQuantum,pixels,exception);
517               if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
518                 break;
519               if (((y-image->extract_info.y) >= 0) && 
520                   ((y-image->extract_info.y) < (ssize_t) image->rows))
521                 {
522                   p=GetVirtualPixels(canvas_image,
523                     canvas_image->extract_info.x,0,canvas_image->columns,1,
524                     exception);
525                   q=GetAuthenticPixels(image,0,y-image->extract_info.y,
526                     image->columns,1,exception);
527                   if ((p == (const Quantum *) NULL) ||
528                       (q == (Quantum *) NULL))
529                     break;
530                   for (x=0; x < (ssize_t) image->columns; x++)
531                   {
532                     SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
533                     p+=GetPixelChannels(canvas_image);
534                     q+=GetPixelChannels(image);
535                   }
536                   if (SyncAuthenticPixels(image,exception) == MagickFalse)
537                     break;
538                 }
539               count=ReadBlob(image,length,pixels);
540             }
541             if (image->previous == (Image *) NULL)
542               {
543                 status=SetImageProgress(image,LoadImageTag,4,5);
544                 if (status == MagickFalse)
545                   break;
546               }
547           }
548         if (image->previous == (Image *) NULL)
549           {
550             status=SetImageProgress(image,LoadImageTag,5,5);
551             if (status == MagickFalse)
552               break;
553           }
554         break;
555       }
556       case PartitionInterlace:
557       {
558         /*
559           Partition interlacing:  YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
560         */
561         AppendImageFormat("Y",image->filename);
562         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
563         if (status == MagickFalse)
564           {
565             canvas_image=DestroyImageList(canvas_image);
566             image=DestroyImageList(image);
567             return((Image *) NULL);
568           }
569         if (DiscardBlobBytes(image,image->offset) == MagickFalse)
570           ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
571             image->filename);
572         length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
573         for (i=0; i < (ssize_t) scene; i++)
574           for (y=0; y < (ssize_t) image->extract_info.height; y++)
575             if (ReadBlob(image,length,pixels) != (ssize_t) length)
576               {
577                 ThrowFileException(exception,CorruptImageError,
578                   "UnexpectedEndOfFile",image->filename);
579                 break;
580               }
581         count=ReadBlob(image,length,pixels);
582         for (y=0; y < (ssize_t) image->extract_info.height; y++)
583         {
584           if (count != (ssize_t) length)
585             {
586               ThrowFileException(exception,CorruptImageError,
587                 "UnexpectedEndOfFile",image->filename);
588               break;
589             }
590           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
591             exception);
592           if (q == (Quantum *) NULL)
593             break;
594           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
595             quantum_info,RedQuantum,pixels,exception);
596           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
597             break;
598           if (((y-image->extract_info.y) >= 0) && 
599               ((y-image->extract_info.y) < (ssize_t) image->rows))
600             {
601               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
602                 canvas_image->columns,1,exception);
603               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
604                 image->columns,1,exception);
605               if ((p == (const Quantum *) NULL) ||
606                   (q == (Quantum *) NULL))
607                 break;
608               for (x=0; x < (ssize_t) image->columns; x++)
609               {
610                 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
611                 p+=GetPixelChannels(canvas_image);
612                 q+=GetPixelChannels(image);
613               }
614               if (SyncAuthenticPixels(image,exception) == MagickFalse)
615                 break;
616             }
617           count=ReadBlob(image,length,pixels);
618         }
619         if (image->previous == (Image *) NULL)
620           {
621             status=SetImageProgress(image,LoadImageTag,1,5);
622             if (status == MagickFalse)
623               break;
624           }
625         (void) CloseBlob(image);
626         AppendImageFormat("Cb",image->filename);
627         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
628         if (status == MagickFalse)
629           {
630             canvas_image=DestroyImageList(canvas_image);
631             image=DestroyImageList(image);
632             return((Image *) NULL);
633           }
634         length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
635         for (i=0; i < (ssize_t) scene; i++)
636           for (y=0; y < (ssize_t) image->extract_info.height; y++)
637             if (ReadBlob(image,length,pixels) != (ssize_t) length)
638               {
639                 ThrowFileException(exception,CorruptImageError,
640                   "UnexpectedEndOfFile",image->filename);
641                 break;
642               }
643         count=ReadBlob(image,length,pixels);
644         for (y=0; y < (ssize_t) image->extract_info.height; y++)
645         {
646           if (count != (ssize_t) length)
647             {
648               ThrowFileException(exception,CorruptImageError,
649                 "UnexpectedEndOfFile",image->filename);
650               break;
651             }
652           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
653             exception);
654           if (q == (Quantum *) NULL)
655             break;
656           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
657             quantum_info,GreenQuantum,pixels,exception);
658           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
659             break;
660           if (((y-image->extract_info.y) >= 0) && 
661               ((y-image->extract_info.y) < (ssize_t) image->rows))
662             {
663               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
664                 canvas_image->columns,1,exception);
665               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
666                 image->columns,1,exception);
667               if ((p == (const Quantum *) NULL) ||
668                   (q == (Quantum *) NULL))
669                 break;
670               for (x=0; x < (ssize_t) image->columns; x++)
671               {
672                 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
673                 p+=GetPixelChannels(canvas_image);
674                 q+=GetPixelChannels(image);
675               }
676               if (SyncAuthenticPixels(image,exception) == MagickFalse)
677                 break;
678            }
679           count=ReadBlob(image,length,pixels);
680         }
681         if (image->previous == (Image *) NULL)
682           {
683             status=SetImageProgress(image,LoadImageTag,2,5);
684             if (status == MagickFalse)
685               break;
686           }
687         (void) CloseBlob(image);
688         AppendImageFormat("Cr",image->filename);
689         status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
690         if (status == MagickFalse)
691           {
692             canvas_image=DestroyImageList(canvas_image);
693             image=DestroyImageList(image);
694             return((Image *) NULL);
695           }
696         length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
697         for (i=0; i < (ssize_t) scene; i++)
698           for (y=0; y < (ssize_t) image->extract_info.height; y++)
699             if (ReadBlob(image,length,pixels) != (ssize_t) length)
700               {
701                 ThrowFileException(exception,CorruptImageError,
702                   "UnexpectedEndOfFile",image->filename);
703                 break;
704               }
705         count=ReadBlob(image,length,pixels);
706         for (y=0; y < (ssize_t) image->extract_info.height; y++)
707         {
708           if (count != (ssize_t) length)
709             {
710               ThrowFileException(exception,CorruptImageError,
711                 "UnexpectedEndOfFile",image->filename);
712               break;
713             }
714           q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
715             exception);
716           if (q == (Quantum *) NULL)
717             break;
718           length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
719             quantum_info,BlueQuantum,pixels,exception);
720           if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
721             break;
722           if (((y-image->extract_info.y) >= 0) && 
723               ((y-image->extract_info.y) < (ssize_t) image->rows))
724             {
725               p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
726                 canvas_image->columns,1,exception);
727               q=GetAuthenticPixels(image,0,y-image->extract_info.y,
728                 image->columns,1,exception);
729               if ((p == (const Quantum *) NULL) ||
730                   (q == (Quantum *) NULL))
731                 break;
732               for (x=0; x < (ssize_t) image->columns; x++)
733               {
734                 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
735                 p+=GetPixelChannels(canvas_image);
736                 q+=GetPixelChannels(image);
737               }
738               if (SyncAuthenticPixels(image,exception) == MagickFalse)
739                 break;
740            }
741           count=ReadBlob(image,length,pixels);
742         }
743         if (image->previous == (Image *) NULL)
744           {
745             status=SetImageProgress(image,LoadImageTag,3,5);
746             if (status == MagickFalse)
747               break;
748           }
749         if (image->matte != MagickFalse)
750           {
751             (void) CloseBlob(image);
752             AppendImageFormat("A",image->filename);
753             status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
754             if (status == MagickFalse)
755               {
756                 canvas_image=DestroyImageList(canvas_image);
757                 image=DestroyImageList(image);
758                 return((Image *) NULL);
759               }
760             length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
761             for (i=0; i < (ssize_t) scene; i++)
762               for (y=0; y < (ssize_t) image->extract_info.height; y++)
763                 if (ReadBlob(image,length,pixels) != (ssize_t) length)
764                   {
765                     ThrowFileException(exception,CorruptImageError,
766                       "UnexpectedEndOfFile",image->filename);
767                     break;
768                   }
769             count=ReadBlob(image,length,pixels);
770             for (y=0; y < (ssize_t) image->extract_info.height; y++)
771             {
772               if (count != (ssize_t) length)
773                 {
774                   ThrowFileException(exception,CorruptImageError,
775                     "UnexpectedEndOfFile",image->filename);
776                   break;
777                 }
778               q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
779                 exception);
780               if (q == (Quantum *) NULL)
781                 break;
782               length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
783                 quantum_info,BlueQuantum,pixels,exception);
784               if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
785                 break;
786               if (((y-image->extract_info.y) >= 0) && 
787                   ((y-image->extract_info.y) < (ssize_t) image->rows))
788                 {
789                   p=GetVirtualPixels(canvas_image,
790                     canvas_image->extract_info.x,0,canvas_image->columns,1,
791                     exception);
792                   q=GetAuthenticPixels(image,0,y-image->extract_info.y,
793                     image->columns,1,exception);
794                   if ((p == (const Quantum *) NULL) ||
795                       (q == (Quantum *) NULL))
796                     break;
797                   for (x=0; x < (ssize_t) image->columns; x++)
798                   {
799                     SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
800                     p+=GetPixelChannels(canvas_image);
801                     q+=GetPixelChannels(image);
802                   }
803                   if (SyncAuthenticPixels(image,exception) == MagickFalse)
804                     break;
805                }
806               count=ReadBlob(image,length,pixels);
807             }
808             if (image->previous == (Image *) NULL)
809               {
810                 status=SetImageProgress(image,LoadImageTag,4,5);
811                 if (status == MagickFalse)
812                   break;
813               }
814           }
815         if (image->previous == (Image *) NULL)
816           {
817             status=SetImageProgress(image,LoadImageTag,5,5);
818             if (status == MagickFalse)
819               break;
820           }
821         break;
822       }
823     }
824     SetQuantumImageType(image,quantum_type);
825     /*
826       Proceed to next image.
827     */
828     if (image_info->number_scenes != 0)
829       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
830         break;
831     if (count == (ssize_t) length)
832       {
833         /*
834           Allocate next image structure.
835         */
836         AcquireNextImage(image_info,image,exception);
837         if (GetNextImageInList(image) == (Image *) NULL)
838           {
839             image=DestroyImageList(image);
840             return((Image *) NULL);
841           }
842         image=SyncNextImageInList(image);
843         status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
844           GetBlobSize(image));
845         if (status == MagickFalse)
846           break;
847       }
848     scene++;
849   } while (count == (ssize_t) length);
850   quantum_info=DestroyQuantumInfo(quantum_info);
851   canvas_image=DestroyImage(canvas_image);
852   (void) CloseBlob(image);
853   return(GetFirstImageInList(image));
854 }
855 \f
856 /*
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858 %                                                                             %
859 %                                                                             %
860 %                                                                             %
861 %   R e g i s t e r Y C b C r I m a g e                                       %
862 %                                                                             %
863 %                                                                             %
864 %                                                                             %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 %
867 %  RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
868 %  the list of supported formats.  The attributes include the image format
869 %  tag, a method to read and/or write the format, whether the format
870 %  supports the saving of more than one frame to the same file or blob,
871 %  whether the format supports native in-memory I/O, and a brief
872 %  description of the format.
873 %
874 %  The format of the RegisterYCBCRImage method is:
875 %
876 %      size_t RegisterYCBCRImage(void)
877 %
878 */
879 ModuleExport size_t RegisterYCBCRImage(void)
880 {
881   MagickInfo
882     *entry;
883
884   entry=SetMagickInfo("YCbCr");
885   entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
886   entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
887   entry->raw=MagickTrue;
888   entry->endian_support=MagickTrue;
889   entry->description=ConstantString("Raw Y, Cb, and Cr samples");
890   entry->module=ConstantString("YCbCr");
891   (void) RegisterMagickInfo(entry);
892   entry=SetMagickInfo("YCbCrA");
893   entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
894   entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
895   entry->raw=MagickTrue;
896   entry->endian_support=MagickTrue;
897   entry->description=ConstantString("Raw Y, Cb, Cr, and alpha samples");
898   entry->module=ConstantString("YCbCr");
899   (void) RegisterMagickInfo(entry);
900   return(MagickImageCoderSignature);
901 }
902 \f
903 /*
904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 %                                                                             %
906 %                                                                             %
907 %                                                                             %
908 %   U n r e g i s t e r Y C b C r I m a g e                                   %
909 %                                                                             %
910 %                                                                             %
911 %                                                                             %
912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913 %
914 %  UnregisterYCBCRImage() removes format registrations made by the
915 %  YCbCr module from the list of supported formats.
916 %
917 %  The format of the UnregisterYCBCRImage method is:
918 %
919 %      UnregisterYCBCRImage(void)
920 %
921 */
922 ModuleExport void UnregisterYCBCRImage(void)
923 {
924   (void) UnregisterMagickInfo("YCbCr");
925   (void) UnregisterMagickInfo("YCbCrA");
926 }
927 \f
928 /*
929 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
930 %                                                                             %
931 %                                                                             %
932 %                                                                             %
933 %   W r i t e Y C b C r I m a g e                                             %
934 %                                                                             %
935 %                                                                             %
936 %                                                                             %
937 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
938 %
939 %  WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
940 %  rasterfile format.
941 %
942 %  The format of the WriteYCBCRImage method is:
943 %
944 %      MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
945 %        Image *image,ExceptionInfo *exception)
946 %
947 %  A description of each parameter follows.
948 %
949 %    o image_info: the image info.
950 %
951 %    o image:  The image.
952 %
953 %    o exception: return any errors or warnings in this structure.
954 %
955 */
956 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
957   Image *image,ExceptionInfo *exception)
958 {
959   MagickBooleanType
960     status;
961
962   MagickOffsetType
963     scene;
964
965   QuantumInfo
966     *quantum_info;
967
968   QuantumType
969     quantum_type;
970
971   register const Quantum
972     *p;
973
974   size_t
975     length;
976
977   ssize_t
978     count,
979     y;
980
981   unsigned char
982     *pixels;
983
984   /*
985     Allocate memory for pixels.
986   */
987   assert(image_info != (const ImageInfo *) NULL);
988   assert(image_info->signature == MagickSignature);
989   assert(image != (Image *) NULL);
990   assert(image->signature == MagickSignature);
991   if (image->debug != MagickFalse)
992     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
993   if (image_info->interlace != PartitionInterlace)
994     {
995       /*
996         Open output image file.
997       */
998       assert(exception != (ExceptionInfo *) NULL);
999   assert(exception->signature == MagickSignature);
1000   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1001       if (status == MagickFalse)
1002         return(status);
1003     }
1004   quantum_type=RGBQuantum;
1005   if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1006     {
1007       quantum_type=RGBAQuantum;
1008       image->matte=MagickTrue;
1009     }
1010   scene=0;
1011   do
1012   {
1013     /*
1014       Convert MIFF to YCbCr raster pixels.
1015     */
1016     if (image->colorspace != YCbCrColorspace)
1017       (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1018     if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1019         (image->matte == MagickFalse))
1020       (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1021     quantum_info=AcquireQuantumInfo(image_info,image);
1022     if (quantum_info == (QuantumInfo *) NULL)
1023       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1024     pixels=GetQuantumPixels(quantum_info);
1025     switch (image_info->interlace)
1026     {
1027       case NoInterlace:
1028       default:
1029       {
1030         /*
1031           No interlacing:  YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1032         */
1033         for (y=0; y < (ssize_t) image->rows; y++)
1034         {
1035           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1036           if (p == (const Quantum *) NULL)
1037             break;
1038           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1039             quantum_type,pixels,exception);
1040           count=WriteBlob(image,length,pixels);
1041           if (count != (ssize_t) length)
1042             break;
1043           if (image->previous == (Image *) NULL)
1044             {
1045               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1046                 image->rows);
1047               if (status == MagickFalse)
1048                 break;
1049             }
1050         }
1051         break;
1052       }
1053       case LineInterlace:
1054       {
1055         /*
1056           Line interlacing:  YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1057         */
1058         for (y=0; y < (ssize_t) image->rows; y++)
1059         {
1060           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1061           if (p == (const Quantum *) NULL)
1062             break;
1063           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1064             RedQuantum,pixels,exception);
1065           count=WriteBlob(image,length,pixels);
1066           if (count != (ssize_t) length)
1067             break;
1068           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1069             GreenQuantum,pixels,exception);
1070           count=WriteBlob(image,length,pixels);
1071           if (count != (ssize_t) length)
1072             break;
1073           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1074             BlueQuantum,pixels,exception);
1075           count=WriteBlob(image,length,pixels);
1076           if (count != (ssize_t) length)
1077             break;
1078           if (quantum_type == RGBAQuantum)
1079             {
1080               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1081                 AlphaQuantum,pixels,exception);
1082               count=WriteBlob(image,length,pixels);
1083               if (count != (ssize_t) length)
1084                 break;
1085             }
1086           if (image->previous == (Image *) NULL)
1087             {
1088               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1089                 image->rows);
1090               if (status == MagickFalse)
1091                 break;
1092             }
1093         }
1094         break;
1095       }
1096       case PlaneInterlace:
1097       {
1098         /*
1099           Plane interlacing:  YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1100         */
1101         for (y=0; y < (ssize_t) image->rows; y++)
1102         {
1103           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1104           if (p == (const Quantum *) NULL)
1105             break;
1106           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1107             RedQuantum,pixels,exception);
1108           count=WriteBlob(image,length,pixels);
1109           if (count != (ssize_t) length)
1110             break;
1111         }
1112         if (image->previous == (Image *) NULL)
1113           {
1114             status=SetImageProgress(image,SaveImageTag,1,5);
1115             if (status == MagickFalse)
1116               break;
1117           }
1118         for (y=0; y < (ssize_t) image->rows; y++)
1119         {
1120           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1121           if (p == (const Quantum *) NULL)
1122             break;
1123           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1124             GreenQuantum,pixels,exception);
1125           count=WriteBlob(image,length,pixels);
1126           if (count != (ssize_t) length)
1127             break;
1128         }
1129         if (image->previous == (Image *) NULL)
1130           {
1131             status=SetImageProgress(image,SaveImageTag,2,5);
1132             if (status == MagickFalse)
1133               break;
1134           }
1135         for (y=0; y < (ssize_t) image->rows; y++)
1136         {
1137           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1138           if (p == (const Quantum *) NULL)
1139             break;
1140           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1141             BlueQuantum,pixels,exception);
1142           count=WriteBlob(image,length,pixels);
1143           if (count != (ssize_t) length)
1144             break;
1145         }
1146         if (image->previous == (Image *) NULL)
1147           {
1148             status=SetImageProgress(image,SaveImageTag,3,5);
1149             if (status == MagickFalse)
1150               break;
1151           }
1152         if (quantum_type == RGBAQuantum)
1153           {
1154             for (y=0; y < (ssize_t) image->rows; y++)
1155             {
1156               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1157               if (p == (const Quantum *) NULL)
1158                 break;
1159               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1160                 AlphaQuantum,pixels,exception);
1161               count=WriteBlob(image,length,pixels);
1162               if (count != (ssize_t) length)
1163               break;
1164             }
1165           }
1166         if (image_info->interlace == PartitionInterlace)
1167           (void) CopyMagickString(image->filename,image_info->filename,
1168             MaxTextExtent);
1169         if (image->previous == (Image *) NULL)
1170           {
1171             status=SetImageProgress(image,SaveImageTag,5,5);
1172             if (status == MagickFalse)
1173               break;
1174           }
1175         break;
1176       }
1177       case PartitionInterlace:
1178       {
1179         /*
1180           Partition interlacing:  YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1181         */
1182         AppendImageFormat("Y",image->filename);
1183         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1184           AppendBinaryBlobMode,exception);
1185         if (status == MagickFalse)
1186           return(status);
1187         for (y=0; y < (ssize_t) image->rows; y++)
1188         {
1189           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1190           if (p == (const Quantum *) NULL)
1191             break;
1192           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1193             RedQuantum,pixels,exception);
1194           count=WriteBlob(image,length,pixels);
1195           if (count != (ssize_t) length)
1196             break;
1197         }
1198         if (image->previous == (Image *) NULL)
1199           {
1200             status=SetImageProgress(image,SaveImageTag,1,5);
1201             if (status == MagickFalse)
1202               break;
1203           }
1204         (void) CloseBlob(image);
1205         AppendImageFormat("Cb",image->filename);
1206         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1207           AppendBinaryBlobMode,exception);
1208         if (status == MagickFalse)
1209           return(status);
1210         for (y=0; y < (ssize_t) image->rows; y++)
1211         {
1212           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1213           if (p == (const Quantum *) NULL)
1214             break;
1215           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1216             GreenQuantum,pixels,exception);
1217           count=WriteBlob(image,length,pixels);
1218           if (count != (ssize_t) length)
1219             break;
1220         }
1221         if (image->previous == (Image *) NULL)
1222           {
1223             status=SetImageProgress(image,SaveImageTag,2,5);
1224             if (status == MagickFalse)
1225               break;
1226           }
1227         (void) CloseBlob(image);
1228         AppendImageFormat("Cr",image->filename);
1229         status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1230           AppendBinaryBlobMode,exception);
1231         if (status == MagickFalse)
1232           return(status);
1233         for (y=0; y < (ssize_t) image->rows; y++)
1234         {
1235           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1236           if (p == (const Quantum *) NULL)
1237             break;
1238           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1239             BlueQuantum,pixels,exception);
1240           count=WriteBlob(image,length,pixels);
1241           if (count != (ssize_t) length)
1242             break;
1243         }
1244         if (image->previous == (Image *) NULL)
1245           {
1246             status=SetImageProgress(image,SaveImageTag,3,5);
1247             if (status == MagickFalse)
1248               break;
1249           }
1250         if (quantum_type == RGBAQuantum)
1251           {
1252             (void) CloseBlob(image);
1253             AppendImageFormat("A",image->filename);
1254             status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1255               AppendBinaryBlobMode,exception);
1256             if (status == MagickFalse)
1257               return(status);
1258             for (y=0; y < (ssize_t) image->rows; y++)
1259             {
1260               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1261               if (p == (const Quantum *) NULL)
1262                 break;
1263               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1264                 AlphaQuantum,pixels,exception);
1265               count=WriteBlob(image,length,pixels);
1266               if (count != (ssize_t) length)
1267                 break;
1268             }
1269             if (image->previous == (Image *) NULL)
1270               {
1271                 status=SetImageProgress(image,SaveImageTag,4,5);
1272                 if (status == MagickFalse)
1273                   break;
1274               }
1275           }
1276         (void) CloseBlob(image);
1277         (void) CopyMagickString(image->filename,image_info->filename,
1278           MaxTextExtent);
1279         if (image->previous == (Image *) NULL)
1280           {
1281             status=SetImageProgress(image,SaveImageTag,5,5);
1282             if (status == MagickFalse)
1283               break;
1284           }
1285         break;
1286       }
1287     }
1288     quantum_info=DestroyQuantumInfo(quantum_info);
1289     if (GetNextImageInList(image) == (Image *) NULL)
1290       break;
1291     image=SyncNextImageInList(image);
1292     status=SetImageProgress(image,SaveImagesTag,scene++,
1293       GetImageListLength(image));
1294     if (status == MagickFalse)
1295       break;
1296   } while (image_info->adjoin != MagickFalse);
1297   (void) CloseBlob(image);
1298   return(MagickTrue);
1299 }