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-2010 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 "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/colorspace.h"
47 #include "magick/constitute.h"
48 #include "magick/exception.h"
49 #include "magick/exception-private.h"
50 #include "magick/image.h"
51 #include "magick/image-private.h"
52 #include "magick/list.h"
53 #include "magick/magick.h"
54 #include "magick/memory_.h"
55 #include "magick/monitor.h"
56 #include "magick/monitor-private.h"
57 #include "magick/pixel-private.h"
58 #include "magick/quantum-private.h"
59 #include "magick/static.h"
60 #include "magick/statistic.h"
61 #include "magick/string_.h"
62 #include "magick/module.h"
63 #include "magick/utility.h"
68 static MagickBooleanType
69 WriteYCBCRImage(const ImageInfo *,Image *);
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)
120 register const PixelPacket
142 assert(image_info != (const ImageInfo *) NULL);
143 assert(image_info->signature == MagickSignature);
144 if (image_info->debug != MagickFalse)
145 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
146 image_info->filename);
147 assert(exception != (ExceptionInfo *) NULL);
148 assert(exception->signature == MagickSignature);
149 image=AcquireImage(image_info);
150 if ((image->columns == 0) || (image->rows == 0))
151 ThrowReaderException(OptionError,"MustSpecifyImageSize");
152 image->colorspace=YCbCrColorspace;
153 if (image_info->interlace != PartitionInterlace)
155 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
156 if (status == MagickFalse)
158 image=DestroyImageList(image);
159 return((Image *) NULL);
161 for (i=0; i < image->offset; i++)
162 if (ReadBlobByte(image) == EOF)
164 ThrowFileException(exception,CorruptImageError,
165 "UnexpectedEndOfFile",image->filename);
170 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
172 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
174 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod);
175 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
176 if (quantum_info == (QuantumInfo *) NULL)
177 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
178 pixels=GetQuantumPixels(quantum_info);
179 quantum_type=RGBQuantum;
180 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
182 quantum_type=RGBAQuantum;
183 image->matte=MagickTrue;
185 if (image_info->number_scenes != 0)
186 while (image->scene < image_info->scene)
192 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
193 for (y=0; y < (ssize_t) image->rows; y++)
195 count=ReadBlob(image,length,pixels);
196 if (count != (ssize_t) length)
206 Read pixels to virtual canvas image then push to image.
208 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
209 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
211 image->colorspace=YCbCrColorspace;
212 switch (image_info->interlace)
218 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
222 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
223 count=ReadBlob(image,length,pixels);
225 for (y=0; y < (ssize_t) image->extract_info.height; y++)
227 if (count != (ssize_t) length)
229 ThrowFileException(exception,CorruptImageError,
230 "UnexpectedEndOfFile",image->filename);
233 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
235 if (q == (PixelPacket *) NULL)
237 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
238 quantum_info,quantum_type,pixels,exception);
239 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
241 if (((y-image->extract_info.y) >= 0) &&
242 ((y-image->extract_info.y) < (ssize_t) image->rows))
244 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
245 canvas_image->columns,1,exception);
246 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
247 image->columns,1,exception);
248 if ((p == (const PixelPacket *) NULL) ||
249 (q == (PixelPacket *) NULL))
251 for (x=0; x < (ssize_t) image->columns; x++)
253 SetRedPixelComponent(q,GetRedPixelComponent(p));
254 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
255 SetBluePixelComponent(q,GetBluePixelComponent(p));
256 if (image->matte != MagickFalse)
257 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
261 if (SyncAuthenticPixels(image,exception) == MagickFalse)
264 if (image->previous == (Image *) NULL)
266 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
268 if (status == MagickFalse)
271 count=ReadBlob(image,length,pixels);
287 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
291 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
292 count=ReadBlob(image,length,pixels);
294 for (y=0; y < (ssize_t) image->extract_info.height; y++)
296 for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
298 if (count != (ssize_t) length)
300 ThrowFileException(exception,CorruptImageError,
301 "UnexpectedEndOfFile",image->filename);
304 quantum_type=quantum_types[i];
305 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
307 if (q == (PixelPacket *) NULL)
309 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
310 quantum_info,quantum_type,pixels,exception);
311 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
313 if (((y-image->extract_info.y) >= 0) &&
314 ((y-image->extract_info.y) < (ssize_t) image->rows))
316 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
317 0,canvas_image->columns,1,exception);
318 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
319 image->columns,1,exception);
320 if ((p == (const PixelPacket *) NULL) ||
321 (q == (PixelPacket *) NULL))
323 for (x=0; x < (ssize_t) image->columns; x++)
325 switch (quantum_type)
327 case RedQuantum: SetRedPixelComponent(q,GetRedPixelComponent(p)); break;
328 case GreenQuantum: SetGreenPixelComponent(q,GetGreenPixelComponent(p)); break;
329 case BlueQuantum: SetBluePixelComponent(q,GetBluePixelComponent(p)); break;
330 case OpacityQuantum: SetOpacityPixelComponent(q,GetOpacityPixelComponent(p)); break;
336 if (SyncAuthenticPixels(image,exception) == MagickFalse)
339 count=ReadBlob(image,length,pixels);
341 if (image->previous == (Image *) NULL)
343 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
345 if (status == MagickFalse)
354 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
358 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
359 count=ReadBlob(image,length,pixels);
361 for (y=0; y < (ssize_t) image->extract_info.height; y++)
363 if (count != (ssize_t) length)
365 ThrowFileException(exception,CorruptImageError,
366 "UnexpectedEndOfFile",image->filename);
369 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
371 if (q == (PixelPacket *) NULL)
373 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
374 quantum_info,RedQuantum,pixels,exception);
375 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
377 if (((y-image->extract_info.y) >= 0) &&
378 ((y-image->extract_info.y) < (ssize_t) image->rows))
380 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
381 canvas_image->columns,1,exception);
382 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
383 image->columns,1,exception);
384 if ((p == (const PixelPacket *) NULL) ||
385 (q == (PixelPacket *) NULL))
387 for (x=0; x < (ssize_t) image->columns; x++)
389 SetRedPixelComponent(q,GetRedPixelComponent(p));
393 if (SyncAuthenticPixels(image,exception) == MagickFalse)
396 count=ReadBlob(image,length,pixels);
398 if (image->previous == (Image *) NULL)
400 status=SetImageProgress(image,LoadImageTag,1,5);
401 if (status == MagickFalse)
404 for (y=0; y < (ssize_t) image->extract_info.height; y++)
406 if (count != (ssize_t) length)
408 ThrowFileException(exception,CorruptImageError,
409 "UnexpectedEndOfFile",image->filename);
412 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
414 if (q == (PixelPacket *) NULL)
416 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
417 quantum_info,GreenQuantum,pixels,exception);
418 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
420 if (((y-image->extract_info.y) >= 0) &&
421 ((y-image->extract_info.y) < (ssize_t) image->rows))
423 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
424 canvas_image->columns,1,exception);
425 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
426 image->columns,1,exception);
427 if ((p == (const PixelPacket *) NULL) ||
428 (q == (PixelPacket *) NULL))
430 for (x=0; x < (ssize_t) image->columns; x++)
432 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
436 if (SyncAuthenticPixels(image,exception) == MagickFalse)
439 count=ReadBlob(image,length,pixels);
441 if (image->previous == (Image *) NULL)
443 status=SetImageProgress(image,LoadImageTag,2,5);
444 if (status == MagickFalse)
447 for (y=0; y < (ssize_t) image->extract_info.height; y++)
449 if (count != (ssize_t) length)
451 ThrowFileException(exception,CorruptImageError,
452 "UnexpectedEndOfFile",image->filename);
455 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
457 if (q == (PixelPacket *) NULL)
459 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
460 quantum_info,BlueQuantum,pixels,exception);
461 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
463 if (((y-image->extract_info.y) >= 0) &&
464 ((y-image->extract_info.y) < (ssize_t) image->rows))
466 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
467 canvas_image->columns,1,exception);
468 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
469 image->columns,1,exception);
470 if ((p == (const PixelPacket *) NULL) ||
471 (q == (PixelPacket *) NULL))
473 for (x=0; x < (ssize_t) image->columns; x++)
475 SetBluePixelComponent(q,GetBluePixelComponent(p));
479 if (SyncAuthenticPixels(image,exception) == MagickFalse)
482 count=ReadBlob(image,length,pixels);
484 if (image->previous == (Image *) NULL)
486 status=SetImageProgress(image,LoadImageTag,3,5);
487 if (status == MagickFalse)
490 if (image->matte != MagickFalse)
492 for (y=0; y < (ssize_t) image->extract_info.height; y++)
494 if (count != (ssize_t) length)
496 ThrowFileException(exception,CorruptImageError,
497 "UnexpectedEndOfFile",image->filename);
500 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
502 if (q == (PixelPacket *) NULL)
504 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
505 quantum_info,AlphaQuantum,pixels,exception);
506 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
508 if (((y-image->extract_info.y) >= 0) &&
509 ((y-image->extract_info.y) < (ssize_t) image->rows))
511 p=GetVirtualPixels(canvas_image,
512 canvas_image->extract_info.x,0,canvas_image->columns,1,
514 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
515 image->columns,1,exception);
516 if ((p == (const PixelPacket *) NULL) ||
517 (q == (PixelPacket *) NULL))
519 for (x=0; x < (ssize_t) image->columns; x++)
521 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
525 if (SyncAuthenticPixels(image,exception) == MagickFalse)
528 count=ReadBlob(image,length,pixels);
530 if (image->previous == (Image *) NULL)
532 status=SetImageProgress(image,LoadImageTag,4,5);
533 if (status == MagickFalse)
537 if (image->previous == (Image *) NULL)
539 status=SetImageProgress(image,LoadImageTag,5,5);
540 if (status == MagickFalse)
545 case PartitionInterlace:
548 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
550 AppendImageFormat("Y",image->filename);
551 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
552 if (status == MagickFalse)
554 canvas_image=DestroyImageList(canvas_image);
555 image=DestroyImageList(image);
556 return((Image *) NULL);
558 for (i=0; i < image->offset; i++)
559 if (ReadBlobByte(image) == EOF)
561 ThrowFileException(exception,CorruptImageError,
562 "UnexpectedEndOfFile",image->filename);
565 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
566 for (i=0; i < (ssize_t) scene; i++)
567 for (y=0; y < (ssize_t) image->extract_info.height; y++)
568 if (ReadBlob(image,length,pixels) != (ssize_t) length)
570 ThrowFileException(exception,CorruptImageError,
571 "UnexpectedEndOfFile",image->filename);
574 count=ReadBlob(image,length,pixels);
575 for (y=0; y < (ssize_t) image->extract_info.height; y++)
577 if (count != (ssize_t) length)
579 ThrowFileException(exception,CorruptImageError,
580 "UnexpectedEndOfFile",image->filename);
583 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
585 if (q == (PixelPacket *) NULL)
587 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
588 quantum_info,RedQuantum,pixels,exception);
589 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
591 if (((y-image->extract_info.y) >= 0) &&
592 ((y-image->extract_info.y) < (ssize_t) image->rows))
594 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
595 canvas_image->columns,1,exception);
596 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
597 image->columns,1,exception);
598 if ((p == (const PixelPacket *) NULL) ||
599 (q == (PixelPacket *) NULL))
601 for (x=0; x < (ssize_t) image->columns; x++)
603 SetRedPixelComponent(q,GetRedPixelComponent(p));
607 if (SyncAuthenticPixels(image,exception) == MagickFalse)
610 count=ReadBlob(image,length,pixels);
612 if (image->previous == (Image *) NULL)
614 status=SetImageProgress(image,LoadImageTag,1,5);
615 if (status == MagickFalse)
618 (void) CloseBlob(image);
619 AppendImageFormat("Cb",image->filename);
620 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
621 if (status == MagickFalse)
623 canvas_image=DestroyImageList(canvas_image);
624 image=DestroyImageList(image);
625 return((Image *) NULL);
627 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
628 for (i=0; i < (ssize_t) scene; i++)
629 for (y=0; y < (ssize_t) image->extract_info.height; y++)
630 if (ReadBlob(image,length,pixels) != (ssize_t) length)
632 ThrowFileException(exception,CorruptImageError,
633 "UnexpectedEndOfFile",image->filename);
636 count=ReadBlob(image,length,pixels);
637 for (y=0; y < (ssize_t) image->extract_info.height; y++)
639 if (count != (ssize_t) length)
641 ThrowFileException(exception,CorruptImageError,
642 "UnexpectedEndOfFile",image->filename);
645 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
647 if (q == (PixelPacket *) NULL)
649 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
650 quantum_info,GreenQuantum,pixels,exception);
651 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
653 if (((y-image->extract_info.y) >= 0) &&
654 ((y-image->extract_info.y) < (ssize_t) image->rows))
656 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
657 canvas_image->columns,1,exception);
658 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
659 image->columns,1,exception);
660 if ((p == (const PixelPacket *) NULL) ||
661 (q == (PixelPacket *) NULL))
663 for (x=0; x < (ssize_t) image->columns; x++)
665 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
669 if (SyncAuthenticPixels(image,exception) == MagickFalse)
672 count=ReadBlob(image,length,pixels);
674 if (image->previous == (Image *) NULL)
676 status=SetImageProgress(image,LoadImageTag,2,5);
677 if (status == MagickFalse)
680 (void) CloseBlob(image);
681 AppendImageFormat("Cr",image->filename);
682 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
683 if (status == MagickFalse)
685 canvas_image=DestroyImageList(canvas_image);
686 image=DestroyImageList(image);
687 return((Image *) NULL);
689 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
690 for (i=0; i < (ssize_t) scene; i++)
691 for (y=0; y < (ssize_t) image->extract_info.height; y++)
692 if (ReadBlob(image,length,pixels) != (ssize_t) length)
694 ThrowFileException(exception,CorruptImageError,
695 "UnexpectedEndOfFile",image->filename);
698 count=ReadBlob(image,length,pixels);
699 for (y=0; y < (ssize_t) image->extract_info.height; y++)
701 if (count != (ssize_t) length)
703 ThrowFileException(exception,CorruptImageError,
704 "UnexpectedEndOfFile",image->filename);
707 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
709 if (q == (PixelPacket *) NULL)
711 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
712 quantum_info,BlueQuantum,pixels,exception);
713 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
715 if (((y-image->extract_info.y) >= 0) &&
716 ((y-image->extract_info.y) < (ssize_t) image->rows))
718 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
719 canvas_image->columns,1,exception);
720 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
721 image->columns,1,exception);
722 if ((p == (const PixelPacket *) NULL) ||
723 (q == (PixelPacket *) NULL))
725 for (x=0; x < (ssize_t) image->columns; x++)
727 SetBluePixelComponent(q,GetBluePixelComponent(p));
731 if (SyncAuthenticPixels(image,exception) == MagickFalse)
734 count=ReadBlob(image,length,pixels);
736 if (image->previous == (Image *) NULL)
738 status=SetImageProgress(image,LoadImageTag,3,5);
739 if (status == MagickFalse)
742 if (image->matte != MagickFalse)
744 (void) CloseBlob(image);
745 AppendImageFormat("A",image->filename);
746 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
747 if (status == MagickFalse)
749 canvas_image=DestroyImageList(canvas_image);
750 image=DestroyImageList(image);
751 return((Image *) NULL);
753 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
754 for (i=0; i < (ssize_t) scene; i++)
755 for (y=0; y < (ssize_t) image->extract_info.height; y++)
756 if (ReadBlob(image,length,pixels) != (ssize_t) length)
758 ThrowFileException(exception,CorruptImageError,
759 "UnexpectedEndOfFile",image->filename);
762 count=ReadBlob(image,length,pixels);
763 for (y=0; y < (ssize_t) image->extract_info.height; y++)
765 if (count != (ssize_t) length)
767 ThrowFileException(exception,CorruptImageError,
768 "UnexpectedEndOfFile",image->filename);
771 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
773 if (q == (PixelPacket *) NULL)
775 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
776 quantum_info,BlueQuantum,pixels,exception);
777 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
779 if (((y-image->extract_info.y) >= 0) &&
780 ((y-image->extract_info.y) < (ssize_t) image->rows))
782 p=GetVirtualPixels(canvas_image,
783 canvas_image->extract_info.x,0,canvas_image->columns,1,
785 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
786 image->columns,1,exception);
787 if ((p == (const PixelPacket *) NULL) ||
788 (q == (PixelPacket *) NULL))
790 for (x=0; x < (ssize_t) image->columns; x++)
792 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
796 if (SyncAuthenticPixels(image,exception) == MagickFalse)
799 count=ReadBlob(image,length,pixels);
801 if (image->previous == (Image *) NULL)
803 status=SetImageProgress(image,LoadImageTag,4,5);
804 if (status == MagickFalse)
808 if (image->previous == (Image *) NULL)
810 status=SetImageProgress(image,LoadImageTag,5,5);
811 if (status == MagickFalse)
817 SetQuantumImageType(image,quantum_type);
819 Proceed to next image.
821 if (image_info->number_scenes != 0)
822 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
824 if (count == (ssize_t) length)
827 Allocate next image structure.
829 AcquireNextImage(image_info,image);
830 if (GetNextImageInList(image) == (Image *) NULL)
832 image=DestroyImageList(image);
833 return((Image *) NULL);
835 image=SyncNextImageInList(image);
836 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
838 if (status == MagickFalse)
842 } while (count == (ssize_t) length);
843 quantum_info=DestroyQuantumInfo(quantum_info);
844 InheritException(&image->exception,&canvas_image->exception);
845 canvas_image=DestroyImage(canvas_image);
846 (void) CloseBlob(image);
847 return(GetFirstImageInList(image));
851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
855 % R e g i s t e r Y C b C r I m a g e %
859 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
861 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
862 % the list of supported formats. The attributes include the image format
863 % tag, a method to read and/or write the format, whether the format
864 % supports the saving of more than one frame to the same file or blob,
865 % whether the format supports native in-memory I/O, and a brief
866 % description of the format.
868 % The format of the RegisterYCBCRImage method is:
870 % size_t RegisterYCBCRImage(void)
873 ModuleExport size_t RegisterYCBCRImage(void)
878 entry=SetMagickInfo("YCbCr");
879 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
880 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
881 entry->raw=MagickTrue;
882 entry->endian_support=MagickTrue;
883 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
884 entry->module=ConstantString("YCbCr");
885 (void) RegisterMagickInfo(entry);
886 entry=SetMagickInfo("YCbCrA");
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, Cr, and alpha samples");
892 entry->module=ConstantString("YCbCr");
893 (void) RegisterMagickInfo(entry);
894 return(MagickImageCoderSignature);
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % U n r e g i s t e r Y C b C r I m a g e %
906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
908 % UnregisterYCBCRImage() removes format registrations made by the
909 % YCbCr module from the list of supported formats.
911 % The format of the UnregisterYCBCRImage method is:
913 % UnregisterYCBCRImage(void)
916 ModuleExport void UnregisterYCBCRImage(void)
918 (void) UnregisterMagickInfo("YCbCr");
919 (void) UnregisterMagickInfo("YCbCrA");
923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
927 % W r i t e Y C b C r I m a g e %
931 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
933 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
936 % The format of the WriteYCBCRImage method is:
938 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
941 % A description of each parameter follows.
943 % o image_info: the image info.
945 % o image: The image.
948 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
966 register const PixelPacket
979 Allocate memory for pixels.
981 assert(image_info != (const ImageInfo *) NULL);
982 assert(image_info->signature == MagickSignature);
983 assert(image != (Image *) NULL);
984 assert(image->signature == MagickSignature);
985 if (image->debug != MagickFalse)
986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
987 if (image_info->interlace != PartitionInterlace)
990 Open output image file.
992 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
993 if (status == MagickFalse)
996 quantum_type=RGBQuantum;
997 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
999 quantum_type=RGBAQuantum;
1000 image->matte=MagickTrue;
1006 Convert MIFF to YCbCr raster pixels.
1008 if (image->colorspace != YCbCrColorspace)
1009 (void) TransformImageColorspace(image,YCbCrColorspace);
1010 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1011 (image->matte == MagickFalse))
1012 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
1013 quantum_info=AcquireQuantumInfo(image_info,image);
1014 if (quantum_info == (QuantumInfo *) NULL)
1015 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1016 pixels=GetQuantumPixels(quantum_info);
1017 switch (image_info->interlace)
1023 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1025 for (y=0; y < (ssize_t) image->rows; y++)
1027 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1028 if (p == (const PixelPacket *) NULL)
1030 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1031 quantum_type,pixels,&image->exception);
1032 count=WriteBlob(image,length,pixels);
1033 if (count != (ssize_t) length)
1035 if (image->previous == (Image *) NULL)
1037 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1039 if (status == MagickFalse)
1048 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1050 for (y=0; y < (ssize_t) image->rows; y++)
1052 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1053 if (p == (const PixelPacket *) NULL)
1055 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1056 RedQuantum,pixels,&image->exception);
1057 count=WriteBlob(image,length,pixels);
1058 if (count != (ssize_t) length)
1060 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1061 GreenQuantum,pixels,&image->exception);
1062 count=WriteBlob(image,length,pixels);
1063 if (count != (ssize_t) length)
1065 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1066 BlueQuantum,pixels,&image->exception);
1067 count=WriteBlob(image,length,pixels);
1068 if (count != (ssize_t) length)
1070 if (quantum_type == RGBAQuantum)
1072 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1073 quantum_info,AlphaQuantum,pixels,&image->exception);
1074 count=WriteBlob(image,length,pixels);
1075 if (count != (ssize_t) length)
1078 if (image->previous == (Image *) NULL)
1080 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1082 if (status == MagickFalse)
1088 case PlaneInterlace:
1091 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1093 for (y=0; y < (ssize_t) image->rows; y++)
1095 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1096 if (p == (const PixelPacket *) NULL)
1098 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1099 RedQuantum,pixels,&image->exception);
1100 count=WriteBlob(image,length,pixels);
1101 if (count != (ssize_t) length)
1104 if (image->previous == (Image *) NULL)
1106 status=SetImageProgress(image,SaveImageTag,1,5);
1107 if (status == MagickFalse)
1110 for (y=0; y < (ssize_t) image->rows; y++)
1112 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1113 if (p == (const PixelPacket *) NULL)
1115 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1116 GreenQuantum,pixels,&image->exception);
1117 count=WriteBlob(image,length,pixels);
1118 if (count != (ssize_t) length)
1121 if (image->previous == (Image *) NULL)
1123 status=SetImageProgress(image,SaveImageTag,2,5);
1124 if (status == MagickFalse)
1127 for (y=0; y < (ssize_t) image->rows; y++)
1129 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1130 if (p == (const PixelPacket *) NULL)
1132 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1133 BlueQuantum,pixels,&image->exception);
1134 count=WriteBlob(image,length,pixels);
1135 if (count != (ssize_t) length)
1138 if (image->previous == (Image *) NULL)
1140 status=SetImageProgress(image,SaveImageTag,3,5);
1141 if (status == MagickFalse)
1144 if (quantum_type == RGBAQuantum)
1146 for (y=0; y < (ssize_t) image->rows; y++)
1148 p=GetVirtualPixels(image,0,y,image->columns,1,
1150 if (p == (const PixelPacket *) NULL)
1152 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1153 quantum_info,AlphaQuantum,pixels,&image->exception);
1154 count=WriteBlob(image,length,pixels);
1155 if (count != (ssize_t) length)
1159 if (image_info->interlace == PartitionInterlace)
1160 (void) CopyMagickString(image->filename,image_info->filename,
1162 if (image->previous == (Image *) NULL)
1164 status=SetImageProgress(image,SaveImageTag,5,5);
1165 if (status == MagickFalse)
1170 case PartitionInterlace:
1173 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1175 AppendImageFormat("Y",image->filename);
1176 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1177 AppendBinaryBlobMode,&image->exception);
1178 if (status == MagickFalse)
1180 for (y=0; y < (ssize_t) image->rows; y++)
1182 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1183 if (p == (const PixelPacket *) NULL)
1185 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1186 RedQuantum,pixels,&image->exception);
1187 count=WriteBlob(image,length,pixels);
1188 if (count != (ssize_t) length)
1191 if (image->previous == (Image *) NULL)
1193 status=SetImageProgress(image,SaveImageTag,1,5);
1194 if (status == MagickFalse)
1197 (void) CloseBlob(image);
1198 AppendImageFormat("Cb",image->filename);
1199 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1200 AppendBinaryBlobMode,&image->exception);
1201 if (status == MagickFalse)
1203 for (y=0; y < (ssize_t) image->rows; y++)
1205 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1206 if (p == (const PixelPacket *) NULL)
1208 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1209 GreenQuantum,pixels,&image->exception);
1210 count=WriteBlob(image,length,pixels);
1211 if (count != (ssize_t) length)
1214 if (image->previous == (Image *) NULL)
1216 status=SetImageProgress(image,SaveImageTag,2,5);
1217 if (status == MagickFalse)
1220 (void) CloseBlob(image);
1221 AppendImageFormat("Cr",image->filename);
1222 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1223 AppendBinaryBlobMode,&image->exception);
1224 if (status == MagickFalse)
1226 for (y=0; y < (ssize_t) image->rows; y++)
1228 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1229 if (p == (const PixelPacket *) NULL)
1231 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1232 BlueQuantum,pixels,&image->exception);
1233 count=WriteBlob(image,length,pixels);
1234 if (count != (ssize_t) length)
1237 if (image->previous == (Image *) NULL)
1239 status=SetImageProgress(image,SaveImageTag,3,5);
1240 if (status == MagickFalse)
1243 if (quantum_type == RGBAQuantum)
1245 (void) CloseBlob(image);
1246 AppendImageFormat("A",image->filename);
1247 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1248 AppendBinaryBlobMode,&image->exception);
1249 if (status == MagickFalse)
1251 for (y=0; y < (ssize_t) image->rows; y++)
1253 p=GetVirtualPixels(image,0,y,image->columns,1,
1255 if (p == (const PixelPacket *) NULL)
1257 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1258 quantum_info,AlphaQuantum,pixels,&image->exception);
1259 count=WriteBlob(image,length,pixels);
1260 if (count != (ssize_t) length)
1263 if (image->previous == (Image *) NULL)
1265 status=SetImageProgress(image,SaveImageTag,4,5);
1266 if (status == MagickFalse)
1270 (void) CloseBlob(image);
1271 (void) CopyMagickString(image->filename,image_info->filename,
1273 if (image->previous == (Image *) NULL)
1275 status=SetImageProgress(image,SaveImageTag,5,5);
1276 if (status == MagickFalse)
1282 quantum_info=DestroyQuantumInfo(quantum_info);
1283 if (GetNextImageInList(image) == (Image *) NULL)
1285 image=SyncNextImageInList(image);
1286 status=SetImageProgress(image,SaveImagesTag,scene++,
1287 GetImageListLength(image));
1288 if (status == MagickFalse)
1290 } while (image_info->adjoin != MagickFalse);
1291 (void) CloseBlob(image);