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 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
162 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
166 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
168 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
170 (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->matte=MagickTrue;
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 image->colorspace=YCbCrColorspace;
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 == (PixelPacket *) 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 PixelPacket *) NULL) ||
245 (q == (PixelPacket *) NULL))
247 for (x=0; x < (ssize_t) image->columns; x++)
249 SetRedPixelComponent(q,GetRedPixelComponent(p));
250 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
251 SetBluePixelComponent(q,GetBluePixelComponent(p));
252 if (image->matte != MagickFalse)
253 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
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->matte != MagickFalse ? 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 == (PixelPacket *) 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 PixelPacket *) NULL) ||
317 (q == (PixelPacket *) NULL))
319 for (x=0; x < (ssize_t) image->columns; x++)
321 switch (quantum_type)
323 case RedQuantum: SetRedPixelComponent(q,GetRedPixelComponent(p)); break;
324 case GreenQuantum: SetGreenPixelComponent(q,GetGreenPixelComponent(p)); break;
325 case BlueQuantum: SetBluePixelComponent(q,GetBluePixelComponent(p)); break;
326 case OpacityQuantum: SetOpacityPixelComponent(q,GetOpacityPixelComponent(p)); break;
332 if (SyncAuthenticPixels(image,exception) == MagickFalse)
335 count=ReadBlob(image,length,pixels);
337 if (image->previous == (Image *) NULL)
339 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
341 if (status == MagickFalse)
350 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
354 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
355 count=ReadBlob(image,length,pixels);
357 for (y=0; y < (ssize_t) image->extract_info.height; y++)
359 if (count != (ssize_t) length)
361 ThrowFileException(exception,CorruptImageError,
362 "UnexpectedEndOfFile",image->filename);
365 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
367 if (q == (PixelPacket *) NULL)
369 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
370 quantum_info,RedQuantum,pixels,exception);
371 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
373 if (((y-image->extract_info.y) >= 0) &&
374 ((y-image->extract_info.y) < (ssize_t) image->rows))
376 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
377 canvas_image->columns,1,exception);
378 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
379 image->columns,1,exception);
380 if ((p == (const PixelPacket *) NULL) ||
381 (q == (PixelPacket *) NULL))
383 for (x=0; x < (ssize_t) image->columns; x++)
385 SetRedPixelComponent(q,GetRedPixelComponent(p));
389 if (SyncAuthenticPixels(image,exception) == MagickFalse)
392 count=ReadBlob(image,length,pixels);
394 if (image->previous == (Image *) NULL)
396 status=SetImageProgress(image,LoadImageTag,1,5);
397 if (status == MagickFalse)
400 for (y=0; y < (ssize_t) image->extract_info.height; y++)
402 if (count != (ssize_t) length)
404 ThrowFileException(exception,CorruptImageError,
405 "UnexpectedEndOfFile",image->filename);
408 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
410 if (q == (PixelPacket *) NULL)
412 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
413 quantum_info,GreenQuantum,pixels,exception);
414 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
416 if (((y-image->extract_info.y) >= 0) &&
417 ((y-image->extract_info.y) < (ssize_t) image->rows))
419 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
420 canvas_image->columns,1,exception);
421 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
422 image->columns,1,exception);
423 if ((p == (const PixelPacket *) NULL) ||
424 (q == (PixelPacket *) NULL))
426 for (x=0; x < (ssize_t) image->columns; x++)
428 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
432 if (SyncAuthenticPixels(image,exception) == MagickFalse)
435 count=ReadBlob(image,length,pixels);
437 if (image->previous == (Image *) NULL)
439 status=SetImageProgress(image,LoadImageTag,2,5);
440 if (status == MagickFalse)
443 for (y=0; y < (ssize_t) image->extract_info.height; y++)
445 if (count != (ssize_t) length)
447 ThrowFileException(exception,CorruptImageError,
448 "UnexpectedEndOfFile",image->filename);
451 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
453 if (q == (PixelPacket *) NULL)
455 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
456 quantum_info,BlueQuantum,pixels,exception);
457 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
459 if (((y-image->extract_info.y) >= 0) &&
460 ((y-image->extract_info.y) < (ssize_t) image->rows))
462 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
463 canvas_image->columns,1,exception);
464 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
465 image->columns,1,exception);
466 if ((p == (const PixelPacket *) NULL) ||
467 (q == (PixelPacket *) NULL))
469 for (x=0; x < (ssize_t) image->columns; x++)
471 SetBluePixelComponent(q,GetBluePixelComponent(p));
475 if (SyncAuthenticPixels(image,exception) == MagickFalse)
478 count=ReadBlob(image,length,pixels);
480 if (image->previous == (Image *) NULL)
482 status=SetImageProgress(image,LoadImageTag,3,5);
483 if (status == MagickFalse)
486 if (image->matte != MagickFalse)
488 for (y=0; y < (ssize_t) image->extract_info.height; y++)
490 if (count != (ssize_t) length)
492 ThrowFileException(exception,CorruptImageError,
493 "UnexpectedEndOfFile",image->filename);
496 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
498 if (q == (PixelPacket *) NULL)
500 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
501 quantum_info,AlphaQuantum,pixels,exception);
502 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
504 if (((y-image->extract_info.y) >= 0) &&
505 ((y-image->extract_info.y) < (ssize_t) image->rows))
507 p=GetVirtualPixels(canvas_image,
508 canvas_image->extract_info.x,0,canvas_image->columns,1,
510 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
511 image->columns,1,exception);
512 if ((p == (const PixelPacket *) NULL) ||
513 (q == (PixelPacket *) NULL))
515 for (x=0; x < (ssize_t) image->columns; x++)
517 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
521 if (SyncAuthenticPixels(image,exception) == MagickFalse)
524 count=ReadBlob(image,length,pixels);
526 if (image->previous == (Image *) NULL)
528 status=SetImageProgress(image,LoadImageTag,4,5);
529 if (status == MagickFalse)
533 if (image->previous == (Image *) NULL)
535 status=SetImageProgress(image,LoadImageTag,5,5);
536 if (status == MagickFalse)
541 case PartitionInterlace:
544 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
546 AppendImageFormat("Y",image->filename);
547 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
548 if (status == MagickFalse)
550 canvas_image=DestroyImageList(canvas_image);
551 image=DestroyImageList(image);
552 return((Image *) NULL);
554 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
555 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
557 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
558 for (i=0; i < (ssize_t) scene; i++)
559 for (y=0; y < (ssize_t) image->extract_info.height; y++)
560 if (ReadBlob(image,length,pixels) != (ssize_t) length)
562 ThrowFileException(exception,CorruptImageError,
563 "UnexpectedEndOfFile",image->filename);
566 count=ReadBlob(image,length,pixels);
567 for (y=0; y < (ssize_t) image->extract_info.height; y++)
569 if (count != (ssize_t) length)
571 ThrowFileException(exception,CorruptImageError,
572 "UnexpectedEndOfFile",image->filename);
575 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
577 if (q == (PixelPacket *) NULL)
579 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
580 quantum_info,RedQuantum,pixels,exception);
581 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
583 if (((y-image->extract_info.y) >= 0) &&
584 ((y-image->extract_info.y) < (ssize_t) image->rows))
586 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
587 canvas_image->columns,1,exception);
588 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
589 image->columns,1,exception);
590 if ((p == (const PixelPacket *) NULL) ||
591 (q == (PixelPacket *) NULL))
593 for (x=0; x < (ssize_t) image->columns; x++)
595 SetRedPixelComponent(q,GetRedPixelComponent(p));
599 if (SyncAuthenticPixels(image,exception) == MagickFalse)
602 count=ReadBlob(image,length,pixels);
604 if (image->previous == (Image *) NULL)
606 status=SetImageProgress(image,LoadImageTag,1,5);
607 if (status == MagickFalse)
610 (void) CloseBlob(image);
611 AppendImageFormat("Cb",image->filename);
612 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
613 if (status == MagickFalse)
615 canvas_image=DestroyImageList(canvas_image);
616 image=DestroyImageList(image);
617 return((Image *) NULL);
619 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
620 for (i=0; i < (ssize_t) scene; i++)
621 for (y=0; y < (ssize_t) image->extract_info.height; y++)
622 if (ReadBlob(image,length,pixels) != (ssize_t) length)
624 ThrowFileException(exception,CorruptImageError,
625 "UnexpectedEndOfFile",image->filename);
628 count=ReadBlob(image,length,pixels);
629 for (y=0; y < (ssize_t) image->extract_info.height; y++)
631 if (count != (ssize_t) length)
633 ThrowFileException(exception,CorruptImageError,
634 "UnexpectedEndOfFile",image->filename);
637 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
639 if (q == (PixelPacket *) NULL)
641 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
642 quantum_info,GreenQuantum,pixels,exception);
643 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
645 if (((y-image->extract_info.y) >= 0) &&
646 ((y-image->extract_info.y) < (ssize_t) image->rows))
648 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
649 canvas_image->columns,1,exception);
650 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
651 image->columns,1,exception);
652 if ((p == (const PixelPacket *) NULL) ||
653 (q == (PixelPacket *) NULL))
655 for (x=0; x < (ssize_t) image->columns; x++)
657 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
661 if (SyncAuthenticPixels(image,exception) == MagickFalse)
664 count=ReadBlob(image,length,pixels);
666 if (image->previous == (Image *) NULL)
668 status=SetImageProgress(image,LoadImageTag,2,5);
669 if (status == MagickFalse)
672 (void) CloseBlob(image);
673 AppendImageFormat("Cr",image->filename);
674 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
675 if (status == MagickFalse)
677 canvas_image=DestroyImageList(canvas_image);
678 image=DestroyImageList(image);
679 return((Image *) NULL);
681 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
682 for (i=0; i < (ssize_t) scene; i++)
683 for (y=0; y < (ssize_t) image->extract_info.height; y++)
684 if (ReadBlob(image,length,pixels) != (ssize_t) length)
686 ThrowFileException(exception,CorruptImageError,
687 "UnexpectedEndOfFile",image->filename);
690 count=ReadBlob(image,length,pixels);
691 for (y=0; y < (ssize_t) image->extract_info.height; y++)
693 if (count != (ssize_t) length)
695 ThrowFileException(exception,CorruptImageError,
696 "UnexpectedEndOfFile",image->filename);
699 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
701 if (q == (PixelPacket *) NULL)
703 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
704 quantum_info,BlueQuantum,pixels,exception);
705 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
707 if (((y-image->extract_info.y) >= 0) &&
708 ((y-image->extract_info.y) < (ssize_t) image->rows))
710 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
711 canvas_image->columns,1,exception);
712 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
713 image->columns,1,exception);
714 if ((p == (const PixelPacket *) NULL) ||
715 (q == (PixelPacket *) NULL))
717 for (x=0; x < (ssize_t) image->columns; x++)
719 SetBluePixelComponent(q,GetBluePixelComponent(p));
723 if (SyncAuthenticPixels(image,exception) == MagickFalse)
726 count=ReadBlob(image,length,pixels);
728 if (image->previous == (Image *) NULL)
730 status=SetImageProgress(image,LoadImageTag,3,5);
731 if (status == MagickFalse)
734 if (image->matte != MagickFalse)
736 (void) CloseBlob(image);
737 AppendImageFormat("A",image->filename);
738 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
739 if (status == MagickFalse)
741 canvas_image=DestroyImageList(canvas_image);
742 image=DestroyImageList(image);
743 return((Image *) NULL);
745 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
746 for (i=0; i < (ssize_t) scene; i++)
747 for (y=0; y < (ssize_t) image->extract_info.height; y++)
748 if (ReadBlob(image,length,pixels) != (ssize_t) length)
750 ThrowFileException(exception,CorruptImageError,
751 "UnexpectedEndOfFile",image->filename);
754 count=ReadBlob(image,length,pixels);
755 for (y=0; y < (ssize_t) image->extract_info.height; y++)
757 if (count != (ssize_t) length)
759 ThrowFileException(exception,CorruptImageError,
760 "UnexpectedEndOfFile",image->filename);
763 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
765 if (q == (PixelPacket *) NULL)
767 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
768 quantum_info,BlueQuantum,pixels,exception);
769 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
771 if (((y-image->extract_info.y) >= 0) &&
772 ((y-image->extract_info.y) < (ssize_t) image->rows))
774 p=GetVirtualPixels(canvas_image,
775 canvas_image->extract_info.x,0,canvas_image->columns,1,
777 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
778 image->columns,1,exception);
779 if ((p == (const PixelPacket *) NULL) ||
780 (q == (PixelPacket *) NULL))
782 for (x=0; x < (ssize_t) image->columns; x++)
784 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
788 if (SyncAuthenticPixels(image,exception) == MagickFalse)
791 count=ReadBlob(image,length,pixels);
793 if (image->previous == (Image *) NULL)
795 status=SetImageProgress(image,LoadImageTag,4,5);
796 if (status == MagickFalse)
800 if (image->previous == (Image *) NULL)
802 status=SetImageProgress(image,LoadImageTag,5,5);
803 if (status == MagickFalse)
809 SetQuantumImageType(image,quantum_type);
811 Proceed to next image.
813 if (image_info->number_scenes != 0)
814 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
816 if (count == (ssize_t) length)
819 Allocate next image structure.
821 AcquireNextImage(image_info,image);
822 if (GetNextImageInList(image) == (Image *) NULL)
824 image=DestroyImageList(image);
825 return((Image *) NULL);
827 image=SyncNextImageInList(image);
828 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
830 if (status == MagickFalse)
834 } while (count == (ssize_t) length);
835 quantum_info=DestroyQuantumInfo(quantum_info);
836 InheritException(&image->exception,&canvas_image->exception);
837 canvas_image=DestroyImage(canvas_image);
838 (void) CloseBlob(image);
839 return(GetFirstImageInList(image));
843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847 % R e g i s t e r Y C b C r I m a g e %
851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
853 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
854 % the list of supported formats. The attributes include the image format
855 % tag, a method to read and/or write the format, whether the format
856 % supports the saving of more than one frame to the same file or blob,
857 % whether the format supports native in-memory I/O, and a brief
858 % description of the format.
860 % The format of the RegisterYCBCRImage method is:
862 % size_t RegisterYCBCRImage(void)
865 ModuleExport size_t RegisterYCBCRImage(void)
870 entry=SetMagickInfo("YCbCr");
871 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
872 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
873 entry->raw=MagickTrue;
874 entry->endian_support=MagickTrue;
875 entry->description=ConstantString("Raw Y, Cb, and Cr samples");
876 entry->module=ConstantString("YCbCr");
877 (void) RegisterMagickInfo(entry);
878 entry=SetMagickInfo("YCbCrA");
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, Cr, and alpha samples");
884 entry->module=ConstantString("YCbCr");
885 (void) RegisterMagickInfo(entry);
886 return(MagickImageCoderSignature);
890 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
894 % U n r e g i s t e r Y C b C r I m a g e %
898 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
900 % UnregisterYCBCRImage() removes format registrations made by the
901 % YCbCr module from the list of supported formats.
903 % The format of the UnregisterYCBCRImage method is:
905 % UnregisterYCBCRImage(void)
908 ModuleExport void UnregisterYCBCRImage(void)
910 (void) UnregisterMagickInfo("YCbCr");
911 (void) UnregisterMagickInfo("YCbCrA");
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
919 % W r i t e Y C b C r I m a g e %
923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
925 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
928 % The format of the WriteYCBCRImage method is:
930 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
933 % A description of each parameter follows.
935 % o image_info: the image info.
937 % o image: The image.
940 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
958 register const PixelPacket
971 Allocate memory for pixels.
973 assert(image_info != (const ImageInfo *) NULL);
974 assert(image_info->signature == MagickSignature);
975 assert(image != (Image *) NULL);
976 assert(image->signature == MagickSignature);
977 if (image->debug != MagickFalse)
978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
979 if (image_info->interlace != PartitionInterlace)
982 Open output image file.
984 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
985 if (status == MagickFalse)
988 quantum_type=RGBQuantum;
989 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
991 quantum_type=RGBAQuantum;
992 image->matte=MagickTrue;
998 Convert MIFF to YCbCr raster pixels.
1000 if (image->colorspace != YCbCrColorspace)
1001 (void) TransformImageColorspace(image,YCbCrColorspace);
1002 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1003 (image->matte == MagickFalse))
1004 (void) SetImageAlphaChannel(image,ResetAlphaChannel);
1005 quantum_info=AcquireQuantumInfo(image_info,image);
1006 if (quantum_info == (QuantumInfo *) NULL)
1007 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1008 pixels=GetQuantumPixels(quantum_info);
1009 switch (image_info->interlace)
1015 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1017 for (y=0; y < (ssize_t) image->rows; y++)
1019 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1020 if (p == (const PixelPacket *) NULL)
1022 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1023 quantum_type,pixels,&image->exception);
1024 count=WriteBlob(image,length,pixels);
1025 if (count != (ssize_t) length)
1027 if (image->previous == (Image *) NULL)
1029 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1031 if (status == MagickFalse)
1040 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1042 for (y=0; y < (ssize_t) image->rows; y++)
1044 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1045 if (p == (const PixelPacket *) NULL)
1047 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1048 RedQuantum,pixels,&image->exception);
1049 count=WriteBlob(image,length,pixels);
1050 if (count != (ssize_t) length)
1052 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1053 GreenQuantum,pixels,&image->exception);
1054 count=WriteBlob(image,length,pixels);
1055 if (count != (ssize_t) length)
1057 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1058 BlueQuantum,pixels,&image->exception);
1059 count=WriteBlob(image,length,pixels);
1060 if (count != (ssize_t) length)
1062 if (quantum_type == RGBAQuantum)
1064 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1065 quantum_info,AlphaQuantum,pixels,&image->exception);
1066 count=WriteBlob(image,length,pixels);
1067 if (count != (ssize_t) length)
1070 if (image->previous == (Image *) NULL)
1072 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1074 if (status == MagickFalse)
1080 case PlaneInterlace:
1083 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1085 for (y=0; y < (ssize_t) image->rows; y++)
1087 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1088 if (p == (const PixelPacket *) NULL)
1090 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1091 RedQuantum,pixels,&image->exception);
1092 count=WriteBlob(image,length,pixels);
1093 if (count != (ssize_t) length)
1096 if (image->previous == (Image *) NULL)
1098 status=SetImageProgress(image,SaveImageTag,1,5);
1099 if (status == MagickFalse)
1102 for (y=0; y < (ssize_t) image->rows; y++)
1104 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1105 if (p == (const PixelPacket *) NULL)
1107 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1108 GreenQuantum,pixels,&image->exception);
1109 count=WriteBlob(image,length,pixels);
1110 if (count != (ssize_t) length)
1113 if (image->previous == (Image *) NULL)
1115 status=SetImageProgress(image,SaveImageTag,2,5);
1116 if (status == MagickFalse)
1119 for (y=0; y < (ssize_t) image->rows; y++)
1121 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1122 if (p == (const PixelPacket *) NULL)
1124 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1125 BlueQuantum,pixels,&image->exception);
1126 count=WriteBlob(image,length,pixels);
1127 if (count != (ssize_t) length)
1130 if (image->previous == (Image *) NULL)
1132 status=SetImageProgress(image,SaveImageTag,3,5);
1133 if (status == MagickFalse)
1136 if (quantum_type == RGBAQuantum)
1138 for (y=0; y < (ssize_t) image->rows; y++)
1140 p=GetVirtualPixels(image,0,y,image->columns,1,
1142 if (p == (const PixelPacket *) NULL)
1144 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1145 quantum_info,AlphaQuantum,pixels,&image->exception);
1146 count=WriteBlob(image,length,pixels);
1147 if (count != (ssize_t) length)
1151 if (image_info->interlace == PartitionInterlace)
1152 (void) CopyMagickString(image->filename,image_info->filename,
1154 if (image->previous == (Image *) NULL)
1156 status=SetImageProgress(image,SaveImageTag,5,5);
1157 if (status == MagickFalse)
1162 case PartitionInterlace:
1165 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1167 AppendImageFormat("Y",image->filename);
1168 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1169 AppendBinaryBlobMode,&image->exception);
1170 if (status == MagickFalse)
1172 for (y=0; y < (ssize_t) image->rows; y++)
1174 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1175 if (p == (const PixelPacket *) NULL)
1177 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1178 RedQuantum,pixels,&image->exception);
1179 count=WriteBlob(image,length,pixels);
1180 if (count != (ssize_t) length)
1183 if (image->previous == (Image *) NULL)
1185 status=SetImageProgress(image,SaveImageTag,1,5);
1186 if (status == MagickFalse)
1189 (void) CloseBlob(image);
1190 AppendImageFormat("Cb",image->filename);
1191 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1192 AppendBinaryBlobMode,&image->exception);
1193 if (status == MagickFalse)
1195 for (y=0; y < (ssize_t) image->rows; y++)
1197 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1198 if (p == (const PixelPacket *) NULL)
1200 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1201 GreenQuantum,pixels,&image->exception);
1202 count=WriteBlob(image,length,pixels);
1203 if (count != (ssize_t) length)
1206 if (image->previous == (Image *) NULL)
1208 status=SetImageProgress(image,SaveImageTag,2,5);
1209 if (status == MagickFalse)
1212 (void) CloseBlob(image);
1213 AppendImageFormat("Cr",image->filename);
1214 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1215 AppendBinaryBlobMode,&image->exception);
1216 if (status == MagickFalse)
1218 for (y=0; y < (ssize_t) image->rows; y++)
1220 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1221 if (p == (const PixelPacket *) NULL)
1223 length=ExportQuantumPixels(image,(const CacheView *) NULL,quantum_info,
1224 BlueQuantum,pixels,&image->exception);
1225 count=WriteBlob(image,length,pixels);
1226 if (count != (ssize_t) length)
1229 if (image->previous == (Image *) NULL)
1231 status=SetImageProgress(image,SaveImageTag,3,5);
1232 if (status == MagickFalse)
1235 if (quantum_type == RGBAQuantum)
1237 (void) CloseBlob(image);
1238 AppendImageFormat("A",image->filename);
1239 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1240 AppendBinaryBlobMode,&image->exception);
1241 if (status == MagickFalse)
1243 for (y=0; y < (ssize_t) image->rows; y++)
1245 p=GetVirtualPixels(image,0,y,image->columns,1,
1247 if (p == (const PixelPacket *) NULL)
1249 length=ExportQuantumPixels(image,(const CacheView *) NULL,
1250 quantum_info,AlphaQuantum,pixels,&image->exception);
1251 count=WriteBlob(image,length,pixels);
1252 if (count != (ssize_t) length)
1255 if (image->previous == (Image *) NULL)
1257 status=SetImageProgress(image,SaveImageTag,4,5);
1258 if (status == MagickFalse)
1262 (void) CloseBlob(image);
1263 (void) CopyMagickString(image->filename,image_info->filename,
1265 if (image->previous == (Image *) NULL)
1267 status=SetImageProgress(image,SaveImageTag,5,5);
1268 if (status == MagickFalse)
1274 quantum_info=DestroyQuantumInfo(quantum_info);
1275 if (GetNextImageInList(image) == (Image *) NULL)
1277 image=SyncNextImageInList(image);
1278 status=SetImageProgress(image,SaveImagesTag,scene++,
1279 GetImageListLength(image));
1280 if (status == MagickFalse)
1282 } while (image_info->adjoin != MagickFalse);
1283 (void) CloseBlob(image);