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)
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);
232 if (count != (ssize_t) length)
235 for (y=0; y < (ssize_t) image->extract_info.height; y++)
237 if (count != (ssize_t) length)
240 ThrowFileException(exception,CorruptImageError,
241 "UnexpectedEndOfFile",image->filename);
244 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
246 if (q == (Quantum *) NULL)
248 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
249 quantum_info,quantum_type,pixels,exception);
250 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
252 if (((y-image->extract_info.y) >= 0) &&
253 ((y-image->extract_info.y) < (ssize_t) image->rows))
255 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
256 canvas_image->columns,1,exception);
257 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
258 image->columns,1,exception);
259 if ((p == (const Quantum *) NULL) ||
260 (q == (Quantum *) NULL))
262 for (x=0; x < (ssize_t) image->columns; x++)
264 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
265 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
266 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
267 if (image->alpha_trait != UndefinedPixelTrait)
268 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
269 p+=GetPixelChannels(canvas_image);
270 q+=GetPixelChannels(image);
272 if (SyncAuthenticPixels(image,exception) == MagickFalse)
275 if (image->previous == (Image *) NULL)
277 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
279 if (status == MagickFalse)
282 pixels=(const unsigned char *) ReadBlobStream(image,length,
283 GetQuantumPixels(quantum_info),&count);
284 if (count != (ssize_t) length)
301 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
305 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
306 pixels=(const unsigned char *) ReadBlobStream(image,length,
307 GetQuantumPixels(quantum_info),&count);
308 if (count != (ssize_t) length)
311 for (y=0; y < (ssize_t) image->extract_info.height; y++)
313 for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
315 if (count != (ssize_t) length)
318 ThrowFileException(exception,CorruptImageError,
319 "UnexpectedEndOfFile",image->filename);
322 quantum_type=quantum_types[i];
323 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
325 if (q == (Quantum *) NULL)
327 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
328 quantum_info,quantum_type,pixels,exception);
329 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
331 if (((y-image->extract_info.y) >= 0) &&
332 ((y-image->extract_info.y) < (ssize_t) image->rows))
334 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
335 0,canvas_image->columns,1,exception);
336 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
337 image->columns,1,exception);
338 if ((p == (const Quantum *) NULL) ||
339 (q == (Quantum *) NULL))
341 for (x=0; x < (ssize_t) image->columns; x++)
343 switch (quantum_type)
347 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
352 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
357 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
362 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
368 p+=GetPixelChannels(canvas_image);
369 q+=GetPixelChannels(image);
371 if (SyncAuthenticPixels(image,exception) == MagickFalse)
374 pixels=(const unsigned char *) ReadBlobStream(image,length,
375 GetQuantumPixels(quantum_info),&count);
376 if (count != (ssize_t) length)
379 if (image->previous == (Image *) NULL)
381 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
383 if (status == MagickFalse)
392 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
396 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
397 pixels=(const unsigned char *) ReadBlobStream(image,length,
398 GetQuantumPixels(quantum_info),&count);
399 if (count != (ssize_t) length)
402 for (y=0; y < (ssize_t) image->extract_info.height; y++)
404 if (count != (ssize_t) length)
407 ThrowFileException(exception,CorruptImageError,
408 "UnexpectedEndOfFile",image->filename);
411 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
413 if (q == (Quantum *) NULL)
415 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
416 quantum_info,RedQuantum,pixels,exception);
417 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
419 if (((y-image->extract_info.y) >= 0) &&
420 ((y-image->extract_info.y) < (ssize_t) image->rows))
422 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
423 canvas_image->columns,1,exception);
424 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
425 image->columns,1,exception);
426 if ((p == (const Quantum *) NULL) ||
427 (q == (Quantum *) NULL))
429 for (x=0; x < (ssize_t) image->columns; x++)
431 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
432 p+=GetPixelChannels(canvas_image);
433 q+=GetPixelChannels(image);
435 if (SyncAuthenticPixels(image,exception) == MagickFalse)
438 pixels=(const unsigned char *) ReadBlobStream(image,length,
439 GetQuantumPixels(quantum_info),&count);
440 if (count != (ssize_t) length)
443 if (image->previous == (Image *) NULL)
445 status=SetImageProgress(image,LoadImageTag,1,5);
446 if (status == MagickFalse)
449 for (y=0; y < (ssize_t) image->extract_info.height; y++)
451 if (count != (ssize_t) length)
454 ThrowFileException(exception,CorruptImageError,
455 "UnexpectedEndOfFile",image->filename);
458 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
460 if (q == (Quantum *) NULL)
462 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
463 quantum_info,GreenQuantum,pixels,exception);
464 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
466 if (((y-image->extract_info.y) >= 0) &&
467 ((y-image->extract_info.y) < (ssize_t) image->rows))
469 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
470 canvas_image->columns,1,exception);
471 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
472 image->columns,1,exception);
473 if ((p == (const Quantum *) NULL) ||
474 (q == (Quantum *) NULL))
476 for (x=0; x < (ssize_t) image->columns; x++)
478 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
479 p+=GetPixelChannels(canvas_image);
480 q+=GetPixelChannels(image);
482 if (SyncAuthenticPixels(image,exception) == MagickFalse)
485 pixels=(const unsigned char *) ReadBlobStream(image,length,
486 GetQuantumPixels(quantum_info),&count);
487 if (count != (ssize_t) length)
490 if (image->previous == (Image *) NULL)
492 status=SetImageProgress(image,LoadImageTag,2,5);
493 if (status == MagickFalse)
496 for (y=0; y < (ssize_t) image->extract_info.height; y++)
498 if (count != (ssize_t) length)
501 ThrowFileException(exception,CorruptImageError,
502 "UnexpectedEndOfFile",image->filename);
505 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
507 if (q == (Quantum *) NULL)
509 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
510 quantum_info,BlueQuantum,pixels,exception);
511 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
513 if (((y-image->extract_info.y) >= 0) &&
514 ((y-image->extract_info.y) < (ssize_t) image->rows))
516 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
517 canvas_image->columns,1,exception);
518 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
519 image->columns,1,exception);
520 if ((p == (const Quantum *) NULL) ||
521 (q == (Quantum *) NULL))
523 for (x=0; x < (ssize_t) image->columns; x++)
525 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
526 p+=GetPixelChannels(canvas_image);
527 q+=GetPixelChannels(image);
529 if (SyncAuthenticPixels(image,exception) == MagickFalse)
532 pixels=(const unsigned char *) ReadBlobStream(image,length,
533 GetQuantumPixels(quantum_info),&count);
534 if (count != (ssize_t) length)
537 if (image->previous == (Image *) NULL)
539 status=SetImageProgress(image,LoadImageTag,3,5);
540 if (status == MagickFalse)
543 if (image->alpha_trait != UndefinedPixelTrait)
545 for (y=0; y < (ssize_t) image->extract_info.height; y++)
547 if (count != (ssize_t) length)
550 ThrowFileException(exception,CorruptImageError,
551 "UnexpectedEndOfFile",image->filename);
554 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
556 if (q == (Quantum *) NULL)
558 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
559 quantum_info,AlphaQuantum,pixels,exception);
560 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
562 if (((y-image->extract_info.y) >= 0) &&
563 ((y-image->extract_info.y) < (ssize_t) image->rows))
565 p=GetVirtualPixels(canvas_image,
566 canvas_image->extract_info.x,0,canvas_image->columns,1,
568 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
569 image->columns,1,exception);
570 if ((p == (const Quantum *) NULL) ||
571 (q == (Quantum *) NULL))
573 for (x=0; x < (ssize_t) image->columns; x++)
575 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
576 p+=GetPixelChannels(canvas_image);
577 q+=GetPixelChannels(image);
579 if (SyncAuthenticPixels(image,exception) == MagickFalse)
582 pixels=(const unsigned char *) ReadBlobStream(image,length,
583 GetQuantumPixels(quantum_info),&count);
584 if (count != (ssize_t) length)
587 if (image->previous == (Image *) NULL)
589 status=SetImageProgress(image,LoadImageTag,4,5);
590 if (status == MagickFalse)
594 if (image->previous == (Image *) NULL)
596 status=SetImageProgress(image,LoadImageTag,5,5);
597 if (status == MagickFalse)
602 case PartitionInterlace:
605 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
607 AppendImageFormat("Y",image->filename);
608 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
609 if (status == MagickFalse)
611 canvas_image=DestroyImageList(canvas_image);
612 image=DestroyImageList(image);
613 return((Image *) NULL);
615 if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
616 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
618 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
619 for (i=0; i < (ssize_t) scene; i++)
620 for (y=0; y < (ssize_t) image->extract_info.height; y++)
622 pixels=(const unsigned char *) ReadBlobStream(image,length,
623 GetQuantumPixels(quantum_info),&count);
624 if (count != (ssize_t) length)
627 ThrowFileException(exception,CorruptImageError,
628 "UnexpectedEndOfFile",image->filename);
632 pixels=(const unsigned char *) ReadBlobStream(image,length,
633 GetQuantumPixels(quantum_info),&count);
634 for (y=0; y < (ssize_t) image->extract_info.height; y++)
636 if (count != (ssize_t) length)
639 ThrowFileException(exception,CorruptImageError,
640 "UnexpectedEndOfFile",image->filename);
643 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
645 if (q == (Quantum *) NULL)
647 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
648 quantum_info,RedQuantum,pixels,exception);
649 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
651 if (((y-image->extract_info.y) >= 0) &&
652 ((y-image->extract_info.y) < (ssize_t) image->rows))
654 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
655 canvas_image->columns,1,exception);
656 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
657 image->columns,1,exception);
658 if ((p == (const Quantum *) NULL) ||
659 (q == (Quantum *) NULL))
661 for (x=0; x < (ssize_t) image->columns; x++)
663 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
664 p+=GetPixelChannels(canvas_image);
665 q+=GetPixelChannels(image);
667 if (SyncAuthenticPixels(image,exception) == MagickFalse)
670 pixels=(const unsigned char *) ReadBlobStream(image,length,
671 GetQuantumPixels(quantum_info),&count);
672 if (count != (ssize_t) length)
675 if (image->previous == (Image *) NULL)
677 status=SetImageProgress(image,LoadImageTag,1,5);
678 if (status == MagickFalse)
681 (void) CloseBlob(image);
682 AppendImageFormat("Cb",image->filename);
683 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
684 if (status == MagickFalse)
686 canvas_image=DestroyImageList(canvas_image);
687 image=DestroyImageList(image);
688 return((Image *) NULL);
690 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
691 for (i=0; i < (ssize_t) scene; i++)
692 for (y=0; y < (ssize_t) image->extract_info.height; y++)
694 pixels=(const unsigned char *) ReadBlobStream(image,length,
695 GetQuantumPixels(quantum_info),&count);
696 if (count != (ssize_t) length)
699 ThrowFileException(exception,CorruptImageError,
700 "UnexpectedEndOfFile",image->filename);
704 pixels=(const unsigned char *) ReadBlobStream(image,length,
705 GetQuantumPixels(quantum_info),&count);
706 if (count != (ssize_t) length)
708 for (y=0; y < (ssize_t) image->extract_info.height; y++)
710 if (count != (ssize_t) length)
713 ThrowFileException(exception,CorruptImageError,
714 "UnexpectedEndOfFile",image->filename);
717 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
719 if (q == (Quantum *) NULL)
721 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
722 quantum_info,GreenQuantum,pixels,exception);
723 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
725 if (((y-image->extract_info.y) >= 0) &&
726 ((y-image->extract_info.y) < (ssize_t) image->rows))
728 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
729 canvas_image->columns,1,exception);
730 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
731 image->columns,1,exception);
732 if ((p == (const Quantum *) NULL) ||
733 (q == (Quantum *) NULL))
735 for (x=0; x < (ssize_t) image->columns; x++)
737 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
738 p+=GetPixelChannels(canvas_image);
739 q+=GetPixelChannels(image);
741 if (SyncAuthenticPixels(image,exception) == MagickFalse)
744 pixels=(const unsigned char *) ReadBlobStream(image,length,
745 GetQuantumPixels(quantum_info),&count);
746 if (count != (ssize_t) length)
749 if (image->previous == (Image *) NULL)
751 status=SetImageProgress(image,LoadImageTag,2,5);
752 if (status == MagickFalse)
755 (void) CloseBlob(image);
756 AppendImageFormat("Cr",image->filename);
757 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
758 if (status == MagickFalse)
760 canvas_image=DestroyImageList(canvas_image);
761 image=DestroyImageList(image);
762 return((Image *) NULL);
764 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
765 for (i=0; i < (ssize_t) scene; i++)
766 for (y=0; y < (ssize_t) image->extract_info.height; y++)
768 pixels=(const unsigned char *) ReadBlobStream(image,length,
769 GetQuantumPixels(quantum_info),&count);
770 if (count != (ssize_t) length)
773 ThrowFileException(exception,CorruptImageError,
774 "UnexpectedEndOfFile",image->filename);
778 pixels=(const unsigned char *) ReadBlobStream(image,length,
779 GetQuantumPixels(quantum_info),&count);
780 if (count != (ssize_t) length)
782 for (y=0; y < (ssize_t) image->extract_info.height; y++)
784 if (count != (ssize_t) length)
787 ThrowFileException(exception,CorruptImageError,
788 "UnexpectedEndOfFile",image->filename);
791 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
793 if (q == (Quantum *) NULL)
795 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
796 quantum_info,BlueQuantum,pixels,exception);
797 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
799 if (((y-image->extract_info.y) >= 0) &&
800 ((y-image->extract_info.y) < (ssize_t) image->rows))
802 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
803 canvas_image->columns,1,exception);
804 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
805 image->columns,1,exception);
806 if ((p == (const Quantum *) NULL) ||
807 (q == (Quantum *) NULL))
809 for (x=0; x < (ssize_t) image->columns; x++)
811 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
812 p+=GetPixelChannels(canvas_image);
813 q+=GetPixelChannels(image);
815 if (SyncAuthenticPixels(image,exception) == MagickFalse)
818 pixels=(const unsigned char *) ReadBlobStream(image,length,
819 GetQuantumPixels(quantum_info),&count);
820 if (count != (ssize_t) length)
823 if (image->previous == (Image *) NULL)
825 status=SetImageProgress(image,LoadImageTag,3,5);
826 if (status == MagickFalse)
829 if (image->alpha_trait != UndefinedPixelTrait)
831 (void) CloseBlob(image);
832 AppendImageFormat("A",image->filename);
833 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
834 if (status == MagickFalse)
836 canvas_image=DestroyImageList(canvas_image);
837 image=DestroyImageList(image);
838 return((Image *) NULL);
840 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
841 for (i=0; i < (ssize_t) scene; i++)
842 for (y=0; y < (ssize_t) image->extract_info.height; y++)
844 pixels=(const unsigned char *) ReadBlobStream(image,length,
845 GetQuantumPixels(quantum_info),&count);
846 if (count != (ssize_t) length)
849 ThrowFileException(exception,CorruptImageError,
850 "UnexpectedEndOfFile",image->filename);
854 pixels=(const unsigned char *) ReadBlobStream(image,length,
855 GetQuantumPixels(quantum_info),&count);
856 if (count != (ssize_t) length)
858 for (y=0; y < (ssize_t) image->extract_info.height; y++)
860 if (count != (ssize_t) length)
863 ThrowFileException(exception,CorruptImageError,
864 "UnexpectedEndOfFile",image->filename);
867 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
869 if (q == (Quantum *) NULL)
871 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
872 quantum_info,BlueQuantum,pixels,exception);
873 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
875 if (((y-image->extract_info.y) >= 0) &&
876 ((y-image->extract_info.y) < (ssize_t) image->rows))
878 p=GetVirtualPixels(canvas_image,
879 canvas_image->extract_info.x,0,canvas_image->columns,1,
881 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
882 image->columns,1,exception);
883 if ((p == (const Quantum *) NULL) ||
884 (q == (Quantum *) NULL))
886 for (x=0; x < (ssize_t) image->columns; x++)
888 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
889 p+=GetPixelChannels(canvas_image);
890 q+=GetPixelChannels(image);
892 if (SyncAuthenticPixels(image,exception) == MagickFalse)
895 pixels=(const unsigned char *) ReadBlobStream(image,length,
896 GetQuantumPixels(quantum_info),&count);
897 if (count != (ssize_t) length)
900 if (image->previous == (Image *) NULL)
902 status=SetImageProgress(image,LoadImageTag,4,5);
903 if (status == MagickFalse)
907 if (image->previous == (Image *) NULL)
909 status=SetImageProgress(image,LoadImageTag,5,5);
910 if (status == MagickFalse)
916 SetQuantumImageType(image,quantum_type);
918 Proceed to next image.
920 if (image_info->number_scenes != 0)
921 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
923 if (count == (ssize_t) length)
926 Allocate next image structure.
928 AcquireNextImage(image_info,image,exception);
929 if (GetNextImageInList(image) == (Image *) NULL)
931 image=DestroyImageList(image);
932 return((Image *) NULL);
934 image=SyncNextImageInList(image);
935 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
937 if (status == MagickFalse)
941 } while (count == (ssize_t) length);
942 quantum_info=DestroyQuantumInfo(quantum_info);
943 canvas_image=DestroyImage(canvas_image);
944 (void) CloseBlob(image);
945 if (status == MagickFalse)
946 return(DestroyImageList(image));
947 return(GetFirstImageInList(image));
951 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 % R e g i s t e r Y C b C r I m a g e %
959 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
961 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
962 % the list of supported formats. The attributes include the image format
963 % tag, a method to read and/or write the format, whether the format
964 % supports the saving of more than one frame to the same file or blob,
965 % whether the format supports native in-memory I/O, and a brief
966 % description of the format.
968 % The format of the RegisterYCBCRImage method is:
970 % size_t RegisterYCBCRImage(void)
973 ModuleExport size_t RegisterYCBCRImage(void)
978 entry=AcquireMagickInfo("YCbCr","YCbCr","Raw Y, Cb, and Cr samples");
979 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
980 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
981 entry->flags|=CoderRawSupportFlag;
982 entry->flags|=CoderEndianSupportFlag;
983 (void) RegisterMagickInfo(entry);
984 entry=AcquireMagickInfo("YCbCr","YCbCrA","Raw Y, Cb, Cr, and alpha samples");
985 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
986 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
987 entry->flags|=CoderRawSupportFlag;
988 entry->flags|=CoderEndianSupportFlag;
989 (void) RegisterMagickInfo(entry);
990 return(MagickImageCoderSignature);
994 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
998 % U n r e g i s t e r Y C b C r I m a g e %
1002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 % UnregisterYCBCRImage() removes format registrations made by the
1005 % YCbCr module from the list of supported formats.
1007 % The format of the UnregisterYCBCRImage method is:
1009 % UnregisterYCBCRImage(void)
1012 ModuleExport void UnregisterYCBCRImage(void)
1014 (void) UnregisterMagickInfo("YCbCr");
1015 (void) UnregisterMagickInfo("YCbCrA");
1019 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1023 % W r i t e Y C b C r I m a g e %
1027 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
1030 % rasterfile format.
1032 % The format of the WriteYCBCRImage method is:
1034 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1035 % Image *image,ExceptionInfo *exception)
1037 % A description of each parameter follows.
1039 % o image_info: the image info.
1041 % o image: The image.
1043 % o exception: return any errors or warnings in this structure.
1046 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1047 Image *image,ExceptionInfo *exception)
1061 register const Quantum
1075 Allocate memory for pixels.
1077 assert(image_info != (const ImageInfo *) NULL);
1078 assert(image_info->signature == MagickCoreSignature);
1079 assert(image != (Image *) NULL);
1080 assert(image->signature == MagickCoreSignature);
1081 if (image->debug != MagickFalse)
1082 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1083 if (image_info->interlace != PartitionInterlace)
1086 Open output image file.
1088 assert(exception != (ExceptionInfo *) NULL);
1089 assert(exception->signature == MagickCoreSignature);
1090 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1091 if (status == MagickFalse)
1094 quantum_type=RGBQuantum;
1095 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1097 quantum_type=RGBAQuantum;
1098 image->alpha_trait=BlendPixelTrait;
1104 Convert MIFF to YCbCr raster pixels.
1106 if (image->colorspace != YCbCrColorspace)
1107 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1108 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1109 (image->alpha_trait == UndefinedPixelTrait))
1110 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1111 quantum_info=AcquireQuantumInfo(image_info,image);
1112 if (quantum_info == (QuantumInfo *) NULL)
1113 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1114 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1115 switch (image_info->interlace)
1121 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1123 for (y=0; y < (ssize_t) image->rows; y++)
1125 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1126 if (p == (const Quantum *) NULL)
1128 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1129 quantum_type,pixels,exception);
1130 count=WriteBlob(image,length,pixels);
1131 if (count != (ssize_t) length)
1133 if (image->previous == (Image *) NULL)
1135 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1137 if (status == MagickFalse)
1146 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1148 for (y=0; y < (ssize_t) image->rows; y++)
1150 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1151 if (p == (const Quantum *) NULL)
1153 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1154 RedQuantum,pixels,exception);
1155 count=WriteBlob(image,length,pixels);
1156 if (count != (ssize_t) length)
1158 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1159 GreenQuantum,pixels,exception);
1160 count=WriteBlob(image,length,pixels);
1161 if (count != (ssize_t) length)
1163 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1164 BlueQuantum,pixels,exception);
1165 count=WriteBlob(image,length,pixels);
1166 if (count != (ssize_t) length)
1168 if (quantum_type == RGBAQuantum)
1170 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1171 AlphaQuantum,pixels,exception);
1172 count=WriteBlob(image,length,pixels);
1173 if (count != (ssize_t) length)
1176 if (image->previous == (Image *) NULL)
1178 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1180 if (status == MagickFalse)
1186 case PlaneInterlace:
1189 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1191 for (y=0; y < (ssize_t) image->rows; y++)
1193 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1194 if (p == (const Quantum *) NULL)
1196 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1197 RedQuantum,pixels,exception);
1198 count=WriteBlob(image,length,pixels);
1199 if (count != (ssize_t) length)
1202 if (image->previous == (Image *) NULL)
1204 status=SetImageProgress(image,SaveImageTag,1,5);
1205 if (status == MagickFalse)
1208 for (y=0; y < (ssize_t) image->rows; y++)
1210 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1211 if (p == (const Quantum *) NULL)
1213 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1214 GreenQuantum,pixels,exception);
1215 count=WriteBlob(image,length,pixels);
1216 if (count != (ssize_t) length)
1219 if (image->previous == (Image *) NULL)
1221 status=SetImageProgress(image,SaveImageTag,2,5);
1222 if (status == MagickFalse)
1225 for (y=0; y < (ssize_t) image->rows; y++)
1227 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1228 if (p == (const Quantum *) NULL)
1230 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1231 BlueQuantum,pixels,exception);
1232 count=WriteBlob(image,length,pixels);
1233 if (count != (ssize_t) length)
1236 if (image->previous == (Image *) NULL)
1238 status=SetImageProgress(image,SaveImageTag,3,5);
1239 if (status == MagickFalse)
1242 if (quantum_type == RGBAQuantum)
1244 for (y=0; y < (ssize_t) image->rows; y++)
1246 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1247 if (p == (const Quantum *) NULL)
1249 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1250 AlphaQuantum,pixels,exception);
1251 count=WriteBlob(image,length,pixels);
1252 if (count != (ssize_t) length)
1256 if (image_info->interlace == PartitionInterlace)
1257 (void) CopyMagickString(image->filename,image_info->filename,
1259 if (image->previous == (Image *) NULL)
1261 status=SetImageProgress(image,SaveImageTag,5,5);
1262 if (status == MagickFalse)
1267 case PartitionInterlace:
1270 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1272 AppendImageFormat("Y",image->filename);
1273 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1274 AppendBinaryBlobMode,exception);
1275 if (status == MagickFalse)
1277 for (y=0; y < (ssize_t) image->rows; y++)
1279 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1280 if (p == (const Quantum *) NULL)
1282 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1283 RedQuantum,pixels,exception);
1284 count=WriteBlob(image,length,pixels);
1285 if (count != (ssize_t) length)
1288 if (image->previous == (Image *) NULL)
1290 status=SetImageProgress(image,SaveImageTag,1,5);
1291 if (status == MagickFalse)
1294 (void) CloseBlob(image);
1295 AppendImageFormat("Cb",image->filename);
1296 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1297 AppendBinaryBlobMode,exception);
1298 if (status == MagickFalse)
1300 for (y=0; y < (ssize_t) image->rows; y++)
1302 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1303 if (p == (const Quantum *) NULL)
1305 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1306 GreenQuantum,pixels,exception);
1307 count=WriteBlob(image,length,pixels);
1308 if (count != (ssize_t) length)
1311 if (image->previous == (Image *) NULL)
1313 status=SetImageProgress(image,SaveImageTag,2,5);
1314 if (status == MagickFalse)
1317 (void) CloseBlob(image);
1318 AppendImageFormat("Cr",image->filename);
1319 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1320 AppendBinaryBlobMode,exception);
1321 if (status == MagickFalse)
1323 for (y=0; y < (ssize_t) image->rows; y++)
1325 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1326 if (p == (const Quantum *) NULL)
1328 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1329 BlueQuantum,pixels,exception);
1330 count=WriteBlob(image,length,pixels);
1331 if (count != (ssize_t) length)
1334 if (image->previous == (Image *) NULL)
1336 status=SetImageProgress(image,SaveImageTag,3,5);
1337 if (status == MagickFalse)
1340 if (quantum_type == RGBAQuantum)
1342 (void) CloseBlob(image);
1343 AppendImageFormat("A",image->filename);
1344 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1345 AppendBinaryBlobMode,exception);
1346 if (status == MagickFalse)
1348 for (y=0; y < (ssize_t) image->rows; y++)
1350 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1351 if (p == (const Quantum *) NULL)
1353 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1354 AlphaQuantum,pixels,exception);
1355 count=WriteBlob(image,length,pixels);
1356 if (count != (ssize_t) length)
1359 if (image->previous == (Image *) NULL)
1361 status=SetImageProgress(image,SaveImageTag,4,5);
1362 if (status == MagickFalse)
1366 (void) CloseBlob(image);
1367 (void) CopyMagickString(image->filename,image_info->filename,
1369 if (image->previous == (Image *) NULL)
1371 status=SetImageProgress(image,SaveImageTag,5,5);
1372 if (status == MagickFalse)
1378 quantum_info=DestroyQuantumInfo(quantum_info);
1379 if (GetNextImageInList(image) == (Image *) NULL)
1381 image=SyncNextImageInList(image);
1382 status=SetImageProgress(image,SaveImagesTag,scene++,
1383 GetImageListLength(image));
1384 if (status == MagickFalse)
1386 } while (image_info->adjoin != MagickFalse);
1387 (void) CloseBlob(image);