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-2014 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/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)
118 register const Quantum
141 assert(image_info != (const ImageInfo *) NULL);
142 assert(image_info->signature == MagickSignature);
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 == MagickSignature);
148 image=AcquireImage(image_info,exception);
149 if ((image->columns == 0) || (image->rows == 0))
150 ThrowReaderException(OptionError,"MustSpecifyImageSize");
151 SetImageColorspace(image,YCbCrColorspace,exception);
152 if (image_info->interlace != PartitionInterlace)
154 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
155 if (status == MagickFalse)
157 image=DestroyImageList(image);
158 return((Image *) NULL);
160 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
161 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
165 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
167 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
169 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
171 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
172 if (quantum_info == (QuantumInfo *) NULL)
173 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
174 pixels=GetQuantumPixels(quantum_info);
175 quantum_type=RGBQuantum;
176 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
178 quantum_type=RGBAQuantum;
179 image->alpha_trait=BlendPixelTrait;
181 if (image_info->number_scenes != 0)
182 while (image->scene < image_info->scene)
188 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
189 for (y=0; y < (ssize_t) image->rows; y++)
191 count=ReadBlob(image,length,pixels);
192 if (count != (ssize_t) length)
202 Read pixels to virtual canvas image then push to image.
204 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
205 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
207 SetImageColorspace(image,YCbCrColorspace,exception);
208 switch (image_info->interlace)
214 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
218 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
219 count=ReadBlob(image,length,pixels);
221 for (y=0; y < (ssize_t) image->extract_info.height; y++)
223 if (count != (ssize_t) length)
225 ThrowFileException(exception,CorruptImageError,
226 "UnexpectedEndOfFile",image->filename);
229 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
231 if (q == (Quantum *) NULL)
233 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
234 quantum_info,quantum_type,pixels,exception);
235 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
237 if (((y-image->extract_info.y) >= 0) &&
238 ((y-image->extract_info.y) < (ssize_t) image->rows))
240 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
241 canvas_image->columns,1,exception);
242 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
243 image->columns,1,exception);
244 if ((p == (const Quantum *) NULL) ||
245 (q == (Quantum *) NULL))
247 for (x=0; x < (ssize_t) image->columns; x++)
249 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
250 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
251 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
252 if (image->alpha_trait == BlendPixelTrait)
253 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
254 p+=GetPixelChannels(canvas_image);
255 q+=GetPixelChannels(image);
257 if (SyncAuthenticPixels(image,exception) == MagickFalse)
260 if (image->previous == (Image *) NULL)
262 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
264 if (status == MagickFalse)
267 count=ReadBlob(image,length,pixels);
283 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
287 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
288 count=ReadBlob(image,length,pixels);
290 for (y=0; y < (ssize_t) image->extract_info.height; y++)
292 for (i=0; i < (image->alpha_trait == BlendPixelTrait ? 4 : 3); i++)
294 if (count != (ssize_t) length)
296 ThrowFileException(exception,CorruptImageError,
297 "UnexpectedEndOfFile",image->filename);
300 quantum_type=quantum_types[i];
301 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
303 if (q == (Quantum *) NULL)
305 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
306 quantum_info,quantum_type,pixels,exception);
307 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
309 if (((y-image->extract_info.y) >= 0) &&
310 ((y-image->extract_info.y) < (ssize_t) image->rows))
312 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
313 0,canvas_image->columns,1,exception);
314 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
315 image->columns,1,exception);
316 if ((p == (const Quantum *) NULL) ||
317 (q == (Quantum *) NULL))
319 for (x=0; x < (ssize_t) image->columns; x++)
321 switch (quantum_type)
325 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
330 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
335 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
340 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
346 p+=GetPixelChannels(canvas_image);
347 q+=GetPixelChannels(image);
349 if (SyncAuthenticPixels(image,exception) == MagickFalse)
352 count=ReadBlob(image,length,pixels);
354 if (image->previous == (Image *) NULL)
356 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
358 if (status == MagickFalse)
367 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
371 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
372 count=ReadBlob(image,length,pixels);
374 for (y=0; y < (ssize_t) image->extract_info.height; y++)
376 if (count != (ssize_t) length)
378 ThrowFileException(exception,CorruptImageError,
379 "UnexpectedEndOfFile",image->filename);
382 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
384 if (q == (Quantum *) NULL)
386 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
387 quantum_info,RedQuantum,pixels,exception);
388 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
390 if (((y-image->extract_info.y) >= 0) &&
391 ((y-image->extract_info.y) < (ssize_t) image->rows))
393 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
394 canvas_image->columns,1,exception);
395 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
396 image->columns,1,exception);
397 if ((p == (const Quantum *) NULL) ||
398 (q == (Quantum *) NULL))
400 for (x=0; x < (ssize_t) image->columns; x++)
402 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
403 p+=GetPixelChannels(canvas_image);
404 q+=GetPixelChannels(image);
406 if (SyncAuthenticPixels(image,exception) == MagickFalse)
409 count=ReadBlob(image,length,pixels);
411 if (image->previous == (Image *) NULL)
413 status=SetImageProgress(image,LoadImageTag,1,5);
414 if (status == MagickFalse)
417 for (y=0; y < (ssize_t) image->extract_info.height; y++)
419 if (count != (ssize_t) length)
421 ThrowFileException(exception,CorruptImageError,
422 "UnexpectedEndOfFile",image->filename);
425 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
427 if (q == (Quantum *) NULL)
429 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
430 quantum_info,GreenQuantum,pixels,exception);
431 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
433 if (((y-image->extract_info.y) >= 0) &&
434 ((y-image->extract_info.y) < (ssize_t) image->rows))
436 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
437 canvas_image->columns,1,exception);
438 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
439 image->columns,1,exception);
440 if ((p == (const Quantum *) NULL) ||
441 (q == (Quantum *) NULL))
443 for (x=0; x < (ssize_t) image->columns; x++)
445 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
446 p+=GetPixelChannels(canvas_image);
447 q+=GetPixelChannels(image);
449 if (SyncAuthenticPixels(image,exception) == MagickFalse)
452 count=ReadBlob(image,length,pixels);
454 if (image->previous == (Image *) NULL)
456 status=SetImageProgress(image,LoadImageTag,2,5);
457 if (status == MagickFalse)
460 for (y=0; y < (ssize_t) image->extract_info.height; y++)
462 if (count != (ssize_t) length)
464 ThrowFileException(exception,CorruptImageError,
465 "UnexpectedEndOfFile",image->filename);
468 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
470 if (q == (Quantum *) NULL)
472 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
473 quantum_info,BlueQuantum,pixels,exception);
474 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
476 if (((y-image->extract_info.y) >= 0) &&
477 ((y-image->extract_info.y) < (ssize_t) image->rows))
479 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
480 canvas_image->columns,1,exception);
481 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
482 image->columns,1,exception);
483 if ((p == (const Quantum *) NULL) ||
484 (q == (Quantum *) NULL))
486 for (x=0; x < (ssize_t) image->columns; x++)
488 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
489 p+=GetPixelChannels(canvas_image);
490 q+=GetPixelChannels(image);
492 if (SyncAuthenticPixels(image,exception) == MagickFalse)
495 count=ReadBlob(image,length,pixels);
497 if (image->previous == (Image *) NULL)
499 status=SetImageProgress(image,LoadImageTag,3,5);
500 if (status == MagickFalse)
503 if (image->alpha_trait == BlendPixelTrait)
505 for (y=0; y < (ssize_t) image->extract_info.height; y++)
507 if (count != (ssize_t) length)
509 ThrowFileException(exception,CorruptImageError,
510 "UnexpectedEndOfFile",image->filename);
513 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
515 if (q == (Quantum *) NULL)
517 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
518 quantum_info,AlphaQuantum,pixels,exception);
519 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
521 if (((y-image->extract_info.y) >= 0) &&
522 ((y-image->extract_info.y) < (ssize_t) image->rows))
524 p=GetVirtualPixels(canvas_image,
525 canvas_image->extract_info.x,0,canvas_image->columns,1,
527 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
528 image->columns,1,exception);
529 if ((p == (const Quantum *) NULL) ||
530 (q == (Quantum *) NULL))
532 for (x=0; x < (ssize_t) image->columns; x++)
534 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
535 p+=GetPixelChannels(canvas_image);
536 q+=GetPixelChannels(image);
538 if (SyncAuthenticPixels(image,exception) == MagickFalse)
541 count=ReadBlob(image,length,pixels);
543 if (image->previous == (Image *) NULL)
545 status=SetImageProgress(image,LoadImageTag,4,5);
546 if (status == MagickFalse)
550 if (image->previous == (Image *) NULL)
552 status=SetImageProgress(image,LoadImageTag,5,5);
553 if (status == MagickFalse)
558 case PartitionInterlace:
561 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
563 AppendImageFormat("Y",image->filename);
564 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
565 if (status == MagickFalse)
567 canvas_image=DestroyImageList(canvas_image);
568 image=DestroyImageList(image);
569 return((Image *) NULL);
571 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
572 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
574 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
575 for (i=0; i < (ssize_t) scene; i++)
576 for (y=0; y < (ssize_t) image->extract_info.height; y++)
577 if (ReadBlob(image,length,pixels) != (ssize_t) length)
579 ThrowFileException(exception,CorruptImageError,
580 "UnexpectedEndOfFile",image->filename);
583 count=ReadBlob(image,length,pixels);
584 for (y=0; y < (ssize_t) image->extract_info.height; y++)
586 if (count != (ssize_t) length)
588 ThrowFileException(exception,CorruptImageError,
589 "UnexpectedEndOfFile",image->filename);
592 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
594 if (q == (Quantum *) NULL)
596 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
597 quantum_info,RedQuantum,pixels,exception);
598 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
600 if (((y-image->extract_info.y) >= 0) &&
601 ((y-image->extract_info.y) < (ssize_t) image->rows))
603 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
604 canvas_image->columns,1,exception);
605 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
606 image->columns,1,exception);
607 if ((p == (const Quantum *) NULL) ||
608 (q == (Quantum *) NULL))
610 for (x=0; x < (ssize_t) image->columns; x++)
612 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
613 p+=GetPixelChannels(canvas_image);
614 q+=GetPixelChannels(image);
616 if (SyncAuthenticPixels(image,exception) == MagickFalse)
619 count=ReadBlob(image,length,pixels);
621 if (image->previous == (Image *) NULL)
623 status=SetImageProgress(image,LoadImageTag,1,5);
624 if (status == MagickFalse)
627 (void) CloseBlob(image);
628 AppendImageFormat("Cb",image->filename);
629 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
630 if (status == MagickFalse)
632 canvas_image=DestroyImageList(canvas_image);
633 image=DestroyImageList(image);
634 return((Image *) NULL);
636 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
637 for (i=0; i < (ssize_t) scene; i++)
638 for (y=0; y < (ssize_t) image->extract_info.height; y++)
639 if (ReadBlob(image,length,pixels) != (ssize_t) length)
641 ThrowFileException(exception,CorruptImageError,
642 "UnexpectedEndOfFile",image->filename);
645 count=ReadBlob(image,length,pixels);
646 for (y=0; y < (ssize_t) image->extract_info.height; y++)
648 if (count != (ssize_t) length)
650 ThrowFileException(exception,CorruptImageError,
651 "UnexpectedEndOfFile",image->filename);
654 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
656 if (q == (Quantum *) NULL)
658 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
659 quantum_info,GreenQuantum,pixels,exception);
660 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
662 if (((y-image->extract_info.y) >= 0) &&
663 ((y-image->extract_info.y) < (ssize_t) image->rows))
665 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
666 canvas_image->columns,1,exception);
667 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
668 image->columns,1,exception);
669 if ((p == (const Quantum *) NULL) ||
670 (q == (Quantum *) NULL))
672 for (x=0; x < (ssize_t) image->columns; x++)
674 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
675 p+=GetPixelChannels(canvas_image);
676 q+=GetPixelChannels(image);
678 if (SyncAuthenticPixels(image,exception) == MagickFalse)
681 count=ReadBlob(image,length,pixels);
683 if (image->previous == (Image *) NULL)
685 status=SetImageProgress(image,LoadImageTag,2,5);
686 if (status == MagickFalse)
689 (void) CloseBlob(image);
690 AppendImageFormat("Cr",image->filename);
691 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
692 if (status == MagickFalse)
694 canvas_image=DestroyImageList(canvas_image);
695 image=DestroyImageList(image);
696 return((Image *) NULL);
698 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
699 for (i=0; i < (ssize_t) scene; i++)
700 for (y=0; y < (ssize_t) image->extract_info.height; y++)
701 if (ReadBlob(image,length,pixels) != (ssize_t) length)
703 ThrowFileException(exception,CorruptImageError,
704 "UnexpectedEndOfFile",image->filename);
707 count=ReadBlob(image,length,pixels);
708 for (y=0; y < (ssize_t) image->extract_info.height; y++)
710 if (count != (ssize_t) length)
712 ThrowFileException(exception,CorruptImageError,
713 "UnexpectedEndOfFile",image->filename);
716 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
718 if (q == (Quantum *) NULL)
720 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
721 quantum_info,BlueQuantum,pixels,exception);
722 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
724 if (((y-image->extract_info.y) >= 0) &&
725 ((y-image->extract_info.y) < (ssize_t) image->rows))
727 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
728 canvas_image->columns,1,exception);
729 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
730 image->columns,1,exception);
731 if ((p == (const Quantum *) NULL) ||
732 (q == (Quantum *) NULL))
734 for (x=0; x < (ssize_t) image->columns; x++)
736 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
737 p+=GetPixelChannels(canvas_image);
738 q+=GetPixelChannels(image);
740 if (SyncAuthenticPixels(image,exception) == MagickFalse)
743 count=ReadBlob(image,length,pixels);
745 if (image->previous == (Image *) NULL)
747 status=SetImageProgress(image,LoadImageTag,3,5);
748 if (status == MagickFalse)
751 if (image->alpha_trait == BlendPixelTrait)
753 (void) CloseBlob(image);
754 AppendImageFormat("A",image->filename);
755 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
756 if (status == MagickFalse)
758 canvas_image=DestroyImageList(canvas_image);
759 image=DestroyImageList(image);
760 return((Image *) NULL);
762 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
763 for (i=0; i < (ssize_t) scene; i++)
764 for (y=0; y < (ssize_t) image->extract_info.height; y++)
765 if (ReadBlob(image,length,pixels) != (ssize_t) length)
767 ThrowFileException(exception,CorruptImageError,
768 "UnexpectedEndOfFile",image->filename);
771 count=ReadBlob(image,length,pixels);
772 for (y=0; y < (ssize_t) image->extract_info.height; y++)
774 if (count != (ssize_t) length)
776 ThrowFileException(exception,CorruptImageError,
777 "UnexpectedEndOfFile",image->filename);
780 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
782 if (q == (Quantum *) NULL)
784 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
785 quantum_info,BlueQuantum,pixels,exception);
786 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
788 if (((y-image->extract_info.y) >= 0) &&
789 ((y-image->extract_info.y) < (ssize_t) image->rows))
791 p=GetVirtualPixels(canvas_image,
792 canvas_image->extract_info.x,0,canvas_image->columns,1,
794 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
795 image->columns,1,exception);
796 if ((p == (const Quantum *) NULL) ||
797 (q == (Quantum *) NULL))
799 for (x=0; x < (ssize_t) image->columns; x++)
801 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
802 p+=GetPixelChannels(canvas_image);
803 q+=GetPixelChannels(image);
805 if (SyncAuthenticPixels(image,exception) == MagickFalse)
808 count=ReadBlob(image,length,pixels);
810 if (image->previous == (Image *) NULL)
812 status=SetImageProgress(image,LoadImageTag,4,5);
813 if (status == MagickFalse)
817 if (image->previous == (Image *) NULL)
819 status=SetImageProgress(image,LoadImageTag,5,5);
820 if (status == MagickFalse)
826 SetQuantumImageType(image,quantum_type);
828 Proceed to next image.
830 if (image_info->number_scenes != 0)
831 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
833 if (count == (ssize_t) length)
836 Allocate next image structure.
838 AcquireNextImage(image_info,image,exception);
839 if (GetNextImageInList(image) == (Image *) NULL)
841 image=DestroyImageList(image);
842 return((Image *) NULL);
844 image=SyncNextImageInList(image);
845 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
847 if (status == MagickFalse)
851 } while (count == (ssize_t) length);
852 quantum_info=DestroyQuantumInfo(quantum_info);
853 canvas_image=DestroyImage(canvas_image);
854 (void) CloseBlob(image);
855 return(GetFirstImageInList(image));
859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
863 % R e g i s t e r Y C b C r I m a g e %
867 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
870 % the list of supported formats. The attributes include the image format
871 % tag, a method to read and/or write the format, whether the format
872 % supports the saving of more than one frame to the same file or blob,
873 % whether the format supports native in-memory I/O, and a brief
874 % description of the format.
876 % The format of the RegisterYCBCRImage method is:
878 % size_t RegisterYCBCRImage(void)
881 ModuleExport size_t RegisterYCBCRImage(void)
886 entry=SetMagickInfo("YCbCr");
887 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
888 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
889 entry->raw=MagickTrue;
890 entry->endian_support=MagickTrue;
891 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
892 entry->module=ConstantString("YCbCr");
893 (void) RegisterMagickInfo(entry);
894 entry=SetMagickInfo("YCbCrA");
895 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
896 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
897 entry->raw=MagickTrue;
898 entry->endian_support=MagickTrue;
899 entry->description=ConstantString("Raw Y, Cb, Cr, and alpha samples");
900 entry->module=ConstantString("YCbCr");
901 (void) RegisterMagickInfo(entry);
902 return(MagickImageCoderSignature);
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
910 % U n r e g i s t e r Y C b C r I m a g e %
914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 % UnregisterYCBCRImage() removes format registrations made by the
917 % YCbCr module from the list of supported formats.
919 % The format of the UnregisterYCBCRImage method is:
921 % UnregisterYCBCRImage(void)
924 ModuleExport void UnregisterYCBCRImage(void)
926 (void) UnregisterMagickInfo("YCbCr");
927 (void) UnregisterMagickInfo("YCbCrA");
931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
935 % W r i t e Y C b C r I m a g e %
939 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
941 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
944 % The format of the WriteYCBCRImage method is:
946 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
947 % Image *image,ExceptionInfo *exception)
949 % A description of each parameter follows.
951 % o image_info: the image info.
953 % o image: The image.
955 % o exception: return any errors or warnings in this structure.
958 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
959 Image *image,ExceptionInfo *exception)
973 register const Quantum
987 Allocate memory for pixels.
989 assert(image_info != (const ImageInfo *) NULL);
990 assert(image_info->signature == MagickSignature);
991 assert(image != (Image *) NULL);
992 assert(image->signature == MagickSignature);
993 if (image->debug != MagickFalse)
994 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
995 if (image_info->interlace != PartitionInterlace)
998 Open output image file.
1000 assert(exception != (ExceptionInfo *) NULL);
1001 assert(exception->signature == MagickSignature);
1002 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1003 if (status == MagickFalse)
1006 quantum_type=RGBQuantum;
1007 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1009 quantum_type=RGBAQuantum;
1010 image->alpha_trait=BlendPixelTrait;
1016 Convert MIFF to YCbCr raster pixels.
1018 if (image->colorspace != YCbCrColorspace)
1019 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1020 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1021 (image->alpha_trait != BlendPixelTrait))
1022 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1023 quantum_info=AcquireQuantumInfo(image_info,image);
1024 if (quantum_info == (QuantumInfo *) NULL)
1025 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1026 pixels=GetQuantumPixels(quantum_info);
1027 switch (image_info->interlace)
1033 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1035 for (y=0; y < (ssize_t) image->rows; y++)
1037 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1038 if (p == (const Quantum *) NULL)
1040 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1041 quantum_type,pixels,exception);
1042 count=WriteBlob(image,length,pixels);
1043 if (count != (ssize_t) length)
1045 if (image->previous == (Image *) NULL)
1047 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1049 if (status == MagickFalse)
1058 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1060 for (y=0; y < (ssize_t) image->rows; y++)
1062 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1063 if (p == (const Quantum *) NULL)
1065 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1066 RedQuantum,pixels,exception);
1067 count=WriteBlob(image,length,pixels);
1068 if (count != (ssize_t) length)
1070 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1071 GreenQuantum,pixels,exception);
1072 count=WriteBlob(image,length,pixels);
1073 if (count != (ssize_t) length)
1075 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1076 BlueQuantum,pixels,exception);
1077 count=WriteBlob(image,length,pixels);
1078 if (count != (ssize_t) length)
1080 if (quantum_type == RGBAQuantum)
1082 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1083 AlphaQuantum,pixels,exception);
1084 count=WriteBlob(image,length,pixels);
1085 if (count != (ssize_t) length)
1088 if (image->previous == (Image *) NULL)
1090 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1092 if (status == MagickFalse)
1098 case PlaneInterlace:
1101 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1103 for (y=0; y < (ssize_t) image->rows; y++)
1105 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1106 if (p == (const Quantum *) NULL)
1108 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1109 RedQuantum,pixels,exception);
1110 count=WriteBlob(image,length,pixels);
1111 if (count != (ssize_t) length)
1114 if (image->previous == (Image *) NULL)
1116 status=SetImageProgress(image,SaveImageTag,1,5);
1117 if (status == MagickFalse)
1120 for (y=0; y < (ssize_t) image->rows; y++)
1122 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1123 if (p == (const Quantum *) NULL)
1125 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1126 GreenQuantum,pixels,exception);
1127 count=WriteBlob(image,length,pixels);
1128 if (count != (ssize_t) length)
1131 if (image->previous == (Image *) NULL)
1133 status=SetImageProgress(image,SaveImageTag,2,5);
1134 if (status == MagickFalse)
1137 for (y=0; y < (ssize_t) image->rows; y++)
1139 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1140 if (p == (const Quantum *) NULL)
1142 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1143 BlueQuantum,pixels,exception);
1144 count=WriteBlob(image,length,pixels);
1145 if (count != (ssize_t) length)
1148 if (image->previous == (Image *) NULL)
1150 status=SetImageProgress(image,SaveImageTag,3,5);
1151 if (status == MagickFalse)
1154 if (quantum_type == RGBAQuantum)
1156 for (y=0; y < (ssize_t) image->rows; y++)
1158 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1159 if (p == (const Quantum *) NULL)
1161 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1162 AlphaQuantum,pixels,exception);
1163 count=WriteBlob(image,length,pixels);
1164 if (count != (ssize_t) length)
1168 if (image_info->interlace == PartitionInterlace)
1169 (void) CopyMagickString(image->filename,image_info->filename,
1171 if (image->previous == (Image *) NULL)
1173 status=SetImageProgress(image,SaveImageTag,5,5);
1174 if (status == MagickFalse)
1179 case PartitionInterlace:
1182 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1184 AppendImageFormat("Y",image->filename);
1185 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1186 AppendBinaryBlobMode,exception);
1187 if (status == MagickFalse)
1189 for (y=0; y < (ssize_t) image->rows; y++)
1191 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1192 if (p == (const Quantum *) NULL)
1194 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1195 RedQuantum,pixels,exception);
1196 count=WriteBlob(image,length,pixels);
1197 if (count != (ssize_t) length)
1200 if (image->previous == (Image *) NULL)
1202 status=SetImageProgress(image,SaveImageTag,1,5);
1203 if (status == MagickFalse)
1206 (void) CloseBlob(image);
1207 AppendImageFormat("Cb",image->filename);
1208 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1209 AppendBinaryBlobMode,exception);
1210 if (status == MagickFalse)
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 GreenQuantum,pixels,exception);
1219 count=WriteBlob(image,length,pixels);
1220 if (count != (ssize_t) length)
1223 if (image->previous == (Image *) NULL)
1225 status=SetImageProgress(image,SaveImageTag,2,5);
1226 if (status == MagickFalse)
1229 (void) CloseBlob(image);
1230 AppendImageFormat("Cr",image->filename);
1231 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1232 AppendBinaryBlobMode,exception);
1233 if (status == MagickFalse)
1235 for (y=0; y < (ssize_t) image->rows; y++)
1237 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1238 if (p == (const Quantum *) NULL)
1240 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1241 BlueQuantum,pixels,exception);
1242 count=WriteBlob(image,length,pixels);
1243 if (count != (ssize_t) length)
1246 if (image->previous == (Image *) NULL)
1248 status=SetImageProgress(image,SaveImageTag,3,5);
1249 if (status == MagickFalse)
1252 if (quantum_type == RGBAQuantum)
1254 (void) CloseBlob(image);
1255 AppendImageFormat("A",image->filename);
1256 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1257 AppendBinaryBlobMode,exception);
1258 if (status == MagickFalse)
1260 for (y=0; y < (ssize_t) image->rows; y++)
1262 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1263 if (p == (const Quantum *) NULL)
1265 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1266 AlphaQuantum,pixels,exception);
1267 count=WriteBlob(image,length,pixels);
1268 if (count != (ssize_t) length)
1271 if (image->previous == (Image *) NULL)
1273 status=SetImageProgress(image,SaveImageTag,4,5);
1274 if (status == MagickFalse)
1278 (void) CloseBlob(image);
1279 (void) CopyMagickString(image->filename,image_info->filename,
1281 if (image->previous == (Image *) NULL)
1283 status=SetImageProgress(image,SaveImageTag,5,5);
1284 if (status == MagickFalse)
1290 quantum_info=DestroyQuantumInfo(quantum_info);
1291 if (GetNextImageInList(image) == (Image *) NULL)
1293 image=SyncNextImageInList(image);
1294 status=SetImageProgress(image,SaveImagesTag,scene++,
1295 GetImageListLength(image));
1296 if (status == MagickFalse)
1298 } while (image_info->adjoin != MagickFalse);
1299 (void) CloseBlob(image);