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