2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
6 % Y Y YYYC BBBB YYYC RRRR %
10 % Y YYYC BBBB YYYC R R %
13 % Read/Write Raw YCbCr Image Format %
20 % Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/colorspace.h"
47 #include "magick/constitute.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/pixel-private.h"
58 #include "magick/quantum-private.h"
59 #include "magick/static.h"
60 #include "magick/statistic.h"
61 #include "magick/string_.h"
62 #include "magick/module.h"
63 #include "magick/utility.h"
68 static MagickBooleanType
69 WriteYCBCRImage(const ImageInfo *,Image *);
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % R e a d Y C b C r I m a g e %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
86 % The format of the ReadYCBCRImage method is:
88 % Image *ReadYCBCRImage(const ImageInfo *image_info,
89 % ExceptionInfo *exception)
91 % A description of each parameter follows:
93 % o image_info: the image info.
95 % o exception: return any errors or warnings in this structure.
98 static Image *ReadYCBCRImage(const ImageInfo *image_info,
99 ExceptionInfo *exception)
120 register const PixelPacket
142 assert(image_info != (const ImageInfo *) NULL);
143 assert(image_info->signature == MagickSignature);
144 if (image_info->debug != MagickFalse)
145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
146 image_info->filename);
147 assert(exception != (ExceptionInfo *) NULL);
148 assert(exception->signature == MagickSignature);
149 image=AcquireImage(image_info);
150 if ((image->columns == 0) || (image->rows == 0))
151 ThrowReaderException(OptionError,"MustSpecifyImageSize");
152 image->colorspace=YCbCrColorspace;
153 if (image_info->interlace != PartitionInterlace)
155 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
156 if (status == MagickFalse)
158 image=DestroyImageList(image);
159 return((Image *) NULL);
161 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
162 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
166 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
168 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
170 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
171 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
172 if (quantum_info == (QuantumInfo *) NULL)
173 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
174 pixels=GetQuantumPixels(quantum_info);
175 quantum_type=RGBQuantum;
176 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
178 quantum_type=RGBAQuantum;
179 image->matte=MagickTrue;
181 if (image_info->number_scenes != 0)
182 while (image->scene < image_info->scene)
188 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
189 for (y=0; y < (ssize_t) image->rows; y++)
191 count=ReadBlob(image,length,pixels);
192 if (count != (ssize_t) length)
202 Read pixels to virtual canvas image then push to image.
204 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
205 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
207 image->colorspace=YCbCrColorspace;
208 switch (image_info->interlace)
214 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
218 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
219 count=ReadBlob(image,length,pixels);
221 for (y=0; y < (ssize_t) image->extract_info.height; y++)
223 if (count != (ssize_t) length)
225 ThrowFileException(exception,CorruptImageError,
226 "UnexpectedEndOfFile",image->filename);
229 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
231 if (q == (PixelPacket *) NULL)
233 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
234 quantum_info,quantum_type,pixels,exception);
235 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
237 if (((y-image->extract_info.y) >= 0) &&
238 ((y-image->extract_info.y) < (ssize_t) image->rows))
240 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
241 canvas_image->columns,1,exception);
242 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
243 image->columns,1,exception);
244 if ((p == (const PixelPacket *) NULL) ||
245 (q == (PixelPacket *) NULL))
247 for (x=0; x < (ssize_t) image->columns; x++)
249 SetRedPixelComponent(q,GetRedPixelComponent(p));
250 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
251 SetBluePixelComponent(q,GetBluePixelComponent(p));
252 if (image->matte != MagickFalse)
253 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
257 if (SyncAuthenticPixels(image,exception) == MagickFalse)
260 if (image->previous == (Image *) NULL)
262 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
264 if (status == MagickFalse)
267 count=ReadBlob(image,length,pixels);
283 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
287 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
288 count=ReadBlob(image,length,pixels);
290 for (y=0; y < (ssize_t) image->extract_info.height; y++)
292 for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
294 if (count != (ssize_t) length)
296 ThrowFileException(exception,CorruptImageError,
297 "UnexpectedEndOfFile",image->filename);
300 quantum_type=quantum_types[i];
301 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
303 if (q == (PixelPacket *) NULL)
305 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
306 quantum_info,quantum_type,pixels,exception);
307 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
309 if (((y-image->extract_info.y) >= 0) &&
310 ((y-image->extract_info.y) < (ssize_t) image->rows))
312 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
313 0,canvas_image->columns,1,exception);
314 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
315 image->columns,1,exception);
316 if ((p == (const PixelPacket *) NULL) ||
317 (q == (PixelPacket *) NULL))
319 for (x=0; x < (ssize_t) image->columns; x++)
321 switch (quantum_type)
325 SetRedPixelComponent(q,GetRedPixelComponent(p));
330 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
335 SetBluePixelComponent(q,GetBluePixelComponent(p));
340 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
349 if (SyncAuthenticPixels(image,exception) == MagickFalse)
352 count=ReadBlob(image,length,pixels);
354 if (image->previous == (Image *) NULL)
356 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
358 if (status == MagickFalse)
367 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
371 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
372 count=ReadBlob(image,length,pixels);
374 for (y=0; y < (ssize_t) image->extract_info.height; y++)
376 if (count != (ssize_t) length)
378 ThrowFileException(exception,CorruptImageError,
379 "UnexpectedEndOfFile",image->filename);
382 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
384 if (q == (PixelPacket *) NULL)
386 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
387 quantum_info,RedQuantum,pixels,exception);
388 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
390 if (((y-image->extract_info.y) >= 0) &&
391 ((y-image->extract_info.y) < (ssize_t) image->rows))
393 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
394 canvas_image->columns,1,exception);
395 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
396 image->columns,1,exception);
397 if ((p == (const PixelPacket *) NULL) ||
398 (q == (PixelPacket *) NULL))
400 for (x=0; x < (ssize_t) image->columns; x++)
402 SetRedPixelComponent(q,GetRedPixelComponent(p));
406 if (SyncAuthenticPixels(image,exception) == MagickFalse)
409 count=ReadBlob(image,length,pixels);
411 if (image->previous == (Image *) NULL)
413 status=SetImageProgress(image,LoadImageTag,1,5);
414 if (status == MagickFalse)
417 for (y=0; y < (ssize_t) image->extract_info.height; y++)
419 if (count != (ssize_t) length)
421 ThrowFileException(exception,CorruptImageError,
422 "UnexpectedEndOfFile",image->filename);
425 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
427 if (q == (PixelPacket *) NULL)
429 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
430 quantum_info,GreenQuantum,pixels,exception);
431 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
433 if (((y-image->extract_info.y) >= 0) &&
434 ((y-image->extract_info.y) < (ssize_t) image->rows))
436 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
437 canvas_image->columns,1,exception);
438 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
439 image->columns,1,exception);
440 if ((p == (const PixelPacket *) NULL) ||
441 (q == (PixelPacket *) NULL))
443 for (x=0; x < (ssize_t) image->columns; x++)
445 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
449 if (SyncAuthenticPixels(image,exception) == MagickFalse)
452 count=ReadBlob(image,length,pixels);
454 if (image->previous == (Image *) NULL)
456 status=SetImageProgress(image,LoadImageTag,2,5);
457 if (status == MagickFalse)
460 for (y=0; y < (ssize_t) image->extract_info.height; y++)
462 if (count != (ssize_t) length)
464 ThrowFileException(exception,CorruptImageError,
465 "UnexpectedEndOfFile",image->filename);
468 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
470 if (q == (PixelPacket *) NULL)
472 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
473 quantum_info,BlueQuantum,pixels,exception);
474 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
476 if (((y-image->extract_info.y) >= 0) &&
477 ((y-image->extract_info.y) < (ssize_t) image->rows))
479 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
480 canvas_image->columns,1,exception);
481 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
482 image->columns,1,exception);
483 if ((p == (const PixelPacket *) NULL) ||
484 (q == (PixelPacket *) NULL))
486 for (x=0; x < (ssize_t) image->columns; x++)
488 SetBluePixelComponent(q,GetBluePixelComponent(p));
492 if (SyncAuthenticPixels(image,exception) == MagickFalse)
495 count=ReadBlob(image,length,pixels);
497 if (image->previous == (Image *) NULL)
499 status=SetImageProgress(image,LoadImageTag,3,5);
500 if (status == MagickFalse)
503 if (image->matte != MagickFalse)
505 for (y=0; y < (ssize_t) image->extract_info.height; y++)
507 if (count != (ssize_t) length)
509 ThrowFileException(exception,CorruptImageError,
510 "UnexpectedEndOfFile",image->filename);
513 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
515 if (q == (PixelPacket *) NULL)
517 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
518 quantum_info,AlphaQuantum,pixels,exception);
519 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
521 if (((y-image->extract_info.y) >= 0) &&
522 ((y-image->extract_info.y) < (ssize_t) image->rows))
524 p=GetVirtualPixels(canvas_image,
525 canvas_image->extract_info.x,0,canvas_image->columns,1,
527 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
528 image->columns,1,exception);
529 if ((p == (const PixelPacket *) NULL) ||
530 (q == (PixelPacket *) NULL))
532 for (x=0; x < (ssize_t) image->columns; x++)
534 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
538 if (SyncAuthenticPixels(image,exception) == MagickFalse)
541 count=ReadBlob(image,length,pixels);
543 if (image->previous == (Image *) NULL)
545 status=SetImageProgress(image,LoadImageTag,4,5);
546 if (status == MagickFalse)
550 if (image->previous == (Image *) NULL)
552 status=SetImageProgress(image,LoadImageTag,5,5);
553 if (status == MagickFalse)
558 case PartitionInterlace:
561 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
563 AppendImageFormat("Y",image->filename);
564 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
565 if (status == MagickFalse)
567 canvas_image=DestroyImageList(canvas_image);
568 image=DestroyImageList(image);
569 return((Image *) NULL);
571 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
572 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
574 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
575 for (i=0; i < (ssize_t) scene; i++)
576 for (y=0; y < (ssize_t) image->extract_info.height; y++)
577 if (ReadBlob(image,length,pixels) != (ssize_t) length)
579 ThrowFileException(exception,CorruptImageError,
580 "UnexpectedEndOfFile",image->filename);
583 count=ReadBlob(image,length,pixels);
584 for (y=0; y < (ssize_t) image->extract_info.height; y++)
586 if (count != (ssize_t) length)
588 ThrowFileException(exception,CorruptImageError,
589 "UnexpectedEndOfFile",image->filename);
592 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
594 if (q == (PixelPacket *) NULL)
596 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
597 quantum_info,RedQuantum,pixels,exception);
598 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
600 if (((y-image->extract_info.y) >= 0) &&
601 ((y-image->extract_info.y) < (ssize_t) image->rows))
603 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
604 canvas_image->columns,1,exception);
605 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
606 image->columns,1,exception);
607 if ((p == (const PixelPacket *) NULL) ||
608 (q == (PixelPacket *) NULL))
610 for (x=0; x < (ssize_t) image->columns; x++)
612 SetRedPixelComponent(q,GetRedPixelComponent(p));
616 if (SyncAuthenticPixels(image,exception) == MagickFalse)
619 count=ReadBlob(image,length,pixels);
621 if (image->previous == (Image *) NULL)
623 status=SetImageProgress(image,LoadImageTag,1,5);
624 if (status == MagickFalse)
627 (void) CloseBlob(image);
628 AppendImageFormat("Cb",image->filename);
629 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
630 if (status == MagickFalse)
632 canvas_image=DestroyImageList(canvas_image);
633 image=DestroyImageList(image);
634 return((Image *) NULL);
636 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
637 for (i=0; i < (ssize_t) scene; i++)
638 for (y=0; y < (ssize_t) image->extract_info.height; y++)
639 if (ReadBlob(image,length,pixels) != (ssize_t) length)
641 ThrowFileException(exception,CorruptImageError,
642 "UnexpectedEndOfFile",image->filename);
645 count=ReadBlob(image,length,pixels);
646 for (y=0; y < (ssize_t) image->extract_info.height; y++)
648 if (count != (ssize_t) length)
650 ThrowFileException(exception,CorruptImageError,
651 "UnexpectedEndOfFile",image->filename);
654 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
656 if (q == (PixelPacket *) NULL)
658 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
659 quantum_info,GreenQuantum,pixels,exception);
660 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
662 if (((y-image->extract_info.y) >= 0) &&
663 ((y-image->extract_info.y) < (ssize_t) image->rows))
665 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
666 canvas_image->columns,1,exception);
667 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
668 image->columns,1,exception);
669 if ((p == (const PixelPacket *) NULL) ||
670 (q == (PixelPacket *) NULL))
672 for (x=0; x < (ssize_t) image->columns; x++)
674 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
678 if (SyncAuthenticPixels(image,exception) == MagickFalse)
681 count=ReadBlob(image,length,pixels);
683 if (image->previous == (Image *) NULL)
685 status=SetImageProgress(image,LoadImageTag,2,5);
686 if (status == MagickFalse)
689 (void) CloseBlob(image);
690 AppendImageFormat("Cr",image->filename);
691 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
692 if (status == MagickFalse)
694 canvas_image=DestroyImageList(canvas_image);
695 image=DestroyImageList(image);
696 return((Image *) NULL);
698 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
699 for (i=0; i < (ssize_t) scene; i++)
700 for (y=0; y < (ssize_t) image->extract_info.height; y++)
701 if (ReadBlob(image,length,pixels) != (ssize_t) length)
703 ThrowFileException(exception,CorruptImageError,
704 "UnexpectedEndOfFile",image->filename);
707 count=ReadBlob(image,length,pixels);
708 for (y=0; y < (ssize_t) image->extract_info.height; y++)
710 if (count != (ssize_t) length)
712 ThrowFileException(exception,CorruptImageError,
713 "UnexpectedEndOfFile",image->filename);
716 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
718 if (q == (PixelPacket *) NULL)
720 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
721 quantum_info,BlueQuantum,pixels,exception);
722 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
724 if (((y-image->extract_info.y) >= 0) &&
725 ((y-image->extract_info.y) < (ssize_t) image->rows))
727 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
728 canvas_image->columns,1,exception);
729 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
730 image->columns,1,exception);
731 if ((p == (const PixelPacket *) NULL) ||
732 (q == (PixelPacket *) NULL))
734 for (x=0; x < (ssize_t) image->columns; x++)
736 SetBluePixelComponent(q,GetBluePixelComponent(p));
740 if (SyncAuthenticPixels(image,exception) == MagickFalse)
743 count=ReadBlob(image,length,pixels);
745 if (image->previous == (Image *) NULL)
747 status=SetImageProgress(image,LoadImageTag,3,5);
748 if (status == MagickFalse)
751 if (image->matte != MagickFalse)
753 (void) CloseBlob(image);
754 AppendImageFormat("A",image->filename);
755 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
756 if (status == MagickFalse)
758 canvas_image=DestroyImageList(canvas_image);
759 image=DestroyImageList(image);
760 return((Image *) NULL);
762 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
763 for (i=0; i < (ssize_t) scene; i++)
764 for (y=0; y < (ssize_t) image->extract_info.height; y++)
765 if (ReadBlob(image,length,pixels) != (ssize_t) length)
767 ThrowFileException(exception,CorruptImageError,
768 "UnexpectedEndOfFile",image->filename);
771 count=ReadBlob(image,length,pixels);
772 for (y=0; y < (ssize_t) image->extract_info.height; y++)
774 if (count != (ssize_t) length)
776 ThrowFileException(exception,CorruptImageError,
777 "UnexpectedEndOfFile",image->filename);
780 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
782 if (q == (PixelPacket *) NULL)
784 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
785 quantum_info,BlueQuantum,pixels,exception);
786 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
788 if (((y-image->extract_info.y) >= 0) &&
789 ((y-image->extract_info.y) < (ssize_t) image->rows))
791 p=GetVirtualPixels(canvas_image,
792 canvas_image->extract_info.x,0,canvas_image->columns,1,
794 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
795 image->columns,1,exception);
796 if ((p == (const PixelPacket *) NULL) ||
797 (q == (PixelPacket *) NULL))
799 for (x=0; x < (ssize_t) image->columns; x++)
801 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
805 if (SyncAuthenticPixels(image,exception) == MagickFalse)
808 count=ReadBlob(image,length,pixels);
810 if (image->previous == (Image *) NULL)
812 status=SetImageProgress(image,LoadImageTag,4,5);
813 if (status == MagickFalse)
817 if (image->previous == (Image *) NULL)
819 status=SetImageProgress(image,LoadImageTag,5,5);
820 if (status == MagickFalse)
826 SetQuantumImageType(image,quantum_type);
828 Proceed to next image.
830 if (image_info->number_scenes != 0)
831 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
833 if (count == (ssize_t) length)
836 Allocate next image structure.
838 AcquireNextImage(image_info,image);
839 if (GetNextImageInList(image) == (Image *) NULL)
841 image=DestroyImageList(image);
842 return((Image *) NULL);
844 image=SyncNextImageInList(image);
845 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
847 if (status == MagickFalse)
851 } while (count == (ssize_t) length);
852 quantum_info=DestroyQuantumInfo(quantum_info);
853 InheritException(&image->exception,&canvas_image->exception);
854 canvas_image=DestroyImage(canvas_image);
855 (void) CloseBlob(image);
856 return(GetFirstImageInList(image));
860 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
864 % R e g i s t e r Y C b C r I m a g e %
868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
870 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
871 % the list of supported formats. The attributes include the image format
872 % tag, a method to read and/or write the format, whether the format
873 % supports the saving of more than one frame to the same file or blob,
874 % whether the format supports native in-memory I/O, and a brief
875 % description of the format.
877 % The format of the RegisterYCBCRImage method is:
879 % size_t RegisterYCBCRImage(void)
882 ModuleExport size_t RegisterYCBCRImage(void)
887 entry=SetMagickInfo("YCbCr");
888 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
889 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
890 entry->raw=MagickTrue;
891 entry->endian_support=MagickTrue;
892 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
893 entry->module=ConstantString("YCbCr");
894 (void) RegisterMagickInfo(entry);
895 entry=SetMagickInfo("YCbCrA");
896 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
897 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
898 entry->raw=MagickTrue;
899 entry->endian_support=MagickTrue;
900 entry->description=ConstantString("Raw Y, Cb, Cr, and alpha samples");
901 entry->module=ConstantString("YCbCr");
902 (void) RegisterMagickInfo(entry);
903 return(MagickImageCoderSignature);
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911 % U n r e g i s t e r Y C b C r I m a g e %
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
917 % UnregisterYCBCRImage() removes format registrations made by the
918 % YCbCr module from the list of supported formats.
920 % The format of the UnregisterYCBCRImage method is:
922 % UnregisterYCBCRImage(void)
925 ModuleExport void UnregisterYCBCRImage(void)
927 (void) UnregisterMagickInfo("YCbCr");
928 (void) UnregisterMagickInfo("YCbCrA");
932 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
936 % W r i t e Y C b C r I m a g e %
940 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
942 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
945 % The format of the WriteYCBCRImage method is:
947 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
950 % A description of each parameter follows.
952 % o image_info: the image info.
954 % o image: The image.
957 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
975 register const PixelPacket
988 Allocate memory for pixels.
990 assert(image_info != (const ImageInfo *) NULL);
991 assert(image_info->signature == MagickSignature);
992 assert(image != (Image *) NULL);
993 assert(image->signature == MagickSignature);
994 if (image->debug != MagickFalse)
995 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
996 if (image_info->interlace != PartitionInterlace)
999 Open output image file.
1001 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1002 if (status == MagickFalse)
1005 quantum_type=RGBQuantum;
1006 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1008 quantum_type=RGBAQuantum;
1009 image->matte=MagickTrue;
1015 Convert MIFF to YCbCr raster pixels.
1017 if (image->colorspace != YCbCrColorspace)
1018 (void) TransformImageColorspace(image,YCbCrColorspace);
1019 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1020 (image->matte == MagickFalse))
1021 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
1022 quantum_info=AcquireQuantumInfo(image_info,image);
1023 if (quantum_info == (QuantumInfo *) NULL)
1024 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1025 pixels=GetQuantumPixels(quantum_info);
1026 switch (image_info->interlace)
1032 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1034 for (y=0; y < (ssize_t) image->rows; y++)
1036 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1037 if (p == (const PixelPacket *) NULL)
1039 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1040 quantum_type,pixels,&image->exception);
1041 count=WriteBlob(image,length,pixels);
1042 if (count != (ssize_t) length)
1044 if (image->previous == (Image *) NULL)
1046 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1048 if (status == MagickFalse)
1057 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1059 for (y=0; y < (ssize_t) image->rows; y++)
1061 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1062 if (p == (const PixelPacket *) NULL)
1064 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1065 RedQuantum,pixels,&image->exception);
1066 count=WriteBlob(image,length,pixels);
1067 if (count != (ssize_t) length)
1069 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1070 GreenQuantum,pixels,&image->exception);
1071 count=WriteBlob(image,length,pixels);
1072 if (count != (ssize_t) length)
1074 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1075 BlueQuantum,pixels,&image->exception);
1076 count=WriteBlob(image,length,pixels);
1077 if (count != (ssize_t) length)
1079 if (quantum_type == RGBAQuantum)
1081 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1082 quantum_info,AlphaQuantum,pixels,&image->exception);
1083 count=WriteBlob(image,length,pixels);
1084 if (count != (ssize_t) length)
1087 if (image->previous == (Image *) NULL)
1089 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1091 if (status == MagickFalse)
1097 case PlaneInterlace:
1100 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1102 for (y=0; y < (ssize_t) image->rows; y++)
1104 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1105 if (p == (const PixelPacket *) NULL)
1107 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1108 RedQuantum,pixels,&image->exception);
1109 count=WriteBlob(image,length,pixels);
1110 if (count != (ssize_t) length)
1113 if (image->previous == (Image *) NULL)
1115 status=SetImageProgress(image,SaveImageTag,1,5);
1116 if (status == MagickFalse)
1119 for (y=0; y < (ssize_t) image->rows; y++)
1121 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1122 if (p == (const PixelPacket *) NULL)
1124 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1125 GreenQuantum,pixels,&image->exception);
1126 count=WriteBlob(image,length,pixels);
1127 if (count != (ssize_t) length)
1130 if (image->previous == (Image *) NULL)
1132 status=SetImageProgress(image,SaveImageTag,2,5);
1133 if (status == MagickFalse)
1136 for (y=0; y < (ssize_t) image->rows; y++)
1138 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1139 if (p == (const PixelPacket *) NULL)
1141 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1142 BlueQuantum,pixels,&image->exception);
1143 count=WriteBlob(image,length,pixels);
1144 if (count != (ssize_t) length)
1147 if (image->previous == (Image *) NULL)
1149 status=SetImageProgress(image,SaveImageTag,3,5);
1150 if (status == MagickFalse)
1153 if (quantum_type == RGBAQuantum)
1155 for (y=0; y < (ssize_t) image->rows; y++)
1157 p=GetVirtualPixels(image,0,y,image->columns,1,
1159 if (p == (const PixelPacket *) NULL)
1161 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1162 quantum_info,AlphaQuantum,pixels,&image->exception);
1163 count=WriteBlob(image,length,pixels);
1164 if (count != (ssize_t) length)
1168 if (image_info->interlace == PartitionInterlace)
1169 (void) CopyMagickString(image->filename,image_info->filename,
1171 if (image->previous == (Image *) NULL)
1173 status=SetImageProgress(image,SaveImageTag,5,5);
1174 if (status == MagickFalse)
1179 case PartitionInterlace:
1182 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1184 AppendImageFormat("Y",image->filename);
1185 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1186 AppendBinaryBlobMode,&image->exception);
1187 if (status == MagickFalse)
1189 for (y=0; y < (ssize_t) image->rows; y++)
1191 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1192 if (p == (const PixelPacket *) NULL)
1194 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1195 RedQuantum,pixels,&image->exception);
1196 count=WriteBlob(image,length,pixels);
1197 if (count != (ssize_t) length)
1200 if (image->previous == (Image *) NULL)
1202 status=SetImageProgress(image,SaveImageTag,1,5);
1203 if (status == MagickFalse)
1206 (void) CloseBlob(image);
1207 AppendImageFormat("Cb",image->filename);
1208 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1209 AppendBinaryBlobMode,&image->exception);
1210 if (status == MagickFalse)
1212 for (y=0; y < (ssize_t) image->rows; y++)
1214 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1215 if (p == (const PixelPacket *) NULL)
1217 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1218 GreenQuantum,pixels,&image->exception);
1219 count=WriteBlob(image,length,pixels);
1220 if (count != (ssize_t) length)
1223 if (image->previous == (Image *) NULL)
1225 status=SetImageProgress(image,SaveImageTag,2,5);
1226 if (status == MagickFalse)
1229 (void) CloseBlob(image);
1230 AppendImageFormat("Cr",image->filename);
1231 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1232 AppendBinaryBlobMode,&image->exception);
1233 if (status == MagickFalse)
1235 for (y=0; y < (ssize_t) image->rows; y++)
1237 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1238 if (p == (const PixelPacket *) NULL)
1240 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1241 BlueQuantum,pixels,&image->exception);
1242 count=WriteBlob(image,length,pixels);
1243 if (count != (ssize_t) length)
1246 if (image->previous == (Image *) NULL)
1248 status=SetImageProgress(image,SaveImageTag,3,5);
1249 if (status == MagickFalse)
1252 if (quantum_type == RGBAQuantum)
1254 (void) CloseBlob(image);
1255 AppendImageFormat("A",image->filename);
1256 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1257 AppendBinaryBlobMode,&image->exception);
1258 if (status == MagickFalse)
1260 for (y=0; y < (ssize_t) image->rows; y++)
1262 p=GetVirtualPixels(image,0,y,image->columns,1,
1264 if (p == (const PixelPacket *) NULL)
1266 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1267 quantum_info,AlphaQuantum,pixels,&image->exception);
1268 count=WriteBlob(image,length,pixels);
1269 if (count != (ssize_t) length)
1272 if (image->previous == (Image *) NULL)
1274 status=SetImageProgress(image,SaveImageTag,4,5);
1275 if (status == MagickFalse)
1279 (void) CloseBlob(image);
1280 (void) CopyMagickString(image->filename,image_info->filename,
1282 if (image->previous == (Image *) NULL)
1284 status=SetImageProgress(image,SaveImageTag,5,5);
1285 if (status == MagickFalse)
1291 quantum_info=DestroyQuantumInfo(quantum_info);
1292 if (GetNextImageInList(image) == (Image *) NULL)
1294 image=SyncNextImageInList(image);
1295 status=SetImageProgress(image,SaveImagesTag,scene++,
1296 GetImageListLength(image));
1297 if (status == MagickFalse)
1299 } while (image_info->adjoin != MagickFalse);
1300 (void) CloseBlob(image);