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-2012 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/blob-private.h"
45 #include "MagickCore/cache.h"
46 #include "MagickCore/colorspace.h"
47 #include "MagickCore/constitute.h"
48 #include "MagickCore/exception.h"
49 #include "MagickCore/exception-private.h"
50 #include "MagickCore/image.h"
51 #include "MagickCore/image-private.h"
52 #include "MagickCore/list.h"
53 #include "MagickCore/magick.h"
54 #include "MagickCore/memory_.h"
55 #include "MagickCore/monitor.h"
56 #include "MagickCore/monitor-private.h"
57 #include "MagickCore/pixel-accessor.h"
58 #include "MagickCore/quantum-private.h"
59 #include "MagickCore/static.h"
60 #include "MagickCore/statistic.h"
61 #include "MagickCore/string_.h"
62 #include "MagickCore/module.h"
63 #include "MagickCore/utility.h"
68 static MagickBooleanType
69 WriteYCBCRImage(const ImageInfo *,Image *,ExceptionInfo *);
72 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
76 % R e a d Y C b C r I m a g e %
80 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82 % ReadYCBCRImage() reads an image of raw YCbCr or YCbCrA samples and returns
83 % it. It allocates the memory necessary for the new Image structure and
84 % returns a pointer to the new image.
86 % The format of the ReadYCBCRImage method is:
88 % Image *ReadYCBCRImage(const ImageInfo *image_info,
89 % ExceptionInfo *exception)
91 % A description of each parameter follows:
93 % o image_info: the image info.
95 % o exception: return any errors or warnings in this structure.
98 static Image *ReadYCBCRImage(const ImageInfo *image_info,
99 ExceptionInfo *exception)
117 register const Quantum
140 assert(image_info != (const ImageInfo *) NULL);
141 assert(image_info->signature == MagickSignature);
142 if (image_info->debug != MagickFalse)
143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
144 image_info->filename);
145 assert(exception != (ExceptionInfo *) NULL);
146 assert(exception->signature == MagickSignature);
147 image=AcquireImage(image_info,exception);
148 if ((image->columns == 0) || (image->rows == 0))
149 ThrowReaderException(OptionError,"MustSpecifyImageSize");
150 SetImageColorspace(image,YCbCrColorspace,exception);
151 if (image_info->interlace != PartitionInterlace)
153 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
154 if (status == MagickFalse)
156 image=DestroyImageList(image);
157 return((Image *) NULL);
159 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
160 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
164 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
166 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
168 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
170 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
171 if (quantum_info == (QuantumInfo *) NULL)
172 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
173 pixels=GetQuantumPixels(quantum_info);
174 quantum_type=RGBQuantum;
175 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
177 quantum_type=RGBAQuantum;
178 image->matte=MagickTrue;
180 if (image_info->number_scenes != 0)
181 while (image->scene < image_info->scene)
187 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
188 for (y=0; y < (ssize_t) image->rows; y++)
190 count=ReadBlob(image,length,pixels);
191 if (count != (ssize_t) length)
201 Read pixels to virtual canvas image then push to image.
203 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
204 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
206 SetImageColorspace(image,YCbCrColorspace,exception);
207 switch (image_info->interlace)
213 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
217 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
218 count=ReadBlob(image,length,pixels);
220 for (y=0; y < (ssize_t) image->extract_info.height; y++)
222 if (count != (ssize_t) length)
224 ThrowFileException(exception,CorruptImageError,
225 "UnexpectedEndOfFile",image->filename);
228 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
230 if (q == (Quantum *) NULL)
232 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
233 quantum_info,quantum_type,pixels,exception);
234 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
236 if (((y-image->extract_info.y) >= 0) &&
237 ((y-image->extract_info.y) < (ssize_t) image->rows))
239 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
240 canvas_image->columns,1,exception);
241 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
242 image->columns,1,exception);
243 if ((p == (const Quantum *) NULL) ||
244 (q == (Quantum *) NULL))
246 for (x=0; x < (ssize_t) image->columns; x++)
248 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
249 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
250 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
251 if (image->matte != MagickFalse)
252 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
253 p+=GetPixelChannels(canvas_image);
254 q+=GetPixelChannels(image);
256 if (SyncAuthenticPixels(image,exception) == MagickFalse)
259 if (image->previous == (Image *) NULL)
261 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
263 if (status == MagickFalse)
266 count=ReadBlob(image,length,pixels);
282 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
286 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
287 count=ReadBlob(image,length,pixels);
289 for (y=0; y < (ssize_t) image->extract_info.height; y++)
291 for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
293 if (count != (ssize_t) length)
295 ThrowFileException(exception,CorruptImageError,
296 "UnexpectedEndOfFile",image->filename);
299 quantum_type=quantum_types[i];
300 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
302 if (q == (Quantum *) NULL)
304 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
305 quantum_info,quantum_type,pixels,exception);
306 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
308 if (((y-image->extract_info.y) >= 0) &&
309 ((y-image->extract_info.y) < (ssize_t) image->rows))
311 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
312 0,canvas_image->columns,1,exception);
313 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
314 image->columns,1,exception);
315 if ((p == (const Quantum *) NULL) ||
316 (q == (Quantum *) NULL))
318 for (x=0; x < (ssize_t) image->columns; x++)
320 switch (quantum_type)
324 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
329 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
334 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
339 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
345 p+=GetPixelChannels(canvas_image);
346 q+=GetPixelChannels(image);
348 if (SyncAuthenticPixels(image,exception) == MagickFalse)
351 count=ReadBlob(image,length,pixels);
353 if (image->previous == (Image *) NULL)
355 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
357 if (status == MagickFalse)
366 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
370 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
371 count=ReadBlob(image,length,pixels);
373 for (y=0; y < (ssize_t) image->extract_info.height; y++)
375 if (count != (ssize_t) length)
377 ThrowFileException(exception,CorruptImageError,
378 "UnexpectedEndOfFile",image->filename);
381 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
383 if (q == (Quantum *) NULL)
385 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
386 quantum_info,RedQuantum,pixels,exception);
387 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
389 if (((y-image->extract_info.y) >= 0) &&
390 ((y-image->extract_info.y) < (ssize_t) image->rows))
392 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
393 canvas_image->columns,1,exception);
394 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
395 image->columns,1,exception);
396 if ((p == (const Quantum *) NULL) ||
397 (q == (Quantum *) NULL))
399 for (x=0; x < (ssize_t) image->columns; x++)
401 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
402 p+=GetPixelChannels(canvas_image);
403 q+=GetPixelChannels(image);
405 if (SyncAuthenticPixels(image,exception) == MagickFalse)
408 count=ReadBlob(image,length,pixels);
410 if (image->previous == (Image *) NULL)
412 status=SetImageProgress(image,LoadImageTag,1,5);
413 if (status == MagickFalse)
416 for (y=0; y < (ssize_t) image->extract_info.height; y++)
418 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,GreenQuantum,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 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
445 p+=GetPixelChannels(canvas_image);
446 q+=GetPixelChannels(image);
448 if (SyncAuthenticPixels(image,exception) == MagickFalse)
451 count=ReadBlob(image,length,pixels);
453 if (image->previous == (Image *) NULL)
455 status=SetImageProgress(image,LoadImageTag,2,5);
456 if (status == MagickFalse)
459 for (y=0; y < (ssize_t) image->extract_info.height; y++)
461 if (count != (ssize_t) length)
463 ThrowFileException(exception,CorruptImageError,
464 "UnexpectedEndOfFile",image->filename);
467 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
469 if (q == (Quantum *) NULL)
471 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
472 quantum_info,BlueQuantum,pixels,exception);
473 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
475 if (((y-image->extract_info.y) >= 0) &&
476 ((y-image->extract_info.y) < (ssize_t) image->rows))
478 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
479 canvas_image->columns,1,exception);
480 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
481 image->columns,1,exception);
482 if ((p == (const Quantum *) NULL) ||
483 (q == (Quantum *) NULL))
485 for (x=0; x < (ssize_t) image->columns; x++)
487 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
488 p+=GetPixelChannels(canvas_image);
489 q+=GetPixelChannels(image);
491 if (SyncAuthenticPixels(image,exception) == MagickFalse)
494 count=ReadBlob(image,length,pixels);
496 if (image->previous == (Image *) NULL)
498 status=SetImageProgress(image,LoadImageTag,3,5);
499 if (status == MagickFalse)
502 if (image->matte != MagickFalse)
504 for (y=0; y < (ssize_t) image->extract_info.height; y++)
506 if (count != (ssize_t) length)
508 ThrowFileException(exception,CorruptImageError,
509 "UnexpectedEndOfFile",image->filename);
512 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
514 if (q == (Quantum *) NULL)
516 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
517 quantum_info,AlphaQuantum,pixels,exception);
518 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
520 if (((y-image->extract_info.y) >= 0) &&
521 ((y-image->extract_info.y) < (ssize_t) image->rows))
523 p=GetVirtualPixels(canvas_image,
524 canvas_image->extract_info.x,0,canvas_image->columns,1,
526 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
527 image->columns,1,exception);
528 if ((p == (const Quantum *) NULL) ||
529 (q == (Quantum *) NULL))
531 for (x=0; x < (ssize_t) image->columns; x++)
533 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
534 p+=GetPixelChannels(canvas_image);
535 q+=GetPixelChannels(image);
537 if (SyncAuthenticPixels(image,exception) == MagickFalse)
540 count=ReadBlob(image,length,pixels);
542 if (image->previous == (Image *) NULL)
544 status=SetImageProgress(image,LoadImageTag,4,5);
545 if (status == MagickFalse)
549 if (image->previous == (Image *) NULL)
551 status=SetImageProgress(image,LoadImageTag,5,5);
552 if (status == MagickFalse)
557 case PartitionInterlace:
560 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
562 AppendImageFormat("Y",image->filename);
563 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
564 if (status == MagickFalse)
566 canvas_image=DestroyImageList(canvas_image);
567 image=DestroyImageList(image);
568 return((Image *) NULL);
570 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
571 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
573 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
574 for (i=0; i < (ssize_t) scene; i++)
575 for (y=0; y < (ssize_t) image->extract_info.height; y++)
576 if (ReadBlob(image,length,pixels) != (ssize_t) length)
578 ThrowFileException(exception,CorruptImageError,
579 "UnexpectedEndOfFile",image->filename);
582 count=ReadBlob(image,length,pixels);
583 for (y=0; y < (ssize_t) image->extract_info.height; y++)
585 if (count != (ssize_t) length)
587 ThrowFileException(exception,CorruptImageError,
588 "UnexpectedEndOfFile",image->filename);
591 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
593 if (q == (Quantum *) NULL)
595 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
596 quantum_info,RedQuantum,pixels,exception);
597 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
599 if (((y-image->extract_info.y) >= 0) &&
600 ((y-image->extract_info.y) < (ssize_t) image->rows))
602 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
603 canvas_image->columns,1,exception);
604 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
605 image->columns,1,exception);
606 if ((p == (const Quantum *) NULL) ||
607 (q == (Quantum *) NULL))
609 for (x=0; x < (ssize_t) image->columns; x++)
611 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
612 p+=GetPixelChannels(canvas_image);
613 q+=GetPixelChannels(image);
615 if (SyncAuthenticPixels(image,exception) == MagickFalse)
618 count=ReadBlob(image,length,pixels);
620 if (image->previous == (Image *) NULL)
622 status=SetImageProgress(image,LoadImageTag,1,5);
623 if (status == MagickFalse)
626 (void) CloseBlob(image);
627 AppendImageFormat("Cb",image->filename);
628 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
629 if (status == MagickFalse)
631 canvas_image=DestroyImageList(canvas_image);
632 image=DestroyImageList(image);
633 return((Image *) NULL);
635 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
636 for (i=0; i < (ssize_t) scene; i++)
637 for (y=0; y < (ssize_t) image->extract_info.height; y++)
638 if (ReadBlob(image,length,pixels) != (ssize_t) length)
640 ThrowFileException(exception,CorruptImageError,
641 "UnexpectedEndOfFile",image->filename);
644 count=ReadBlob(image,length,pixels);
645 for (y=0; y < (ssize_t) image->extract_info.height; y++)
647 if (count != (ssize_t) length)
649 ThrowFileException(exception,CorruptImageError,
650 "UnexpectedEndOfFile",image->filename);
653 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
655 if (q == (Quantum *) NULL)
657 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
658 quantum_info,GreenQuantum,pixels,exception);
659 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
661 if (((y-image->extract_info.y) >= 0) &&
662 ((y-image->extract_info.y) < (ssize_t) image->rows))
664 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
665 canvas_image->columns,1,exception);
666 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
667 image->columns,1,exception);
668 if ((p == (const Quantum *) NULL) ||
669 (q == (Quantum *) NULL))
671 for (x=0; x < (ssize_t) image->columns; x++)
673 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
674 p+=GetPixelChannels(canvas_image);
675 q+=GetPixelChannels(image);
677 if (SyncAuthenticPixels(image,exception) == MagickFalse)
680 count=ReadBlob(image,length,pixels);
682 if (image->previous == (Image *) NULL)
684 status=SetImageProgress(image,LoadImageTag,2,5);
685 if (status == MagickFalse)
688 (void) CloseBlob(image);
689 AppendImageFormat("Cr",image->filename);
690 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
691 if (status == MagickFalse)
693 canvas_image=DestroyImageList(canvas_image);
694 image=DestroyImageList(image);
695 return((Image *) NULL);
697 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
698 for (i=0; i < (ssize_t) scene; i++)
699 for (y=0; y < (ssize_t) image->extract_info.height; y++)
700 if (ReadBlob(image,length,pixels) != (ssize_t) length)
702 ThrowFileException(exception,CorruptImageError,
703 "UnexpectedEndOfFile",image->filename);
706 count=ReadBlob(image,length,pixels);
707 for (y=0; y < (ssize_t) image->extract_info.height; y++)
709 if (count != (ssize_t) length)
711 ThrowFileException(exception,CorruptImageError,
712 "UnexpectedEndOfFile",image->filename);
715 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
717 if (q == (Quantum *) NULL)
719 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
720 quantum_info,BlueQuantum,pixels,exception);
721 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
723 if (((y-image->extract_info.y) >= 0) &&
724 ((y-image->extract_info.y) < (ssize_t) image->rows))
726 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
727 canvas_image->columns,1,exception);
728 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
729 image->columns,1,exception);
730 if ((p == (const Quantum *) NULL) ||
731 (q == (Quantum *) NULL))
733 for (x=0; x < (ssize_t) image->columns; x++)
735 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
736 p+=GetPixelChannels(canvas_image);
737 q+=GetPixelChannels(image);
739 if (SyncAuthenticPixels(image,exception) == MagickFalse)
742 count=ReadBlob(image,length,pixels);
744 if (image->previous == (Image *) NULL)
746 status=SetImageProgress(image,LoadImageTag,3,5);
747 if (status == MagickFalse)
750 if (image->matte != MagickFalse)
752 (void) CloseBlob(image);
753 AppendImageFormat("A",image->filename);
754 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
755 if (status == MagickFalse)
757 canvas_image=DestroyImageList(canvas_image);
758 image=DestroyImageList(image);
759 return((Image *) NULL);
761 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
762 for (i=0; i < (ssize_t) scene; i++)
763 for (y=0; y < (ssize_t) image->extract_info.height; y++)
764 if (ReadBlob(image,length,pixels) != (ssize_t) length)
766 ThrowFileException(exception,CorruptImageError,
767 "UnexpectedEndOfFile",image->filename);
770 count=ReadBlob(image,length,pixels);
771 for (y=0; y < (ssize_t) image->extract_info.height; y++)
773 if (count != (ssize_t) length)
775 ThrowFileException(exception,CorruptImageError,
776 "UnexpectedEndOfFile",image->filename);
779 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
781 if (q == (Quantum *) NULL)
783 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
784 quantum_info,BlueQuantum,pixels,exception);
785 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
787 if (((y-image->extract_info.y) >= 0) &&
788 ((y-image->extract_info.y) < (ssize_t) image->rows))
790 p=GetVirtualPixels(canvas_image,
791 canvas_image->extract_info.x,0,canvas_image->columns,1,
793 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
794 image->columns,1,exception);
795 if ((p == (const Quantum *) NULL) ||
796 (q == (Quantum *) NULL))
798 for (x=0; x < (ssize_t) image->columns; x++)
800 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
801 p+=GetPixelChannels(canvas_image);
802 q+=GetPixelChannels(image);
804 if (SyncAuthenticPixels(image,exception) == MagickFalse)
807 count=ReadBlob(image,length,pixels);
809 if (image->previous == (Image *) NULL)
811 status=SetImageProgress(image,LoadImageTag,4,5);
812 if (status == MagickFalse)
816 if (image->previous == (Image *) NULL)
818 status=SetImageProgress(image,LoadImageTag,5,5);
819 if (status == MagickFalse)
825 SetQuantumImageType(image,quantum_type);
827 Proceed to next image.
829 if (image_info->number_scenes != 0)
830 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
832 if (count == (ssize_t) length)
835 Allocate next image structure.
837 AcquireNextImage(image_info,image,exception);
838 if (GetNextImageInList(image) == (Image *) NULL)
840 image=DestroyImageList(image);
841 return((Image *) NULL);
843 image=SyncNextImageInList(image);
844 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
846 if (status == MagickFalse)
850 } while (count == (ssize_t) length);
851 quantum_info=DestroyQuantumInfo(quantum_info);
852 canvas_image=DestroyImage(canvas_image);
853 (void) CloseBlob(image);
854 return(GetFirstImageInList(image));
858 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
862 % R e g i s t e r Y C b C r I m a g e %
866 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
868 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
869 % the list of supported formats. The attributes include the image format
870 % tag, a method to read and/or write the format, whether the format
871 % supports the saving of more than one frame to the same file or blob,
872 % whether the format supports native in-memory I/O, and a brief
873 % description of the format.
875 % The format of the RegisterYCBCRImage method is:
877 % size_t RegisterYCBCRImage(void)
880 ModuleExport size_t RegisterYCBCRImage(void)
885 entry=SetMagickInfo("YCbCr");
886 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
887 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
888 entry->raw=MagickTrue;
889 entry->endian_support=MagickTrue;
890 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
891 entry->module=ConstantString("YCbCr");
892 (void) RegisterMagickInfo(entry);
893 entry=SetMagickInfo("YCbCrA");
894 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
895 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
896 entry->raw=MagickTrue;
897 entry->endian_support=MagickTrue;
898 entry->description=ConstantString("Raw Y, Cb, Cr, and alpha samples");
899 entry->module=ConstantString("YCbCr");
900 (void) RegisterMagickInfo(entry);
901 return(MagickImageCoderSignature);
905 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 % U n r e g i s t e r Y C b C r I m a g e %
913 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
915 % UnregisterYCBCRImage() removes format registrations made by the
916 % YCbCr module from the list of supported formats.
918 % The format of the UnregisterYCBCRImage method is:
920 % UnregisterYCBCRImage(void)
923 ModuleExport void UnregisterYCBCRImage(void)
925 (void) UnregisterMagickInfo("YCbCr");
926 (void) UnregisterMagickInfo("YCbCrA");
930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
934 % W r i t e Y C b C r I m a g e %
938 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
940 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
943 % The format of the WriteYCBCRImage method is:
945 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
946 % Image *image,ExceptionInfo *exception)
948 % A description of each parameter follows.
950 % o image_info: the image info.
952 % o image: The image.
954 % o exception: return any errors or warnings in this structure.
957 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
958 Image *image,ExceptionInfo *exception)
972 register const Quantum
986 Allocate memory for pixels.
988 assert(image_info != (const ImageInfo *) NULL);
989 assert(image_info->signature == MagickSignature);
990 assert(image != (Image *) NULL);
991 assert(image->signature == MagickSignature);
992 if (image->debug != MagickFalse)
993 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
994 if (image_info->interlace != PartitionInterlace)
997 Open output image file.
999 assert(exception != (ExceptionInfo *) NULL);
1000 assert(exception->signature == MagickSignature);
1001 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1002 if (status == MagickFalse)
1005 quantum_type=RGBQuantum;
1006 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1008 quantum_type=RGBAQuantum;
1009 image->matte=MagickTrue;
1015 Convert MIFF to YCbCr raster pixels.
1017 if (image->colorspace != YCbCrColorspace)
1018 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1019 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1020 (image->matte == MagickFalse))
1021 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1022 quantum_info=AcquireQuantumInfo(image_info,image);
1023 if (quantum_info == (QuantumInfo *) NULL)
1024 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1025 pixels=GetQuantumPixels(quantum_info);
1026 switch (image_info->interlace)
1032 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1034 for (y=0; y < (ssize_t) image->rows; y++)
1036 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1037 if (p == (const Quantum *) NULL)
1039 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1040 quantum_type,pixels,exception);
1041 count=WriteBlob(image,length,pixels);
1042 if (count != (ssize_t) length)
1044 if (image->previous == (Image *) NULL)
1046 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1048 if (status == MagickFalse)
1057 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1059 for (y=0; y < (ssize_t) image->rows; y++)
1061 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1062 if (p == (const Quantum *) NULL)
1064 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1065 RedQuantum,pixels,exception);
1066 count=WriteBlob(image,length,pixels);
1067 if (count != (ssize_t) length)
1069 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1070 GreenQuantum,pixels,exception);
1071 count=WriteBlob(image,length,pixels);
1072 if (count != (ssize_t) length)
1074 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1075 BlueQuantum,pixels,exception);
1076 count=WriteBlob(image,length,pixels);
1077 if (count != (ssize_t) length)
1079 if (quantum_type == RGBAQuantum)
1081 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1082 AlphaQuantum,pixels,exception);
1083 count=WriteBlob(image,length,pixels);
1084 if (count != (ssize_t) length)
1087 if (image->previous == (Image *) NULL)
1089 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1091 if (status == MagickFalse)
1097 case PlaneInterlace:
1100 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1102 for (y=0; y < (ssize_t) image->rows; y++)
1104 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1105 if (p == (const Quantum *) NULL)
1107 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1108 RedQuantum,pixels,exception);
1109 count=WriteBlob(image,length,pixels);
1110 if (count != (ssize_t) length)
1113 if (image->previous == (Image *) NULL)
1115 status=SetImageProgress(image,SaveImageTag,1,5);
1116 if (status == MagickFalse)
1119 for (y=0; y < (ssize_t) image->rows; y++)
1121 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1122 if (p == (const Quantum *) NULL)
1124 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1125 GreenQuantum,pixels,exception);
1126 count=WriteBlob(image,length,pixels);
1127 if (count != (ssize_t) length)
1130 if (image->previous == (Image *) NULL)
1132 status=SetImageProgress(image,SaveImageTag,2,5);
1133 if (status == MagickFalse)
1136 for (y=0; y < (ssize_t) image->rows; y++)
1138 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1139 if (p == (const Quantum *) NULL)
1141 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1142 BlueQuantum,pixels,exception);
1143 count=WriteBlob(image,length,pixels);
1144 if (count != (ssize_t) length)
1147 if (image->previous == (Image *) NULL)
1149 status=SetImageProgress(image,SaveImageTag,3,5);
1150 if (status == MagickFalse)
1153 if (quantum_type == RGBAQuantum)
1155 for (y=0; y < (ssize_t) image->rows; y++)
1157 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1158 if (p == (const Quantum *) NULL)
1160 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1161 AlphaQuantum,pixels,exception);
1162 count=WriteBlob(image,length,pixels);
1163 if (count != (ssize_t) length)
1167 if (image_info->interlace == PartitionInterlace)
1168 (void) CopyMagickString(image->filename,image_info->filename,
1170 if (image->previous == (Image *) NULL)
1172 status=SetImageProgress(image,SaveImageTag,5,5);
1173 if (status == MagickFalse)
1178 case PartitionInterlace:
1181 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1183 AppendImageFormat("Y",image->filename);
1184 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1185 AppendBinaryBlobMode,exception);
1186 if (status == MagickFalse)
1188 for (y=0; y < (ssize_t) image->rows; y++)
1190 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1191 if (p == (const Quantum *) NULL)
1193 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1194 RedQuantum,pixels,exception);
1195 count=WriteBlob(image,length,pixels);
1196 if (count != (ssize_t) length)
1199 if (image->previous == (Image *) NULL)
1201 status=SetImageProgress(image,SaveImageTag,1,5);
1202 if (status == MagickFalse)
1205 (void) CloseBlob(image);
1206 AppendImageFormat("Cb",image->filename);
1207 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1208 AppendBinaryBlobMode,exception);
1209 if (status == MagickFalse)
1211 for (y=0; y < (ssize_t) image->rows; y++)
1213 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1214 if (p == (const Quantum *) NULL)
1216 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1217 GreenQuantum,pixels,exception);
1218 count=WriteBlob(image,length,pixels);
1219 if (count != (ssize_t) length)
1222 if (image->previous == (Image *) NULL)
1224 status=SetImageProgress(image,SaveImageTag,2,5);
1225 if (status == MagickFalse)
1228 (void) CloseBlob(image);
1229 AppendImageFormat("Cr",image->filename);
1230 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1231 AppendBinaryBlobMode,exception);
1232 if (status == MagickFalse)
1234 for (y=0; y < (ssize_t) image->rows; y++)
1236 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1237 if (p == (const Quantum *) NULL)
1239 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1240 BlueQuantum,pixels,exception);
1241 count=WriteBlob(image,length,pixels);
1242 if (count != (ssize_t) length)
1245 if (image->previous == (Image *) NULL)
1247 status=SetImageProgress(image,SaveImageTag,3,5);
1248 if (status == MagickFalse)
1251 if (quantum_type == RGBAQuantum)
1253 (void) CloseBlob(image);
1254 AppendImageFormat("A",image->filename);
1255 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1256 AppendBinaryBlobMode,exception);
1257 if (status == MagickFalse)
1259 for (y=0; y < (ssize_t) image->rows; y++)
1261 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1262 if (p == (const Quantum *) NULL)
1264 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1265 AlphaQuantum,pixels,exception);
1266 count=WriteBlob(image,length,pixels);
1267 if (count != (ssize_t) length)
1270 if (image->previous == (Image *) NULL)
1272 status=SetImageProgress(image,SaveImageTag,4,5);
1273 if (status == MagickFalse)
1277 (void) CloseBlob(image);
1278 (void) CopyMagickString(image->filename,image_info->filename,
1280 if (image->previous == (Image *) NULL)
1282 status=SetImageProgress(image,SaveImageTag,5,5);
1283 if (status == MagickFalse)
1289 quantum_info=DestroyQuantumInfo(quantum_info);
1290 if (GetNextImageInList(image) == (Image *) NULL)
1292 image=SyncNextImageInList(image);
1293 status=SetImageProgress(image,SaveImagesTag,scene++,
1294 GetImageListLength(image));
1295 if (status == MagickFalse)
1297 } while (image_info->adjoin != MagickFalse);
1298 (void) CloseBlob(image);