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-2017 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)
121 register const Quantum
141 assert(image_info != (const ImageInfo *) NULL);
142 assert(image_info->signature == MagickCoreSignature);
143 if (image_info->debug != MagickFalse)
144 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
145 image_info->filename);
146 assert(exception != (ExceptionInfo *) NULL);
147 assert(exception->signature == MagickCoreSignature);
148 image=AcquireImage(image_info,exception);
149 if ((image->columns == 0) || (image->rows == 0))
150 ThrowReaderException(OptionError,"MustSpecifyImageSize");
151 status=SetImageExtent(image,image->columns,image->rows,exception);
152 if (status == MagickFalse)
153 return(DestroyImageList(image));
154 (void) SetImageColorspace(image,YCbCrColorspace,exception);
155 if (image_info->interlace != PartitionInterlace)
157 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
158 if (status == MagickFalse)
160 image=DestroyImageList(image);
161 return((Image *) NULL);
163 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
164 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
168 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
170 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
172 if (canvas_image == (Image *) NULL)
173 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
174 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
176 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
177 if (quantum_info == (QuantumInfo *) NULL)
178 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
179 quantum_type=RGBQuantum;
180 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
182 quantum_type=RGBAQuantum;
183 image->alpha_trait=BlendPixelTrait;
185 pixels=(const unsigned char *) NULL;
186 if (image_info->number_scenes != 0)
187 while (image->scene < image_info->scene)
193 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
194 for (y=0; y < (ssize_t) image->rows; y++)
196 pixels=(const unsigned char *) ReadBlobStream(image,length,
197 GetQuantumPixels(quantum_info),&count);
198 if (count != (ssize_t) length)
209 Read pixels to virtual canvas image then push to image.
211 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
212 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
214 status=SetImageExtent(image,image->columns,image->rows,exception);
215 if (status == MagickFalse)
217 if (SetImageColorspace(image,YCbCrColorspace,exception) == MagickFalse)
219 switch (image_info->interlace)
225 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
229 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
230 pixels=(const unsigned char *) ReadBlobStream(image,length,
231 GetQuantumPixels(quantum_info),&count);
233 for (y=0; y < (ssize_t) image->extract_info.height; y++)
235 if (count != (ssize_t) length)
238 ThrowFileException(exception,CorruptImageError,
239 "UnexpectedEndOfFile",image->filename);
242 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
244 if (q == (Quantum *) NULL)
246 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
247 quantum_info,quantum_type,pixels,exception);
248 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
250 if (((y-image->extract_info.y) >= 0) &&
251 ((y-image->extract_info.y) < (ssize_t) image->rows))
253 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
254 canvas_image->columns,1,exception);
255 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
256 image->columns,1,exception);
257 if ((p == (const Quantum *) NULL) ||
258 (q == (Quantum *) NULL))
260 for (x=0; x < (ssize_t) image->columns; x++)
262 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
263 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
264 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
265 if (image->alpha_trait != UndefinedPixelTrait)
266 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
267 p+=GetPixelChannels(canvas_image);
268 q+=GetPixelChannels(image);
270 if (SyncAuthenticPixels(image,exception) == MagickFalse)
273 if (image->previous == (Image *) NULL)
275 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
277 if (status == MagickFalse)
280 pixels=(const unsigned char *) ReadBlobStream(image,length,
281 GetQuantumPixels(quantum_info),&count);
297 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
301 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
302 pixels=(const unsigned char *) ReadBlobStream(image,length,
303 GetQuantumPixels(quantum_info),&count);
305 for (y=0; y < (ssize_t) image->extract_info.height; y++)
307 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
309 if (count != (ssize_t) length)
312 ThrowFileException(exception,CorruptImageError,
313 "UnexpectedEndOfFile",image->filename);
316 quantum_type=quantum_types[i];
317 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
319 if (q == (Quantum *) NULL)
321 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
322 quantum_info,quantum_type,pixels,exception);
323 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
325 if (((y-image->extract_info.y) >= 0) &&
326 ((y-image->extract_info.y) < (ssize_t) image->rows))
328 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
329 0,canvas_image->columns,1,exception);
330 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
331 image->columns,1,exception);
332 if ((p == (const Quantum *) NULL) ||
333 (q == (Quantum *) NULL))
335 for (x=0; x < (ssize_t) image->columns; x++)
337 switch (quantum_type)
341 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
346 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
351 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
356 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
362 p+=GetPixelChannels(canvas_image);
363 q+=GetPixelChannels(image);
365 if (SyncAuthenticPixels(image,exception) == MagickFalse)
368 pixels=(const unsigned char *) ReadBlobStream(image,length,
369 GetQuantumPixels(quantum_info),&count);
371 if (image->previous == (Image *) NULL)
373 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
375 if (status == MagickFalse)
384 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
388 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
389 pixels=(const unsigned char *) ReadBlobStream(image,length,
390 GetQuantumPixels(quantum_info),&count);
392 for (y=0; y < (ssize_t) image->extract_info.height; y++)
394 if (count != (ssize_t) length)
397 ThrowFileException(exception,CorruptImageError,
398 "UnexpectedEndOfFile",image->filename);
401 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
403 if (q == (Quantum *) NULL)
405 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
406 quantum_info,RedQuantum,pixels,exception);
407 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
409 if (((y-image->extract_info.y) >= 0) &&
410 ((y-image->extract_info.y) < (ssize_t) image->rows))
412 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
413 canvas_image->columns,1,exception);
414 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
415 image->columns,1,exception);
416 if ((p == (const Quantum *) NULL) ||
417 (q == (Quantum *) NULL))
419 for (x=0; x < (ssize_t) image->columns; x++)
421 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
422 p+=GetPixelChannels(canvas_image);
423 q+=GetPixelChannels(image);
425 if (SyncAuthenticPixels(image,exception) == MagickFalse)
428 pixels=(const unsigned char *) ReadBlobStream(image,length,
429 GetQuantumPixels(quantum_info),&count);
431 if (image->previous == (Image *) NULL)
433 status=SetImageProgress(image,LoadImageTag,1,5);
434 if (status == MagickFalse)
437 for (y=0; y < (ssize_t) image->extract_info.height; y++)
439 if (count != (ssize_t) length)
442 ThrowFileException(exception,CorruptImageError,
443 "UnexpectedEndOfFile",image->filename);
446 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
448 if (q == (Quantum *) NULL)
450 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
451 quantum_info,GreenQuantum,pixels,exception);
452 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
454 if (((y-image->extract_info.y) >= 0) &&
455 ((y-image->extract_info.y) < (ssize_t) image->rows))
457 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
458 canvas_image->columns,1,exception);
459 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
460 image->columns,1,exception);
461 if ((p == (const Quantum *) NULL) ||
462 (q == (Quantum *) NULL))
464 for (x=0; x < (ssize_t) image->columns; x++)
466 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
467 p+=GetPixelChannels(canvas_image);
468 q+=GetPixelChannels(image);
470 if (SyncAuthenticPixels(image,exception) == MagickFalse)
473 pixels=(const unsigned char *) ReadBlobStream(image,length,
474 GetQuantumPixels(quantum_info),&count);
476 if (image->previous == (Image *) NULL)
478 status=SetImageProgress(image,LoadImageTag,2,5);
479 if (status == MagickFalse)
482 for (y=0; y < (ssize_t) image->extract_info.height; y++)
484 if (count != (ssize_t) length)
487 ThrowFileException(exception,CorruptImageError,
488 "UnexpectedEndOfFile",image->filename);
491 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
493 if (q == (Quantum *) NULL)
495 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
496 quantum_info,BlueQuantum,pixels,exception);
497 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
499 if (((y-image->extract_info.y) >= 0) &&
500 ((y-image->extract_info.y) < (ssize_t) image->rows))
502 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
503 canvas_image->columns,1,exception);
504 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
505 image->columns,1,exception);
506 if ((p == (const Quantum *) NULL) ||
507 (q == (Quantum *) NULL))
509 for (x=0; x < (ssize_t) image->columns; x++)
511 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
512 p+=GetPixelChannels(canvas_image);
513 q+=GetPixelChannels(image);
515 if (SyncAuthenticPixels(image,exception) == MagickFalse)
518 pixels=(const unsigned char *) ReadBlobStream(image,length,
519 GetQuantumPixels(quantum_info),&count);
521 if (image->previous == (Image *) NULL)
523 status=SetImageProgress(image,LoadImageTag,3,5);
524 if (status == MagickFalse)
527 if (image->alpha_trait != UndefinedPixelTrait)
529 for (y=0; y < (ssize_t) image->extract_info.height; y++)
531 if (count != (ssize_t) length)
534 ThrowFileException(exception,CorruptImageError,
535 "UnexpectedEndOfFile",image->filename);
538 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
540 if (q == (Quantum *) NULL)
542 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
543 quantum_info,AlphaQuantum,pixels,exception);
544 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
546 if (((y-image->extract_info.y) >= 0) &&
547 ((y-image->extract_info.y) < (ssize_t) image->rows))
549 p=GetVirtualPixels(canvas_image,
550 canvas_image->extract_info.x,0,canvas_image->columns,1,
552 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
553 image->columns,1,exception);
554 if ((p == (const Quantum *) NULL) ||
555 (q == (Quantum *) NULL))
557 for (x=0; x < (ssize_t) image->columns; x++)
559 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
560 p+=GetPixelChannels(canvas_image);
561 q+=GetPixelChannels(image);
563 if (SyncAuthenticPixels(image,exception) == MagickFalse)
566 pixels=(const unsigned char *) ReadBlobStream(image,length,
567 GetQuantumPixels(quantum_info),&count);
569 if (image->previous == (Image *) NULL)
571 status=SetImageProgress(image,LoadImageTag,4,5);
572 if (status == MagickFalse)
576 if (image->previous == (Image *) NULL)
578 status=SetImageProgress(image,LoadImageTag,5,5);
579 if (status == MagickFalse)
584 case PartitionInterlace:
587 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
589 AppendImageFormat("Y",image->filename);
590 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
591 if (status == MagickFalse)
593 canvas_image=DestroyImageList(canvas_image);
594 image=DestroyImageList(image);
595 return((Image *) NULL);
597 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
598 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
600 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
601 for (i=0; i < (ssize_t) scene; i++)
602 for (y=0; y < (ssize_t) image->extract_info.height; y++)
604 pixels=(const unsigned char *) ReadBlobStream(image,length,
605 GetQuantumPixels(quantum_info),&count);
606 if (count != (ssize_t) length)
609 ThrowFileException(exception,CorruptImageError,
610 "UnexpectedEndOfFile",image->filename);
614 pixels=(const unsigned char *) ReadBlobStream(image,length,
615 GetQuantumPixels(quantum_info),&count);
616 for (y=0; y < (ssize_t) image->extract_info.height; y++)
618 if (count != (ssize_t) length)
621 ThrowFileException(exception,CorruptImageError,
622 "UnexpectedEndOfFile",image->filename);
625 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
627 if (q == (Quantum *) NULL)
629 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
630 quantum_info,RedQuantum,pixels,exception);
631 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
633 if (((y-image->extract_info.y) >= 0) &&
634 ((y-image->extract_info.y) < (ssize_t) image->rows))
636 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
637 canvas_image->columns,1,exception);
638 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
639 image->columns,1,exception);
640 if ((p == (const Quantum *) NULL) ||
641 (q == (Quantum *) NULL))
643 for (x=0; x < (ssize_t) image->columns; x++)
645 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
646 p+=GetPixelChannels(canvas_image);
647 q+=GetPixelChannels(image);
649 if (SyncAuthenticPixels(image,exception) == MagickFalse)
652 pixels=(const unsigned char *) ReadBlobStream(image,length,
653 GetQuantumPixels(quantum_info),&count);
655 if (image->previous == (Image *) NULL)
657 status=SetImageProgress(image,LoadImageTag,1,5);
658 if (status == MagickFalse)
661 (void) CloseBlob(image);
662 AppendImageFormat("Cb",image->filename);
663 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
664 if (status == MagickFalse)
666 canvas_image=DestroyImageList(canvas_image);
667 image=DestroyImageList(image);
668 return((Image *) NULL);
670 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
671 for (i=0; i < (ssize_t) scene; i++)
672 for (y=0; y < (ssize_t) image->extract_info.height; y++)
674 pixels=(const unsigned char *) ReadBlobStream(image,length,
675 GetQuantumPixels(quantum_info),&count);
676 if (count != (ssize_t) length)
679 ThrowFileException(exception,CorruptImageError,
680 "UnexpectedEndOfFile",image->filename);
684 pixels=(const unsigned char *) ReadBlobStream(image,length,
685 GetQuantumPixels(quantum_info),&count);
686 for (y=0; y < (ssize_t) image->extract_info.height; y++)
688 if (count != (ssize_t) length)
691 ThrowFileException(exception,CorruptImageError,
692 "UnexpectedEndOfFile",image->filename);
695 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
697 if (q == (Quantum *) NULL)
699 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
700 quantum_info,GreenQuantum,pixels,exception);
701 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
703 if (((y-image->extract_info.y) >= 0) &&
704 ((y-image->extract_info.y) < (ssize_t) image->rows))
706 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
707 canvas_image->columns,1,exception);
708 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
709 image->columns,1,exception);
710 if ((p == (const Quantum *) NULL) ||
711 (q == (Quantum *) NULL))
713 for (x=0; x < (ssize_t) image->columns; x++)
715 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
716 p+=GetPixelChannels(canvas_image);
717 q+=GetPixelChannels(image);
719 if (SyncAuthenticPixels(image,exception) == MagickFalse)
722 pixels=(const unsigned char *) ReadBlobStream(image,length,
723 GetQuantumPixels(quantum_info),&count);
725 if (image->previous == (Image *) NULL)
727 status=SetImageProgress(image,LoadImageTag,2,5);
728 if (status == MagickFalse)
731 (void) CloseBlob(image);
732 AppendImageFormat("Cr",image->filename);
733 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
734 if (status == MagickFalse)
736 canvas_image=DestroyImageList(canvas_image);
737 image=DestroyImageList(image);
738 return((Image *) NULL);
740 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
741 for (i=0; i < (ssize_t) scene; i++)
742 for (y=0; y < (ssize_t) image->extract_info.height; y++)
744 pixels=(const unsigned char *) ReadBlobStream(image,length,
745 GetQuantumPixels(quantum_info),&count);
746 if (count != (ssize_t) length)
749 ThrowFileException(exception,CorruptImageError,
750 "UnexpectedEndOfFile",image->filename);
754 pixels=(const unsigned char *) ReadBlobStream(image,length,
755 GetQuantumPixels(quantum_info),&count);
756 for (y=0; y < (ssize_t) image->extract_info.height; y++)
758 if (count != (ssize_t) length)
761 ThrowFileException(exception,CorruptImageError,
762 "UnexpectedEndOfFile",image->filename);
765 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
767 if (q == (Quantum *) NULL)
769 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
770 quantum_info,BlueQuantum,pixels,exception);
771 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
773 if (((y-image->extract_info.y) >= 0) &&
774 ((y-image->extract_info.y) < (ssize_t) image->rows))
776 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
777 canvas_image->columns,1,exception);
778 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
779 image->columns,1,exception);
780 if ((p == (const Quantum *) NULL) ||
781 (q == (Quantum *) NULL))
783 for (x=0; x < (ssize_t) image->columns; x++)
785 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
786 p+=GetPixelChannels(canvas_image);
787 q+=GetPixelChannels(image);
789 if (SyncAuthenticPixels(image,exception) == MagickFalse)
792 pixels=(const unsigned char *) ReadBlobStream(image,length,
793 GetQuantumPixels(quantum_info),&count);
795 if (image->previous == (Image *) NULL)
797 status=SetImageProgress(image,LoadImageTag,3,5);
798 if (status == MagickFalse)
801 if (image->alpha_trait != UndefinedPixelTrait)
803 (void) CloseBlob(image);
804 AppendImageFormat("A",image->filename);
805 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
806 if (status == MagickFalse)
808 canvas_image=DestroyImageList(canvas_image);
809 image=DestroyImageList(image);
810 return((Image *) NULL);
812 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
813 for (i=0; i < (ssize_t) scene; i++)
814 for (y=0; y < (ssize_t) image->extract_info.height; y++)
816 pixels=(const unsigned char *) ReadBlobStream(image,length,
817 GetQuantumPixels(quantum_info),&count);
818 if (count != (ssize_t) length)
821 ThrowFileException(exception,CorruptImageError,
822 "UnexpectedEndOfFile",image->filename);
826 pixels=(const unsigned char *) ReadBlobStream(image,length,
827 GetQuantumPixels(quantum_info),&count);
828 for (y=0; y < (ssize_t) image->extract_info.height; y++)
830 if (count != (ssize_t) length)
833 ThrowFileException(exception,CorruptImageError,
834 "UnexpectedEndOfFile",image->filename);
837 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
839 if (q == (Quantum *) NULL)
841 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
842 quantum_info,BlueQuantum,pixels,exception);
843 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
845 if (((y-image->extract_info.y) >= 0) &&
846 ((y-image->extract_info.y) < (ssize_t) image->rows))
848 p=GetVirtualPixels(canvas_image,
849 canvas_image->extract_info.x,0,canvas_image->columns,1,
851 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
852 image->columns,1,exception);
853 if ((p == (const Quantum *) NULL) ||
854 (q == (Quantum *) NULL))
856 for (x=0; x < (ssize_t) image->columns; x++)
858 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
859 p+=GetPixelChannels(canvas_image);
860 q+=GetPixelChannels(image);
862 if (SyncAuthenticPixels(image,exception) == MagickFalse)
865 pixels=(const unsigned char *) ReadBlobStream(image,length,
866 GetQuantumPixels(quantum_info),&count);
868 if (image->previous == (Image *) NULL)
870 status=SetImageProgress(image,LoadImageTag,4,5);
871 if (status == MagickFalse)
875 if (image->previous == (Image *) NULL)
877 status=SetImageProgress(image,LoadImageTag,5,5);
878 if (status == MagickFalse)
884 SetQuantumImageType(image,quantum_type);
886 Proceed to next image.
888 if (image_info->number_scenes != 0)
889 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
891 if (count == (ssize_t) length)
894 Allocate next image structure.
896 AcquireNextImage(image_info,image,exception);
897 if (GetNextImageInList(image) == (Image *) NULL)
899 image=DestroyImageList(image);
900 return((Image *) NULL);
902 image=SyncNextImageInList(image);
903 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
905 if (status == MagickFalse)
909 } while (count == (ssize_t) length);
910 quantum_info=DestroyQuantumInfo(quantum_info);
911 canvas_image=DestroyImage(canvas_image);
912 (void) CloseBlob(image);
913 if (status == MagickFalse)
914 return(DestroyImageList(image));
915 return(GetFirstImageInList(image));
919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
923 % R e g i s t e r Y C b C r I m a g e %
927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
929 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
930 % the list of supported formats. The attributes include the image format
931 % tag, a method to read and/or write the format, whether the format
932 % supports the saving of more than one frame to the same file or blob,
933 % whether the format supports native in-memory I/O, and a brief
934 % description of the format.
936 % The format of the RegisterYCBCRImage method is:
938 % size_t RegisterYCBCRImage(void)
941 ModuleExport size_t RegisterYCBCRImage(void)
946 entry=AcquireMagickInfo("YCbCr","YCbCr","Raw Y, Cb, and Cr samples");
947 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
948 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
949 entry->flags|=CoderRawSupportFlag;
950 entry->flags|=CoderEndianSupportFlag;
951 (void) RegisterMagickInfo(entry);
952 entry=AcquireMagickInfo("YCbCr","YCbCrA","Raw Y, Cb, Cr, and alpha samples");
953 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
954 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
955 entry->flags|=CoderRawSupportFlag;
956 entry->flags|=CoderEndianSupportFlag;
957 (void) RegisterMagickInfo(entry);
958 return(MagickImageCoderSignature);
962 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
966 % U n r e g i s t e r Y C b C r I m a g e %
970 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 % UnregisterYCBCRImage() removes format registrations made by the
973 % YCbCr module from the list of supported formats.
975 % The format of the UnregisterYCBCRImage method is:
977 % UnregisterYCBCRImage(void)
980 ModuleExport void UnregisterYCBCRImage(void)
982 (void) UnregisterMagickInfo("YCbCr");
983 (void) UnregisterMagickInfo("YCbCrA");
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
991 % W r i t e Y C b C r I m a g e %
995 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
997 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
1000 % The format of the WriteYCBCRImage method is:
1002 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1003 % Image *image,ExceptionInfo *exception)
1005 % A description of each parameter follows.
1007 % o image_info: the image info.
1009 % o image: The image.
1011 % o exception: return any errors or warnings in this structure.
1014 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1015 Image *image,ExceptionInfo *exception)
1029 register const Quantum
1043 Allocate memory for pixels.
1045 assert(image_info != (const ImageInfo *) NULL);
1046 assert(image_info->signature == MagickCoreSignature);
1047 assert(image != (Image *) NULL);
1048 assert(image->signature == MagickCoreSignature);
1049 if (image->debug != MagickFalse)
1050 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1051 if (image_info->interlace != PartitionInterlace)
1054 Open output image file.
1056 assert(exception != (ExceptionInfo *) NULL);
1057 assert(exception->signature == MagickCoreSignature);
1058 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1059 if (status == MagickFalse)
1062 quantum_type=RGBQuantum;
1063 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1065 quantum_type=RGBAQuantum;
1066 image->alpha_trait=BlendPixelTrait;
1072 Convert MIFF to YCbCr raster pixels.
1074 if (image->colorspace != YCbCrColorspace)
1075 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1076 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1077 (image->alpha_trait == UndefinedPixelTrait))
1078 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1079 quantum_info=AcquireQuantumInfo(image_info,image);
1080 if (quantum_info == (QuantumInfo *) NULL)
1081 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1082 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1083 switch (image_info->interlace)
1089 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1091 for (y=0; y < (ssize_t) image->rows; y++)
1093 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1094 if (p == (const Quantum *) NULL)
1096 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1097 quantum_type,pixels,exception);
1098 count=WriteBlob(image,length,pixels);
1099 if (count != (ssize_t) length)
1101 if (image->previous == (Image *) NULL)
1103 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1105 if (status == MagickFalse)
1114 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1116 for (y=0; y < (ssize_t) image->rows; y++)
1118 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1119 if (p == (const Quantum *) NULL)
1121 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1122 RedQuantum,pixels,exception);
1123 count=WriteBlob(image,length,pixels);
1124 if (count != (ssize_t) length)
1126 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1127 GreenQuantum,pixels,exception);
1128 count=WriteBlob(image,length,pixels);
1129 if (count != (ssize_t) length)
1131 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1132 BlueQuantum,pixels,exception);
1133 count=WriteBlob(image,length,pixels);
1134 if (count != (ssize_t) length)
1136 if (quantum_type == RGBAQuantum)
1138 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1139 AlphaQuantum,pixels,exception);
1140 count=WriteBlob(image,length,pixels);
1141 if (count != (ssize_t) length)
1144 if (image->previous == (Image *) NULL)
1146 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1148 if (status == MagickFalse)
1154 case PlaneInterlace:
1157 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1159 for (y=0; y < (ssize_t) image->rows; y++)
1161 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1162 if (p == (const Quantum *) NULL)
1164 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1165 RedQuantum,pixels,exception);
1166 count=WriteBlob(image,length,pixels);
1167 if (count != (ssize_t) length)
1170 if (image->previous == (Image *) NULL)
1172 status=SetImageProgress(image,SaveImageTag,1,5);
1173 if (status == MagickFalse)
1176 for (y=0; y < (ssize_t) image->rows; y++)
1178 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1179 if (p == (const Quantum *) NULL)
1181 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1182 GreenQuantum,pixels,exception);
1183 count=WriteBlob(image,length,pixels);
1184 if (count != (ssize_t) length)
1187 if (image->previous == (Image *) NULL)
1189 status=SetImageProgress(image,SaveImageTag,2,5);
1190 if (status == MagickFalse)
1193 for (y=0; y < (ssize_t) image->rows; y++)
1195 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1196 if (p == (const Quantum *) NULL)
1198 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1199 BlueQuantum,pixels,exception);
1200 count=WriteBlob(image,length,pixels);
1201 if (count != (ssize_t) length)
1204 if (image->previous == (Image *) NULL)
1206 status=SetImageProgress(image,SaveImageTag,3,5);
1207 if (status == MagickFalse)
1210 if (quantum_type == RGBAQuantum)
1212 for (y=0; y < (ssize_t) image->rows; y++)
1214 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1215 if (p == (const Quantum *) NULL)
1217 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1218 AlphaQuantum,pixels,exception);
1219 count=WriteBlob(image,length,pixels);
1220 if (count != (ssize_t) length)
1224 if (image_info->interlace == PartitionInterlace)
1225 (void) CopyMagickString(image->filename,image_info->filename,
1227 if (image->previous == (Image *) NULL)
1229 status=SetImageProgress(image,SaveImageTag,5,5);
1230 if (status == MagickFalse)
1235 case PartitionInterlace:
1238 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1240 AppendImageFormat("Y",image->filename);
1241 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1242 AppendBinaryBlobMode,exception);
1243 if (status == MagickFalse)
1245 for (y=0; y < (ssize_t) image->rows; y++)
1247 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1248 if (p == (const Quantum *) NULL)
1250 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1251 RedQuantum,pixels,exception);
1252 count=WriteBlob(image,length,pixels);
1253 if (count != (ssize_t) length)
1256 if (image->previous == (Image *) NULL)
1258 status=SetImageProgress(image,SaveImageTag,1,5);
1259 if (status == MagickFalse)
1262 (void) CloseBlob(image);
1263 AppendImageFormat("Cb",image->filename);
1264 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1265 AppendBinaryBlobMode,exception);
1266 if (status == MagickFalse)
1268 for (y=0; y < (ssize_t) image->rows; y++)
1270 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1271 if (p == (const Quantum *) NULL)
1273 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1274 GreenQuantum,pixels,exception);
1275 count=WriteBlob(image,length,pixels);
1276 if (count != (ssize_t) length)
1279 if (image->previous == (Image *) NULL)
1281 status=SetImageProgress(image,SaveImageTag,2,5);
1282 if (status == MagickFalse)
1285 (void) CloseBlob(image);
1286 AppendImageFormat("Cr",image->filename);
1287 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1288 AppendBinaryBlobMode,exception);
1289 if (status == MagickFalse)
1291 for (y=0; y < (ssize_t) image->rows; y++)
1293 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1294 if (p == (const Quantum *) NULL)
1296 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1297 BlueQuantum,pixels,exception);
1298 count=WriteBlob(image,length,pixels);
1299 if (count != (ssize_t) length)
1302 if (image->previous == (Image *) NULL)
1304 status=SetImageProgress(image,SaveImageTag,3,5);
1305 if (status == MagickFalse)
1308 if (quantum_type == RGBAQuantum)
1310 (void) CloseBlob(image);
1311 AppendImageFormat("A",image->filename);
1312 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1313 AppendBinaryBlobMode,exception);
1314 if (status == MagickFalse)
1316 for (y=0; y < (ssize_t) image->rows; y++)
1318 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1319 if (p == (const Quantum *) NULL)
1321 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1322 AlphaQuantum,pixels,exception);
1323 count=WriteBlob(image,length,pixels);
1324 if (count != (ssize_t) length)
1327 if (image->previous == (Image *) NULL)
1329 status=SetImageProgress(image,SaveImageTag,4,5);
1330 if (status == MagickFalse)
1334 (void) CloseBlob(image);
1335 (void) CopyMagickString(image->filename,image_info->filename,
1337 if (image->previous == (Image *) NULL)
1339 status=SetImageProgress(image,SaveImageTag,5,5);
1340 if (status == MagickFalse)
1346 quantum_info=DestroyQuantumInfo(quantum_info);
1347 if (GetNextImageInList(image) == (Image *) NULL)
1349 image=SyncNextImageInList(image);
1350 status=SetImageProgress(image,SaveImagesTag,scene++,
1351 GetImageListLength(image));
1352 if (status == MagickFalse)
1354 } while (image_info->adjoin != MagickFalse);
1355 (void) CloseBlob(image);