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-2018 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 % https://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 "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"
69 static MagickBooleanType
70 WriteYCBCRImage(const ImageInfo *,Image *,ExceptionInfo *);
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 % R e a d Y C b C r I m a g e %
81 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
87 % The format of the ReadYCBCRImage method is:
89 % Image *ReadYCBCRImage(const ImageInfo *image_info,
90 % ExceptionInfo *exception)
92 % A description of each parameter follows:
94 % o image_info: the image info.
96 % o exception: return any errors or warnings in this structure.
99 static Image *ReadYCBCRImage(const ImageInfo *image_info,
100 ExceptionInfo *exception)
134 assert(image_info != (const ImageInfo *) NULL);
135 assert(image_info->signature == MagickCoreSignature);
136 if (image_info->debug != MagickFalse)
137 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
138 image_info->filename);
139 assert(exception != (ExceptionInfo *) NULL);
140 assert(exception->signature == MagickCoreSignature);
141 image=AcquireImage(image_info,exception);
142 if ((image->columns == 0) || (image->rows == 0))
143 ThrowReaderException(OptionError,"MustSpecifyImageSize");
144 status=SetImageExtent(image,image->columns,image->rows,exception);
145 if (status == MagickFalse)
146 return(DestroyImageList(image));
147 (void) SetImageColorspace(image,YCbCrColorspace,exception);
148 if (image_info->interlace != PartitionInterlace)
150 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
151 if (status == MagickFalse)
153 image=DestroyImageList(image);
154 return((Image *) NULL);
156 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
157 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
161 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
163 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
165 if (canvas_image == (Image *) NULL)
166 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
167 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
169 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
170 if (quantum_info == (QuantumInfo *) NULL)
172 canvas_image=DestroyImage(canvas_image);
173 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
175 quantum_type=RGBQuantum;
176 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
178 quantum_type=RGBAQuantum;
179 image->alpha_trait=BlendPixelTrait;
181 pixels=(const unsigned char *) NULL;
182 if (image_info->number_scenes != 0)
183 while (image->scene < image_info->scene)
189 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
190 for (y=0; y < (ssize_t) image->rows; y++)
192 pixels=(const unsigned char *) ReadBlobStream(image,length,
193 GetQuantumPixels(quantum_info),&count);
194 if (count != (ssize_t) length)
205 Read pixels to virtual canvas image then push to image.
207 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
208 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
210 status=SetImageExtent(image,image->columns,image->rows,exception);
211 if (status == MagickFalse)
213 if (SetImageColorspace(image,YCbCrColorspace,exception) == MagickFalse)
215 switch (image_info->interlace)
221 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
225 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
226 pixels=(const unsigned char *) ReadBlobStream(image,length,
227 GetQuantumPixels(quantum_info),&count);
229 for (y=0; y < (ssize_t) image->extract_info.height; y++)
231 register const Quantum
240 if (count != (ssize_t) length)
243 ThrowFileException(exception,CorruptImageError,
244 "UnexpectedEndOfFile",image->filename);
247 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
249 if (q == (Quantum *) NULL)
251 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
252 quantum_info,quantum_type,pixels,exception);
253 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
255 if (((y-image->extract_info.y) >= 0) &&
256 ((y-image->extract_info.y) < (ssize_t) image->rows))
258 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
259 canvas_image->columns,1,exception);
260 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
261 image->columns,1,exception);
262 if ((p == (const Quantum *) NULL) ||
263 (q == (Quantum *) NULL))
265 for (x=0; x < (ssize_t) image->columns; x++)
267 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
268 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
269 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
270 if (image->alpha_trait != UndefinedPixelTrait)
271 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
272 p+=GetPixelChannels(canvas_image);
273 q+=GetPixelChannels(image);
275 if (SyncAuthenticPixels(image,exception) == MagickFalse)
278 if (image->previous == (Image *) NULL)
280 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
282 if (status == MagickFalse)
285 pixels=(const unsigned char *) ReadBlobStream(image,length,
286 GetQuantumPixels(quantum_info),&count);
302 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
306 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
307 pixels=(const unsigned char *) ReadBlobStream(image,length,
308 GetQuantumPixels(quantum_info),&count);
310 for (y=0; y < (ssize_t) image->extract_info.height; y++)
312 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
314 register const Quantum
323 if (count != (ssize_t) length)
326 ThrowFileException(exception,CorruptImageError,
327 "UnexpectedEndOfFile",image->filename);
330 quantum_type=quantum_types[i];
331 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
333 if (q == (Quantum *) NULL)
335 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
336 quantum_info,quantum_type,pixels,exception);
337 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
339 if (((y-image->extract_info.y) >= 0) &&
340 ((y-image->extract_info.y) < (ssize_t) image->rows))
342 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
343 0,canvas_image->columns,1,exception);
344 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
345 image->columns,1,exception);
346 if ((p == (const Quantum *) NULL) ||
347 (q == (Quantum *) NULL))
349 for (x=0; x < (ssize_t) image->columns; x++)
351 switch (quantum_type)
355 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
360 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
365 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
370 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
376 p+=GetPixelChannels(canvas_image);
377 q+=GetPixelChannels(image);
379 if (SyncAuthenticPixels(image,exception) == MagickFalse)
382 pixels=(const unsigned char *) ReadBlobStream(image,length,
383 GetQuantumPixels(quantum_info),&count);
385 if (image->previous == (Image *) NULL)
387 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
389 if (status == MagickFalse)
398 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
402 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
403 pixels=(const unsigned char *) ReadBlobStream(image,length,
404 GetQuantumPixels(quantum_info),&count);
406 for (y=0; y < (ssize_t) image->extract_info.height; y++)
408 register const Quantum
417 if (count != (ssize_t) length)
420 ThrowFileException(exception,CorruptImageError,
421 "UnexpectedEndOfFile",image->filename);
424 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
426 if (q == (Quantum *) NULL)
428 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
429 quantum_info,RedQuantum,pixels,exception);
430 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
432 if (((y-image->extract_info.y) >= 0) &&
433 ((y-image->extract_info.y) < (ssize_t) image->rows))
435 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
436 canvas_image->columns,1,exception);
437 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
438 image->columns,1,exception);
439 if ((p == (const Quantum *) NULL) ||
440 (q == (Quantum *) NULL))
442 for (x=0; x < (ssize_t) image->columns; x++)
444 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
445 p+=GetPixelChannels(canvas_image);
446 q+=GetPixelChannels(image);
448 if (SyncAuthenticPixels(image,exception) == MagickFalse)
451 pixels=(const unsigned char *) ReadBlobStream(image,length,
452 GetQuantumPixels(quantum_info),&count);
454 if (image->previous == (Image *) NULL)
456 status=SetImageProgress(image,LoadImageTag,1,5);
457 if (status == MagickFalse)
460 for (y=0; y < (ssize_t) image->extract_info.height; y++)
462 register const Quantum
471 if (count != (ssize_t) length)
474 ThrowFileException(exception,CorruptImageError,
475 "UnexpectedEndOfFile",image->filename);
478 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
480 if (q == (Quantum *) NULL)
482 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
483 quantum_info,GreenQuantum,pixels,exception);
484 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
486 if (((y-image->extract_info.y) >= 0) &&
487 ((y-image->extract_info.y) < (ssize_t) image->rows))
489 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
490 canvas_image->columns,1,exception);
491 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
492 image->columns,1,exception);
493 if ((p == (const Quantum *) NULL) ||
494 (q == (Quantum *) NULL))
496 for (x=0; x < (ssize_t) image->columns; x++)
498 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
499 p+=GetPixelChannels(canvas_image);
500 q+=GetPixelChannels(image);
502 if (SyncAuthenticPixels(image,exception) == MagickFalse)
505 pixels=(const unsigned char *) ReadBlobStream(image,length,
506 GetQuantumPixels(quantum_info),&count);
508 if (image->previous == (Image *) NULL)
510 status=SetImageProgress(image,LoadImageTag,2,5);
511 if (status == MagickFalse)
514 for (y=0; y < (ssize_t) image->extract_info.height; y++)
516 register const Quantum
525 if (count != (ssize_t) length)
528 ThrowFileException(exception,CorruptImageError,
529 "UnexpectedEndOfFile",image->filename);
532 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
534 if (q == (Quantum *) NULL)
536 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
537 quantum_info,BlueQuantum,pixels,exception);
538 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
540 if (((y-image->extract_info.y) >= 0) &&
541 ((y-image->extract_info.y) < (ssize_t) image->rows))
543 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
544 canvas_image->columns,1,exception);
545 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
546 image->columns,1,exception);
547 if ((p == (const Quantum *) NULL) ||
548 (q == (Quantum *) NULL))
550 for (x=0; x < (ssize_t) image->columns; x++)
552 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
553 p+=GetPixelChannels(canvas_image);
554 q+=GetPixelChannels(image);
556 if (SyncAuthenticPixels(image,exception) == MagickFalse)
559 pixels=(const unsigned char *) ReadBlobStream(image,length,
560 GetQuantumPixels(quantum_info),&count);
562 if (image->previous == (Image *) NULL)
564 status=SetImageProgress(image,LoadImageTag,3,5);
565 if (status == MagickFalse)
568 if (image->alpha_trait != UndefinedPixelTrait)
570 for (y=0; y < (ssize_t) image->extract_info.height; y++)
572 register const Quantum
581 if (count != (ssize_t) length)
584 ThrowFileException(exception,CorruptImageError,
585 "UnexpectedEndOfFile",image->filename);
588 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
590 if (q == (Quantum *) NULL)
592 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
593 quantum_info,AlphaQuantum,pixels,exception);
594 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
596 if (((y-image->extract_info.y) >= 0) &&
597 ((y-image->extract_info.y) < (ssize_t) image->rows))
599 p=GetVirtualPixels(canvas_image,
600 canvas_image->extract_info.x,0,canvas_image->columns,1,
602 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
603 image->columns,1,exception);
604 if ((p == (const Quantum *) NULL) ||
605 (q == (Quantum *) NULL))
607 for (x=0; x < (ssize_t) image->columns; x++)
609 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
610 p+=GetPixelChannels(canvas_image);
611 q+=GetPixelChannels(image);
613 if (SyncAuthenticPixels(image,exception) == MagickFalse)
616 pixels=(const unsigned char *) ReadBlobStream(image,length,
617 GetQuantumPixels(quantum_info),&count);
619 if (image->previous == (Image *) NULL)
621 status=SetImageProgress(image,LoadImageTag,4,5);
622 if (status == MagickFalse)
626 if (image->previous == (Image *) NULL)
628 status=SetImageProgress(image,LoadImageTag,5,5);
629 if (status == MagickFalse)
634 case PartitionInterlace:
637 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
639 AppendImageFormat("Y",image->filename);
640 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
641 if (status == MagickFalse)
643 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
646 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
650 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
651 for (i=0; i < (ssize_t) scene; i++)
653 for (y=0; y < (ssize_t) image->extract_info.height; y++)
655 pixels=(const unsigned char *) ReadBlobStream(image,length,
656 GetQuantumPixels(quantum_info),&count);
657 if (count != (ssize_t) length)
660 if (count != (ssize_t) length)
663 pixels=(const unsigned char *) ReadBlobStream(image,length,
664 GetQuantumPixels(quantum_info),&count);
665 for (y=0; y < (ssize_t) image->extract_info.height; y++)
667 register const Quantum
676 if (count != (ssize_t) length)
679 ThrowFileException(exception,CorruptImageError,
680 "UnexpectedEndOfFile",image->filename);
683 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
685 if (q == (Quantum *) NULL)
687 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
688 quantum_info,RedQuantum,pixels,exception);
689 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
691 if (((y-image->extract_info.y) >= 0) &&
692 ((y-image->extract_info.y) < (ssize_t) image->rows))
694 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
695 canvas_image->columns,1,exception);
696 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
697 image->columns,1,exception);
698 if ((p == (const Quantum *) NULL) ||
699 (q == (Quantum *) NULL))
701 for (x=0; x < (ssize_t) image->columns; x++)
703 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
704 p+=GetPixelChannels(canvas_image);
705 q+=GetPixelChannels(image);
707 if (SyncAuthenticPixels(image,exception) == MagickFalse)
710 pixels=(const unsigned char *) ReadBlobStream(image,length,
711 GetQuantumPixels(quantum_info),&count);
713 if (image->previous == (Image *) NULL)
715 status=SetImageProgress(image,LoadImageTag,1,5);
716 if (status == MagickFalse)
719 (void) CloseBlob(image);
720 AppendImageFormat("Cb",image->filename);
721 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
722 if (status == MagickFalse)
724 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
725 for (i=0; i < (ssize_t) scene; i++)
727 for (y=0; y < (ssize_t) image->extract_info.height; y++)
729 pixels=(const unsigned char *) ReadBlobStream(image,length,
730 GetQuantumPixels(quantum_info),&count);
731 if (count != (ssize_t) length)
734 if (count != (ssize_t) length)
737 pixels=(const unsigned char *) ReadBlobStream(image,length,
738 GetQuantumPixels(quantum_info),&count);
739 for (y=0; y < (ssize_t) image->extract_info.height; y++)
741 register const Quantum
750 if (count != (ssize_t) length)
753 ThrowFileException(exception,CorruptImageError,
754 "UnexpectedEndOfFile",image->filename);
757 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
759 if (q == (Quantum *) NULL)
761 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
762 quantum_info,GreenQuantum,pixels,exception);
763 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
765 if (((y-image->extract_info.y) >= 0) &&
766 ((y-image->extract_info.y) < (ssize_t) image->rows))
768 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
769 canvas_image->columns,1,exception);
770 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
771 image->columns,1,exception);
772 if ((p == (const Quantum *) NULL) ||
773 (q == (Quantum *) NULL))
775 for (x=0; x < (ssize_t) image->columns; x++)
777 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
778 p+=GetPixelChannels(canvas_image);
779 q+=GetPixelChannels(image);
781 if (SyncAuthenticPixels(image,exception) == MagickFalse)
784 pixels=(const unsigned char *) ReadBlobStream(image,length,
785 GetQuantumPixels(quantum_info),&count);
787 if (image->previous == (Image *) NULL)
789 status=SetImageProgress(image,LoadImageTag,2,5);
790 if (status == MagickFalse)
793 (void) CloseBlob(image);
794 AppendImageFormat("Cr",image->filename);
795 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
796 if (status == MagickFalse)
798 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
799 for (i=0; i < (ssize_t) scene; i++)
801 for (y=0; y < (ssize_t) image->extract_info.height; y++)
803 pixels=(const unsigned char *) ReadBlobStream(image,length,
804 GetQuantumPixels(quantum_info),&count);
805 if (count != (ssize_t) length)
808 if (count != (ssize_t) length)
811 pixels=(const unsigned char *) ReadBlobStream(image,length,
812 GetQuantumPixels(quantum_info),&count);
813 for (y=0; y < (ssize_t) image->extract_info.height; y++)
815 register const Quantum
824 if (count != (ssize_t) length)
827 ThrowFileException(exception,CorruptImageError,
828 "UnexpectedEndOfFile",image->filename);
831 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
833 if (q == (Quantum *) NULL)
835 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
836 quantum_info,BlueQuantum,pixels,exception);
837 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
839 if (((y-image->extract_info.y) >= 0) &&
840 ((y-image->extract_info.y) < (ssize_t) image->rows))
842 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
843 canvas_image->columns,1,exception);
844 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
845 image->columns,1,exception);
846 if ((p == (const Quantum *) NULL) ||
847 (q == (Quantum *) NULL))
849 for (x=0; x < (ssize_t) image->columns; x++)
851 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
852 p+=GetPixelChannels(canvas_image);
853 q+=GetPixelChannels(image);
855 if (SyncAuthenticPixels(image,exception) == MagickFalse)
858 pixels=(const unsigned char *) ReadBlobStream(image,length,
859 GetQuantumPixels(quantum_info),&count);
861 if (image->previous == (Image *) NULL)
863 status=SetImageProgress(image,LoadImageTag,3,5);
864 if (status == MagickFalse)
867 if (image->alpha_trait != UndefinedPixelTrait)
869 (void) CloseBlob(image);
870 AppendImageFormat("A",image->filename);
871 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
872 if (status == MagickFalse)
874 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
875 for (i=0; i < (ssize_t) scene; i++)
877 for (y=0; y < (ssize_t) image->extract_info.height; y++)
879 pixels=(const unsigned char *) ReadBlobStream(image,length,
880 GetQuantumPixels(quantum_info),&count);
881 if (count != (ssize_t) length)
884 if (count != (ssize_t) length)
887 pixels=(const unsigned char *) ReadBlobStream(image,length,
888 GetQuantumPixels(quantum_info),&count);
889 for (y=0; y < (ssize_t) image->extract_info.height; y++)
891 register const Quantum
900 if (count != (ssize_t) length)
903 ThrowFileException(exception,CorruptImageError,
904 "UnexpectedEndOfFile",image->filename);
907 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
909 if (q == (Quantum *) NULL)
911 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
912 quantum_info,BlueQuantum,pixels,exception);
913 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
915 if (((y-image->extract_info.y) >= 0) &&
916 ((y-image->extract_info.y) < (ssize_t) image->rows))
918 p=GetVirtualPixels(canvas_image,
919 canvas_image->extract_info.x,0,canvas_image->columns,1,
921 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
922 image->columns,1,exception);
923 if ((p == (const Quantum *) NULL) ||
924 (q == (Quantum *) NULL))
926 for (x=0; x < (ssize_t) image->columns; x++)
928 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
929 p+=GetPixelChannels(canvas_image);
930 q+=GetPixelChannels(image);
932 if (SyncAuthenticPixels(image,exception) == MagickFalse)
935 pixels=(const unsigned char *) ReadBlobStream(image,length,
936 GetQuantumPixels(quantum_info),&count);
938 if (image->previous == (Image *) NULL)
940 status=SetImageProgress(image,LoadImageTag,4,5);
941 if (status == MagickFalse)
945 if (image->previous == (Image *) NULL)
947 status=SetImageProgress(image,LoadImageTag,5,5);
948 if (status == MagickFalse)
954 if (status == MagickFalse)
956 SetQuantumImageType(image,quantum_type);
958 Proceed to next image.
960 if (image_info->number_scenes != 0)
961 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
963 if (count == (ssize_t) length)
966 Allocate next image structure.
968 AcquireNextImage(image_info,image,exception);
969 if (GetNextImageInList(image) == (Image *) NULL)
974 image=SyncNextImageInList(image);
975 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
977 if (status == MagickFalse)
981 } while (count == (ssize_t) length);
982 quantum_info=DestroyQuantumInfo(quantum_info);
983 canvas_image=DestroyImage(canvas_image);
984 (void) CloseBlob(image);
985 if (status == MagickFalse)
986 return(DestroyImageList(image));
987 return(GetFirstImageInList(image));
991 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
995 % R e g i s t e r Y C b C r I m a g e %
999 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1001 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
1002 % the list of supported formats. The attributes include the image format
1003 % tag, a method to read and/or write the format, whether the format
1004 % supports the saving of more than one frame to the same file or blob,
1005 % whether the format supports native in-memory I/O, and a brief
1006 % description of the format.
1008 % The format of the RegisterYCBCRImage method is:
1010 % size_t RegisterYCBCRImage(void)
1013 ModuleExport size_t RegisterYCBCRImage(void)
1018 entry=AcquireMagickInfo("YCbCr","YCbCr","Raw Y, Cb, and Cr samples");
1019 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
1020 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
1021 entry->flags|=CoderRawSupportFlag;
1022 entry->flags|=CoderEndianSupportFlag;
1023 (void) RegisterMagickInfo(entry);
1024 entry=AcquireMagickInfo("YCbCr","YCbCrA","Raw Y, Cb, Cr, and alpha samples");
1025 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
1026 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
1027 entry->flags|=CoderRawSupportFlag;
1028 entry->flags|=CoderEndianSupportFlag;
1029 (void) RegisterMagickInfo(entry);
1030 return(MagickImageCoderSignature);
1034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1038 % U n r e g i s t e r Y C b C r I m a g e %
1042 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1044 % UnregisterYCBCRImage() removes format registrations made by the
1045 % YCbCr module from the list of supported formats.
1047 % The format of the UnregisterYCBCRImage method is:
1049 % UnregisterYCBCRImage(void)
1052 ModuleExport void UnregisterYCBCRImage(void)
1054 (void) UnregisterMagickInfo("YCbCr");
1055 (void) UnregisterMagickInfo("YCbCrA");
1059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1063 % W r i t e Y C b C r I m a g e %
1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1069 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
1070 % rasterfile format.
1072 % The format of the WriteYCBCRImage method is:
1074 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1075 % Image *image,ExceptionInfo *exception)
1077 % A description of each parameter follows.
1079 % o image_info: the image info.
1081 % o image: The image.
1083 % o exception: return any errors or warnings in this structure.
1086 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1087 Image *image,ExceptionInfo *exception)
1101 register const Quantum
1116 Allocate memory for pixels.
1118 assert(image_info != (const ImageInfo *) NULL);
1119 assert(image_info->signature == MagickCoreSignature);
1120 assert(image != (Image *) NULL);
1121 assert(image->signature == MagickCoreSignature);
1122 if (image->debug != MagickFalse)
1123 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1124 if (image_info->interlace != PartitionInterlace)
1127 Open output image file.
1129 assert(exception != (ExceptionInfo *) NULL);
1130 assert(exception->signature == MagickCoreSignature);
1131 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1132 if (status == MagickFalse)
1135 quantum_type=RGBQuantum;
1136 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1138 quantum_type=RGBAQuantum;
1139 image->alpha_trait=BlendPixelTrait;
1142 imageListLength=GetImageListLength(image);
1146 Convert MIFF to YCbCr raster pixels.
1148 if (image->colorspace != YCbCrColorspace)
1149 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1150 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1151 (image->alpha_trait == UndefinedPixelTrait))
1152 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1153 quantum_info=AcquireQuantumInfo(image_info,image);
1154 if (quantum_info == (QuantumInfo *) NULL)
1155 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1156 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1157 switch (image_info->interlace)
1163 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1165 for (y=0; y < (ssize_t) image->rows; y++)
1167 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1168 if (p == (const Quantum *) NULL)
1170 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1171 quantum_type,pixels,exception);
1172 count=WriteBlob(image,length,pixels);
1173 if (count != (ssize_t) length)
1175 if (image->previous == (Image *) NULL)
1177 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1179 if (status == MagickFalse)
1188 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1190 for (y=0; y < (ssize_t) image->rows; y++)
1192 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1193 if (p == (const Quantum *) NULL)
1195 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1196 RedQuantum,pixels,exception);
1197 count=WriteBlob(image,length,pixels);
1198 if (count != (ssize_t) length)
1200 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1201 GreenQuantum,pixels,exception);
1202 count=WriteBlob(image,length,pixels);
1203 if (count != (ssize_t) length)
1205 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1206 BlueQuantum,pixels,exception);
1207 count=WriteBlob(image,length,pixels);
1208 if (count != (ssize_t) length)
1210 if (quantum_type == RGBAQuantum)
1212 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1213 AlphaQuantum,pixels,exception);
1214 count=WriteBlob(image,length,pixels);
1215 if (count != (ssize_t) length)
1218 if (image->previous == (Image *) NULL)
1220 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1222 if (status == MagickFalse)
1228 case PlaneInterlace:
1231 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1233 for (y=0; y < (ssize_t) image->rows; y++)
1235 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1236 if (p == (const Quantum *) NULL)
1238 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1239 RedQuantum,pixels,exception);
1240 count=WriteBlob(image,length,pixels);
1241 if (count != (ssize_t) length)
1244 if (image->previous == (Image *) NULL)
1246 status=SetImageProgress(image,SaveImageTag,1,5);
1247 if (status == MagickFalse)
1250 for (y=0; y < (ssize_t) image->rows; y++)
1252 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1253 if (p == (const Quantum *) NULL)
1255 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1256 GreenQuantum,pixels,exception);
1257 count=WriteBlob(image,length,pixels);
1258 if (count != (ssize_t) length)
1261 if (image->previous == (Image *) NULL)
1263 status=SetImageProgress(image,SaveImageTag,2,5);
1264 if (status == MagickFalse)
1267 for (y=0; y < (ssize_t) image->rows; y++)
1269 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1270 if (p == (const Quantum *) NULL)
1272 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1273 BlueQuantum,pixels,exception);
1274 count=WriteBlob(image,length,pixels);
1275 if (count != (ssize_t) length)
1278 if (image->previous == (Image *) NULL)
1280 status=SetImageProgress(image,SaveImageTag,3,5);
1281 if (status == MagickFalse)
1284 if (quantum_type == RGBAQuantum)
1286 for (y=0; y < (ssize_t) image->rows; y++)
1288 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1289 if (p == (const Quantum *) NULL)
1291 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1292 AlphaQuantum,pixels,exception);
1293 count=WriteBlob(image,length,pixels);
1294 if (count != (ssize_t) length)
1298 if (image_info->interlace == PartitionInterlace)
1299 (void) CopyMagickString(image->filename,image_info->filename,
1301 if (image->previous == (Image *) NULL)
1303 status=SetImageProgress(image,SaveImageTag,5,5);
1304 if (status == MagickFalse)
1309 case PartitionInterlace:
1312 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1314 AppendImageFormat("Y",image->filename);
1315 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1316 AppendBinaryBlobMode,exception);
1317 if (status == MagickFalse)
1319 for (y=0; y < (ssize_t) image->rows; y++)
1321 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1322 if (p == (const Quantum *) NULL)
1324 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1325 RedQuantum,pixels,exception);
1326 count=WriteBlob(image,length,pixels);
1327 if (count != (ssize_t) length)
1330 if (image->previous == (Image *) NULL)
1332 status=SetImageProgress(image,SaveImageTag,1,5);
1333 if (status == MagickFalse)
1336 (void) CloseBlob(image);
1337 AppendImageFormat("Cb",image->filename);
1338 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1339 AppendBinaryBlobMode,exception);
1340 if (status == MagickFalse)
1342 for (y=0; y < (ssize_t) image->rows; y++)
1344 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1345 if (p == (const Quantum *) NULL)
1347 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1348 GreenQuantum,pixels,exception);
1349 count=WriteBlob(image,length,pixels);
1350 if (count != (ssize_t) length)
1353 if (image->previous == (Image *) NULL)
1355 status=SetImageProgress(image,SaveImageTag,2,5);
1356 if (status == MagickFalse)
1359 (void) CloseBlob(image);
1360 AppendImageFormat("Cr",image->filename);
1361 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1362 AppendBinaryBlobMode,exception);
1363 if (status == MagickFalse)
1365 for (y=0; y < (ssize_t) image->rows; y++)
1367 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1368 if (p == (const Quantum *) NULL)
1370 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1371 BlueQuantum,pixels,exception);
1372 count=WriteBlob(image,length,pixels);
1373 if (count != (ssize_t) length)
1376 if (image->previous == (Image *) NULL)
1378 status=SetImageProgress(image,SaveImageTag,3,5);
1379 if (status == MagickFalse)
1382 if (quantum_type == RGBAQuantum)
1384 (void) CloseBlob(image);
1385 AppendImageFormat("A",image->filename);
1386 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1387 AppendBinaryBlobMode,exception);
1388 if (status == MagickFalse)
1390 for (y=0; y < (ssize_t) image->rows; y++)
1392 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1393 if (p == (const Quantum *) NULL)
1395 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1396 AlphaQuantum,pixels,exception);
1397 count=WriteBlob(image,length,pixels);
1398 if (count != (ssize_t) length)
1401 if (image->previous == (Image *) NULL)
1403 status=SetImageProgress(image,SaveImageTag,4,5);
1404 if (status == MagickFalse)
1408 (void) CloseBlob(image);
1409 (void) CopyMagickString(image->filename,image_info->filename,
1411 if (image->previous == (Image *) NULL)
1413 status=SetImageProgress(image,SaveImageTag,5,5);
1414 if (status == MagickFalse)
1420 quantum_info=DestroyQuantumInfo(quantum_info);
1421 if (GetNextImageInList(image) == (Image *) NULL)
1423 image=SyncNextImageInList(image);
1424 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
1425 if (status == MagickFalse)
1427 } while (image_info->adjoin != MagickFalse);
1428 (void) CloseBlob(image);