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-2009 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 for (i=0; i < image->offset; i++)
162 if (ReadBlobByte(image) == EOF)
164 ThrowFileException(exception,CorruptImageError,
165 "UnexpectedEndOfFile",image->filename);
170 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
172 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
174 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
175 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
176 if (quantum_info == (QuantumInfo *) NULL)
177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
178 pixels=GetQuantumPixels(quantum_info);
179 quantum_type=RGBQuantum;
180 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
182 quantum_type=RGBAQuantum;
183 image->matte=MagickTrue;
185 if (image_info->number_scenes != 0)
186 while (image->scene < image_info->scene)
192 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
193 for (y=0; y < (long) image->rows; y++)
195 count=ReadBlob(image,length,pixels);
196 if (count != (ssize_t) length)
206 Read pixels to virtual canvas image then push to image.
208 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
209 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
211 image->colorspace=YCbCrColorspace;
212 switch (image_info->interlace)
218 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
222 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
223 count=ReadBlob(image,length,pixels);
224 if (count != (ssize_t) length)
227 for (y=0; y < (long) image->extract_info.height; y++)
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) < (long) 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 < (long) image->columns; x++)
252 if (image->matte != MagickFalse)
253 q->opacity=p->opacity;
257 if (SyncAuthenticPixels(image,exception) == MagickFalse)
260 if (image->previous == (Image *) NULL)
262 status=SetImageProgress(image,LoadImageTag,y,image->rows);
263 if (status == MagickFalse)
266 count=ReadBlob(image,length,pixels);
267 if (count != (ssize_t) length)
284 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
288 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
289 count=ReadBlob(image,length,pixels);
290 if (count != (ssize_t) length)
293 for (y=0; y < (long) image->extract_info.height; y++)
295 for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
297 quantum_type=quantum_types[i];
298 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
300 if (q == (PixelPacket *) NULL)
302 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
303 quantum_info,quantum_type,pixels,exception);
304 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
306 if (((y-image->extract_info.y) >= 0) &&
307 ((y-image->extract_info.y) < (long) image->rows))
309 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
310 0,canvas_image->columns,1,exception);
311 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
312 image->columns,1,exception);
313 if ((p == (const PixelPacket *) NULL) ||
314 (q == (PixelPacket *) NULL))
316 for (x=0; x < (long) image->columns; x++)
318 switch (quantum_type)
320 case RedQuantum: q->red=p->red; break;
321 case GreenQuantum: q->green=p->green; break;
322 case BlueQuantum: q->blue=p->blue; break;
323 case OpacityQuantum: q->opacity=p->opacity; break;
329 if (SyncAuthenticPixels(image,exception) == MagickFalse)
332 count=ReadBlob(image,length,pixels);
333 if (count != (ssize_t) length)
336 if (image->previous == (Image *) NULL)
338 status=SetImageProgress(image,LoadImageTag,y,image->rows);
339 if (status == MagickFalse)
348 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
352 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
353 count=ReadBlob(image,length,pixels);
354 if (count != (ssize_t) length)
357 for (y=0; y < (long) image->extract_info.height; y++)
359 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
361 if (q == (PixelPacket *) NULL)
363 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
364 quantum_info,RedQuantum,pixels,exception);
365 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
367 if (((y-image->extract_info.y) >= 0) &&
368 ((y-image->extract_info.y) < (long) image->rows))
370 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
371 canvas_image->columns,1,exception);
372 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
373 image->columns,1,exception);
374 if ((p == (const PixelPacket *) NULL) ||
375 (q == (PixelPacket *) NULL))
377 for (x=0; x < (long) image->columns; x++)
383 if (SyncAuthenticPixels(image,exception) == MagickFalse)
386 count=ReadBlob(image,length,pixels);
387 if (count != (ssize_t) length)
390 if (image->previous == (Image *) NULL)
392 status=SetImageProgress(image,LoadImageTag,1,5);
393 if (status == MagickFalse)
396 for (y=0; y < (long) image->extract_info.height; y++)
398 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
400 if (q == (PixelPacket *) NULL)
402 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
403 quantum_info,GreenQuantum,pixels,exception);
404 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
406 if (((y-image->extract_info.y) >= 0) &&
407 ((y-image->extract_info.y) < (long) image->rows))
409 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
410 canvas_image->columns,1,exception);
411 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
412 image->columns,1,exception);
413 if ((p == (const PixelPacket *) NULL) ||
414 (q == (PixelPacket *) NULL))
416 for (x=0; x < (long) image->columns; x++)
422 if (SyncAuthenticPixels(image,exception) == MagickFalse)
425 count=ReadBlob(image,length,pixels);
426 if (count != (ssize_t) length)
429 if (image->previous == (Image *) NULL)
431 status=SetImageProgress(image,LoadImageTag,2,5);
432 if (status == MagickFalse)
435 for (y=0; y < (long) image->extract_info.height; y++)
437 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
439 if (q == (PixelPacket *) NULL)
441 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
442 quantum_info,BlueQuantum,pixels,exception);
443 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
445 if (((y-image->extract_info.y) >= 0) &&
446 ((y-image->extract_info.y) < (long) image->rows))
448 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
449 canvas_image->columns,1,exception);
450 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
451 image->columns,1,exception);
452 if ((p == (const PixelPacket *) NULL) ||
453 (q == (PixelPacket *) NULL))
455 for (x=0; x < (long) image->columns; x++)
461 if (SyncAuthenticPixels(image,exception) == MagickFalse)
464 count=ReadBlob(image,length,pixels);
465 if (count != (ssize_t) length)
468 if (image->previous == (Image *) NULL)
470 status=SetImageProgress(image,LoadImageTag,3,5);
471 if (status == MagickFalse)
474 if (image->matte != MagickFalse)
476 for (y=0; y < (long) image->extract_info.height; y++)
478 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
480 if (q == (PixelPacket *) NULL)
482 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
483 quantum_info,AlphaQuantum,pixels,exception);
484 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
486 if (((y-image->extract_info.y) >= 0) &&
487 ((y-image->extract_info.y) < (long) image->rows))
489 p=GetVirtualPixels(canvas_image,
490 canvas_image->extract_info.x,0,canvas_image->columns,1,
492 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
493 image->columns,1,exception);
494 if ((p == (const PixelPacket *) NULL) ||
495 (q == (PixelPacket *) NULL))
497 for (x=0; x < (long) image->columns; x++)
499 q->opacity=p->opacity;
503 if (SyncAuthenticPixels(image,exception) == MagickFalse)
506 count=ReadBlob(image,length,pixels);
507 if (count != (ssize_t) length)
510 if (image->previous == (Image *) NULL)
512 status=SetImageProgress(image,LoadImageTag,4,5);
513 if (status == MagickFalse)
517 if (image->previous == (Image *) NULL)
519 status=SetImageProgress(image,LoadImageTag,5,5);
520 if (status == MagickFalse)
525 case PartitionInterlace:
528 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
530 AppendImageFormat("Y",image->filename);
531 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
532 if (status == MagickFalse)
534 canvas_image=DestroyImageList(canvas_image);
535 image=DestroyImageList(image);
536 return((Image *) NULL);
538 for (i=0; i < image->offset; i++)
539 if (ReadBlobByte(image) == EOF)
541 ThrowFileException(exception,CorruptImageError,
542 "UnexpectedEndOfFile",image->filename);
545 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
546 for (i=0; i < (long) scene; i++)
547 for (y=0; y < (long) image->extract_info.height; y++)
548 if (ReadBlob(image,length,pixels) != (ssize_t) length)
550 ThrowFileException(exception,CorruptImageError,
551 "UnexpectedEndOfFile",image->filename);
554 count=ReadBlob(image,length,pixels);
555 if (count != (ssize_t) length)
557 for (y=0; y < (long) image->extract_info.height; y++)
559 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
561 if (q == (PixelPacket *) NULL)
563 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
564 quantum_info,RedQuantum,pixels,exception);
565 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
567 if (((y-image->extract_info.y) >= 0) &&
568 ((y-image->extract_info.y) < (long) image->rows))
570 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
571 canvas_image->columns,1,exception);
572 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
573 image->columns,1,exception);
574 if ((p == (const PixelPacket *) NULL) ||
575 (q == (PixelPacket *) NULL))
577 for (x=0; x < (long) image->columns; x++)
583 if (SyncAuthenticPixels(image,exception) == MagickFalse)
586 count=ReadBlob(image,length,pixels);
587 if (count != (ssize_t) length)
590 if (image->previous == (Image *) NULL)
592 status=SetImageProgress(image,LoadImageTag,1,5);
593 if (status == MagickFalse)
596 (void) CloseBlob(image);
597 AppendImageFormat("Cb",image->filename);
598 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
599 if (status == MagickFalse)
601 canvas_image=DestroyImageList(canvas_image);
602 image=DestroyImageList(image);
603 return((Image *) NULL);
605 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
606 for (i=0; i < (long) scene; i++)
607 for (y=0; y < (long) image->extract_info.height; y++)
608 if (ReadBlob(image,length,pixels) != (ssize_t) length)
610 ThrowFileException(exception,CorruptImageError,
611 "UnexpectedEndOfFile",image->filename);
614 count=ReadBlob(image,length,pixels);
615 if (count != (ssize_t) length)
617 for (y=0; y < (long) image->extract_info.height; y++)
619 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
621 if (q == (PixelPacket *) NULL)
623 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
624 quantum_info,GreenQuantum,pixels,exception);
625 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
627 if (((y-image->extract_info.y) >= 0) &&
628 ((y-image->extract_info.y) < (long) image->rows))
630 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
631 canvas_image->columns,1,exception);
632 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
633 image->columns,1,exception);
634 if ((p == (const PixelPacket *) NULL) ||
635 (q == (PixelPacket *) NULL))
637 for (x=0; x < (long) image->columns; x++)
643 if (SyncAuthenticPixels(image,exception) == MagickFalse)
646 count=ReadBlob(image,length,pixels);
647 if (count != (ssize_t) length)
650 if (image->previous == (Image *) NULL)
652 status=SetImageProgress(image,LoadImageTag,2,5);
653 if (status == MagickFalse)
656 (void) CloseBlob(image);
657 AppendImageFormat("Cr",image->filename);
658 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
659 if (status == MagickFalse)
661 canvas_image=DestroyImageList(canvas_image);
662 image=DestroyImageList(image);
663 return((Image *) NULL);
665 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
666 for (i=0; i < (long) scene; i++)
667 for (y=0; y < (long) image->extract_info.height; y++)
668 if (ReadBlob(image,length,pixels) != (ssize_t) length)
670 ThrowFileException(exception,CorruptImageError,
671 "UnexpectedEndOfFile",image->filename);
674 count=ReadBlob(image,length,pixels);
675 if (count != (ssize_t) length)
677 for (y=0; y < (long) image->extract_info.height; y++)
679 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
681 if (q == (PixelPacket *) NULL)
683 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
684 quantum_info,BlueQuantum,pixels,exception);
685 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
687 if (((y-image->extract_info.y) >= 0) &&
688 ((y-image->extract_info.y) < (long) image->rows))
690 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
691 canvas_image->columns,1,exception);
692 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
693 image->columns,1,exception);
694 if ((p == (const PixelPacket *) NULL) ||
695 (q == (PixelPacket *) NULL))
697 for (x=0; x < (long) image->columns; x++)
703 if (SyncAuthenticPixels(image,exception) == MagickFalse)
706 count=ReadBlob(image,length,pixels);
707 if (count != (ssize_t) length)
710 if (image->previous == (Image *) NULL)
712 status=SetImageProgress(image,LoadImageTag,3,5);
713 if (status == MagickFalse)
716 if (image->matte != MagickFalse)
718 (void) CloseBlob(image);
719 AppendImageFormat("A",image->filename);
720 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
721 if (status == MagickFalse)
723 canvas_image=DestroyImageList(canvas_image);
724 image=DestroyImageList(image);
725 return((Image *) NULL);
727 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
728 for (i=0; i < (long) scene; i++)
729 for (y=0; y < (long) image->extract_info.height; y++)
730 if (ReadBlob(image,length,pixels) != (ssize_t) length)
732 ThrowFileException(exception,CorruptImageError,
733 "UnexpectedEndOfFile",image->filename);
736 count=ReadBlob(image,length,pixels);
737 if (count != (ssize_t) length)
739 for (y=0; y < (long) image->extract_info.height; y++)
741 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
743 if (q == (PixelPacket *) NULL)
745 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
746 quantum_info,BlueQuantum,pixels,exception);
747 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
749 if (((y-image->extract_info.y) >= 0) &&
750 ((y-image->extract_info.y) < (long) image->rows))
752 p=GetVirtualPixels(canvas_image,
753 canvas_image->extract_info.x,0,canvas_image->columns,1,
755 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
756 image->columns,1,exception);
757 if ((p == (const PixelPacket *) NULL) ||
758 (q == (PixelPacket *) NULL))
760 for (x=0; x < (long) image->columns; x++)
762 q->opacity=p->opacity;
766 if (SyncAuthenticPixels(image,exception) == MagickFalse)
769 count=ReadBlob(image,length,pixels);
770 if (count != (ssize_t) length)
773 if (image->previous == (Image *) NULL)
775 status=SetImageProgress(image,LoadImageTag,4,5);
776 if (status == MagickFalse)
780 if (image->previous == (Image *) NULL)
782 status=SetImageProgress(image,LoadImageTag,5,5);
783 if (status == MagickFalse)
789 SetQuantumImageType(image,quantum_type);
791 Proceed to next image.
793 if (image_info->number_scenes != 0)
794 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
796 if (count == (ssize_t) length)
799 Allocate next image structure.
801 AcquireNextImage(image_info,image);
802 if (GetNextImageInList(image) == (Image *) NULL)
804 image=DestroyImageList(image);
805 return((Image *) NULL);
807 image=SyncNextImageInList(image);
808 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
810 if (status == MagickFalse)
814 } while (count == (ssize_t) length);
815 InheritException(exception,&image->exception);
816 quantum_info=DestroyQuantumInfo(quantum_info);
817 canvas_image=DestroyImage(canvas_image);
818 (void) CloseBlob(image);
819 return(GetFirstImageInList(image));
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
827 % R e g i s t e r Y C b C r I m a g e %
831 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
834 % the list of supported formats. The attributes include the image format
835 % tag, a method to read and/or write the format, whether the format
836 % supports the saving of more than one frame to the same file or blob,
837 % whether the format supports native in-memory I/O, and a brief
838 % description of the format.
840 % The format of the RegisterYCBCRImage method is:
842 % unsigned long RegisterYCBCRImage(void)
845 ModuleExport unsigned long RegisterYCBCRImage(void)
850 entry=SetMagickInfo("YCbCr");
851 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
852 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
853 entry->raw=MagickTrue;
854 entry->endian_support=MagickTrue;
855 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
856 entry->module=ConstantString("YCbCr");
857 (void) RegisterMagickInfo(entry);
858 entry=SetMagickInfo("YCbCrA");
859 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
860 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
861 entry->raw=MagickTrue;
862 entry->endian_support=MagickTrue;
863 entry->description=ConstantString("Raw Y, Cb, Cr, and alpha samples");
864 entry->module=ConstantString("YCbCr");
865 (void) RegisterMagickInfo(entry);
866 return(MagickImageCoderSignature);
870 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
874 % U n r e g i s t e r Y C b C r I m a g e %
878 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
880 % UnregisterYCBCRImage() removes format registrations made by the
881 % YCbCr module from the list of supported formats.
883 % The format of the UnregisterYCBCRImage method is:
885 % UnregisterYCBCRImage(void)
888 ModuleExport void UnregisterYCBCRImage(void)
890 (void) UnregisterMagickInfo("YCbCr");
891 (void) UnregisterMagickInfo("YCbCrA");
895 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899 % W r i t e Y C b C r I m a g e %
903 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
908 % The format of the WriteYCBCRImage method is:
910 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
913 % A description of each parameter follows.
915 % o image_info: the image info.
917 % o image: The image.
920 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
938 register const PixelPacket
951 Allocate memory for pixels.
953 assert(image_info != (const ImageInfo *) NULL);
954 assert(image_info->signature == MagickSignature);
955 assert(image != (Image *) NULL);
956 assert(image->signature == MagickSignature);
957 if (image->debug != MagickFalse)
958 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
959 if (image_info->interlace != PartitionInterlace)
962 Open output image file.
964 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
965 if (status == MagickFalse)
968 quantum_type=RGBQuantum;
969 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
971 quantum_type=RGBAQuantum;
972 image->matte=MagickTrue;
978 Convert MIFF to YCbCr raster pixels.
980 if (image->colorspace != YCbCrColorspace)
981 (void) TransformImageColorspace(image,YCbCrColorspace);
982 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
983 (image->matte == MagickFalse))
984 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
985 quantum_info=AcquireQuantumInfo(image_info,image);
986 if (quantum_info == (QuantumInfo *) NULL)
987 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
988 pixels=GetQuantumPixels(quantum_info);
989 switch (image_info->interlace)
995 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
997 for (y=0; y < (long) image->rows; y++)
999 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1000 if (p == (const PixelPacket *) NULL)
1002 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1003 quantum_type,pixels,&image->exception);
1004 count=WriteBlob(image,length,pixels);
1005 if (count != (ssize_t) length)
1007 if (image->previous == (Image *) NULL)
1009 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1010 if (status == MagickFalse)
1019 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1021 for (y=0; y < (long) image->rows; y++)
1023 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1024 if (p == (const PixelPacket *) NULL)
1026 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1027 RedQuantum,pixels,&image->exception);
1028 count=WriteBlob(image,length,pixels);
1029 if (count != (ssize_t) length)
1031 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1032 GreenQuantum,pixels,&image->exception);
1033 count=WriteBlob(image,length,pixels);
1034 if (count != (ssize_t) length)
1036 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1037 BlueQuantum,pixels,&image->exception);
1038 count=WriteBlob(image,length,pixels);
1039 if (count != (ssize_t) length)
1041 if (quantum_type == RGBAQuantum)
1043 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1044 quantum_info,AlphaQuantum,pixels,&image->exception);
1045 count=WriteBlob(image,length,pixels);
1046 if (count != (ssize_t) length)
1049 if (image->previous == (Image *) NULL)
1051 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1052 if (status == MagickFalse)
1058 case PlaneInterlace:
1061 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1063 for (y=0; y < (long) image->rows; y++)
1065 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1066 if (p == (const PixelPacket *) NULL)
1068 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1069 RedQuantum,pixels,&image->exception);
1070 count=WriteBlob(image,length,pixels);
1071 if (count != (ssize_t) length)
1074 if (image->previous == (Image *) NULL)
1076 status=SetImageProgress(image,SaveImageTag,1,5);
1077 if (status == MagickFalse)
1080 for (y=0; y < (long) image->rows; y++)
1082 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1083 if (p == (const PixelPacket *) NULL)
1085 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1086 GreenQuantum,pixels,&image->exception);
1087 count=WriteBlob(image,length,pixels);
1088 if (count != (ssize_t) length)
1091 if (image->previous == (Image *) NULL)
1093 status=SetImageProgress(image,SaveImageTag,2,5);
1094 if (status == MagickFalse)
1097 for (y=0; y < (long) image->rows; y++)
1099 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1100 if (p == (const PixelPacket *) NULL)
1102 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1103 BlueQuantum,pixels,&image->exception);
1104 count=WriteBlob(image,length,pixels);
1105 if (count != (ssize_t) length)
1108 if (image->previous == (Image *) NULL)
1110 status=SetImageProgress(image,SaveImageTag,3,5);
1111 if (status == MagickFalse)
1114 if (quantum_type == RGBAQuantum)
1116 for (y=0; y < (long) image->rows; y++)
1118 p=GetVirtualPixels(image,0,y,image->columns,1,
1120 if (p == (const PixelPacket *) NULL)
1122 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1123 quantum_info,AlphaQuantum,pixels,&image->exception);
1124 count=WriteBlob(image,length,pixels);
1125 if (count != (ssize_t) length)
1129 if (image_info->interlace == PartitionInterlace)
1130 (void) CopyMagickString(image->filename,image_info->filename,
1132 if (image->previous == (Image *) NULL)
1134 status=SetImageProgress(image,SaveImageTag,5,5);
1135 if (status == MagickFalse)
1140 case PartitionInterlace:
1143 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1145 AppendImageFormat("Y",image->filename);
1146 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1147 AppendBinaryBlobMode,&image->exception);
1148 if (status == MagickFalse)
1150 for (y=0; y < (long) image->rows; y++)
1152 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1153 if (p == (const PixelPacket *) NULL)
1155 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1156 RedQuantum,pixels,&image->exception);
1157 count=WriteBlob(image,length,pixels);
1158 if (count != (ssize_t) length)
1161 if (image->previous == (Image *) NULL)
1163 status=SetImageProgress(image,SaveImageTag,1,5);
1164 if (status == MagickFalse)
1167 (void) CloseBlob(image);
1168 AppendImageFormat("Cb",image->filename);
1169 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1170 AppendBinaryBlobMode,&image->exception);
1171 if (status == MagickFalse)
1173 for (y=0; y < (long) image->rows; y++)
1175 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1176 if (p == (const PixelPacket *) NULL)
1178 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1179 GreenQuantum,pixels,&image->exception);
1180 count=WriteBlob(image,length,pixels);
1181 if (count != (ssize_t) length)
1184 if (image->previous == (Image *) NULL)
1186 status=SetImageProgress(image,SaveImageTag,2,5);
1187 if (status == MagickFalse)
1190 (void) CloseBlob(image);
1191 AppendImageFormat("Cr",image->filename);
1192 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1193 AppendBinaryBlobMode,&image->exception);
1194 if (status == MagickFalse)
1196 for (y=0; y < (long) image->rows; y++)
1198 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1199 if (p == (const PixelPacket *) NULL)
1201 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1202 BlueQuantum,pixels,&image->exception);
1203 count=WriteBlob(image,length,pixels);
1204 if (count != (ssize_t) length)
1207 if (image->previous == (Image *) NULL)
1209 status=SetImageProgress(image,SaveImageTag,3,5);
1210 if (status == MagickFalse)
1213 if (quantum_type == RGBAQuantum)
1215 (void) CloseBlob(image);
1216 AppendImageFormat("A",image->filename);
1217 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1218 AppendBinaryBlobMode,&image->exception);
1219 if (status == MagickFalse)
1221 for (y=0; y < (long) image->rows; y++)
1223 p=GetVirtualPixels(image,0,y,image->columns,1,
1225 if (p == (const PixelPacket *) NULL)
1227 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1228 quantum_info,AlphaQuantum,pixels,&image->exception);
1229 count=WriteBlob(image,length,pixels);
1230 if (count != (ssize_t) length)
1233 if (image->previous == (Image *) NULL)
1235 status=SetImageProgress(image,SaveImageTag,4,5);
1236 if (status == MagickFalse)
1240 (void) CloseBlob(image);
1241 (void) CopyMagickString(image->filename,image_info->filename,
1243 if (image->previous == (Image *) NULL)
1245 status=SetImageProgress(image,SaveImageTag,5,5);
1246 if (status == MagickFalse)
1252 quantum_info=DestroyQuantumInfo(quantum_info);
1253 if (GetNextImageInList(image) == (Image *) NULL)
1255 image=SyncNextImageInList(image);
1256 status=SetImageProgress(image,SaveImagesTag,scene++,
1257 GetImageListLength(image));
1258 if (status == MagickFalse)
1260 } while (image_info->adjoin != MagickFalse);
1261 (void) CloseBlob(image);