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-2017 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)
121 register const Quantum
141 assert(image_info != (const ImageInfo *) NULL);
142 assert(image_info->signature == MagickCoreSignature);
143 if (image_info->debug != MagickFalse)
144 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
145 image_info->filename);
146 assert(exception != (ExceptionInfo *) NULL);
147 assert(exception->signature == MagickCoreSignature);
148 image=AcquireImage(image_info,exception);
149 if ((image->columns == 0) || (image->rows == 0))
150 ThrowReaderException(OptionError,"MustSpecifyImageSize");
151 status=SetImageExtent(image,image->columns,image->rows,exception);
152 if (status == MagickFalse)
153 return(DestroyImageList(image));
154 SetImageColorspace(image,YCbCrColorspace,exception);
155 if (image_info->interlace != PartitionInterlace)
157 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
158 if (status == MagickFalse)
160 image=DestroyImageList(image);
161 return((Image *) NULL);
163 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
164 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
168 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
170 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
172 (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
174 quantum_info=AcquireQuantumInfo(image_info,canvas_image);
175 if (quantum_info == (QuantumInfo *) NULL)
176 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
177 quantum_type=RGBQuantum;
178 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
180 quantum_type=RGBAQuantum;
181 image->alpha_trait=BlendPixelTrait;
183 pixels=(const unsigned char *) NULL;
184 if (image_info->number_scenes != 0)
185 while (image->scene < image_info->scene)
191 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
192 for (y=0; y < (ssize_t) image->rows; y++)
194 pixels=(const unsigned char *) ReadBlobStream(image,length,
195 GetQuantumPixels(quantum_info),&count);
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 status=SetImageExtent(image,image->columns,image->rows,exception);
212 if (status == MagickFalse)
213 return(DestroyImageList(image));
214 SetImageColorspace(image,YCbCrColorspace,exception);
215 switch (image_info->interlace)
221 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
225 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
226 pixels=(const unsigned char *) ReadBlobStream(image,length,
227 GetQuantumPixels(quantum_info),&count);
229 for (y=0; y < (ssize_t) image->extract_info.height; y++)
231 if (count != (ssize_t) length)
233 ThrowFileException(exception,CorruptImageError,
234 "UnexpectedEndOfFile",image->filename);
237 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
239 if (q == (Quantum *) NULL)
241 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
242 quantum_info,quantum_type,pixels,exception);
243 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
245 if (((y-image->extract_info.y) >= 0) &&
246 ((y-image->extract_info.y) < (ssize_t) image->rows))
248 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
249 canvas_image->columns,1,exception);
250 q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
251 image->columns,1,exception);
252 if ((p == (const Quantum *) NULL) ||
253 (q == (Quantum *) NULL))
255 for (x=0; x < (ssize_t) image->columns; x++)
257 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
258 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
259 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
260 if (image->alpha_trait != UndefinedPixelTrait)
261 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
262 p+=GetPixelChannels(canvas_image);
263 q+=GetPixelChannels(image);
265 if (SyncAuthenticPixels(image,exception) == MagickFalse)
268 if (image->previous == (Image *) NULL)
270 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
272 if (status == MagickFalse)
275 pixels=(const unsigned char *) ReadBlobStream(image,length,
276 GetQuantumPixels(quantum_info),&count);
292 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
296 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
297 pixels=(const unsigned char *) ReadBlobStream(image,length,
298 GetQuantumPixels(quantum_info),&count);
300 for (y=0; y < (ssize_t) image->extract_info.height; y++)
302 for (i=0; i < (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
304 if (count != (ssize_t) length)
306 ThrowFileException(exception,CorruptImageError,
307 "UnexpectedEndOfFile",image->filename);
310 quantum_type=quantum_types[i];
311 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
313 if (q == (Quantum *) NULL)
315 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
316 quantum_info,quantum_type,pixels,exception);
317 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
319 if (((y-image->extract_info.y) >= 0) &&
320 ((y-image->extract_info.y) < (ssize_t) image->rows))
322 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
323 0,canvas_image->columns,1,exception);
324 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
325 image->columns,1,exception);
326 if ((p == (const Quantum *) NULL) ||
327 (q == (Quantum *) NULL))
329 for (x=0; x < (ssize_t) image->columns; x++)
331 switch (quantum_type)
335 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
340 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
345 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
350 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
356 p+=GetPixelChannels(canvas_image);
357 q+=GetPixelChannels(image);
359 if (SyncAuthenticPixels(image,exception) == MagickFalse)
362 pixels=(const unsigned char *) ReadBlobStream(image,length,
363 GetQuantumPixels(quantum_info),&count);
365 if (image->previous == (Image *) NULL)
367 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
369 if (status == MagickFalse)
378 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
382 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
383 pixels=(const unsigned char *) ReadBlobStream(image,length,
384 GetQuantumPixels(quantum_info),&count);
386 for (y=0; y < (ssize_t) image->extract_info.height; y++)
388 if (count != (ssize_t) length)
390 ThrowFileException(exception,CorruptImageError,
391 "UnexpectedEndOfFile",image->filename);
394 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
396 if (q == (Quantum *) NULL)
398 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
399 quantum_info,RedQuantum,pixels,exception);
400 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
402 if (((y-image->extract_info.y) >= 0) &&
403 ((y-image->extract_info.y) < (ssize_t) image->rows))
405 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
406 canvas_image->columns,1,exception);
407 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
408 image->columns,1,exception);
409 if ((p == (const Quantum *) NULL) ||
410 (q == (Quantum *) NULL))
412 for (x=0; x < (ssize_t) image->columns; x++)
414 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
415 p+=GetPixelChannels(canvas_image);
416 q+=GetPixelChannels(image);
418 if (SyncAuthenticPixels(image,exception) == MagickFalse)
421 pixels=(const unsigned char *) ReadBlobStream(image,length,
422 GetQuantumPixels(quantum_info),&count);
424 if (image->previous == (Image *) NULL)
426 status=SetImageProgress(image,LoadImageTag,1,5);
427 if (status == MagickFalse)
430 for (y=0; y < (ssize_t) image->extract_info.height; y++)
432 if (count != (ssize_t) length)
434 ThrowFileException(exception,CorruptImageError,
435 "UnexpectedEndOfFile",image->filename);
438 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
440 if (q == (Quantum *) NULL)
442 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
443 quantum_info,GreenQuantum,pixels,exception);
444 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
446 if (((y-image->extract_info.y) >= 0) &&
447 ((y-image->extract_info.y) < (ssize_t) image->rows))
449 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
450 canvas_image->columns,1,exception);
451 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
452 image->columns,1,exception);
453 if ((p == (const Quantum *) NULL) ||
454 (q == (Quantum *) NULL))
456 for (x=0; x < (ssize_t) image->columns; x++)
458 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
459 p+=GetPixelChannels(canvas_image);
460 q+=GetPixelChannels(image);
462 if (SyncAuthenticPixels(image,exception) == MagickFalse)
465 pixels=(const unsigned char *) ReadBlobStream(image,length,
466 GetQuantumPixels(quantum_info),&count);
468 if (image->previous == (Image *) NULL)
470 status=SetImageProgress(image,LoadImageTag,2,5);
471 if (status == MagickFalse)
474 for (y=0; y < (ssize_t) image->extract_info.height; y++)
476 if (count != (ssize_t) length)
478 ThrowFileException(exception,CorruptImageError,
479 "UnexpectedEndOfFile",image->filename);
482 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
484 if (q == (Quantum *) NULL)
486 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
487 quantum_info,BlueQuantum,pixels,exception);
488 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
490 if (((y-image->extract_info.y) >= 0) &&
491 ((y-image->extract_info.y) < (ssize_t) image->rows))
493 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
494 canvas_image->columns,1,exception);
495 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
496 image->columns,1,exception);
497 if ((p == (const Quantum *) NULL) ||
498 (q == (Quantum *) NULL))
500 for (x=0; x < (ssize_t) image->columns; x++)
502 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
503 p+=GetPixelChannels(canvas_image);
504 q+=GetPixelChannels(image);
506 if (SyncAuthenticPixels(image,exception) == MagickFalse)
509 pixels=(const unsigned char *) ReadBlobStream(image,length,
510 GetQuantumPixels(quantum_info),&count);
512 if (image->previous == (Image *) NULL)
514 status=SetImageProgress(image,LoadImageTag,3,5);
515 if (status == MagickFalse)
518 if (image->alpha_trait != UndefinedPixelTrait)
520 for (y=0; y < (ssize_t) image->extract_info.height; y++)
522 if (count != (ssize_t) length)
524 ThrowFileException(exception,CorruptImageError,
525 "UnexpectedEndOfFile",image->filename);
528 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
530 if (q == (Quantum *) NULL)
532 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
533 quantum_info,AlphaQuantum,pixels,exception);
534 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
536 if (((y-image->extract_info.y) >= 0) &&
537 ((y-image->extract_info.y) < (ssize_t) image->rows))
539 p=GetVirtualPixels(canvas_image,
540 canvas_image->extract_info.x,0,canvas_image->columns,1,
542 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
543 image->columns,1,exception);
544 if ((p == (const Quantum *) NULL) ||
545 (q == (Quantum *) NULL))
547 for (x=0; x < (ssize_t) image->columns; x++)
549 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
550 p+=GetPixelChannels(canvas_image);
551 q+=GetPixelChannels(image);
553 if (SyncAuthenticPixels(image,exception) == MagickFalse)
556 pixels=(const unsigned char *) ReadBlobStream(image,length,
557 GetQuantumPixels(quantum_info),&count);
559 if (image->previous == (Image *) NULL)
561 status=SetImageProgress(image,LoadImageTag,4,5);
562 if (status == MagickFalse)
566 if (image->previous == (Image *) NULL)
568 status=SetImageProgress(image,LoadImageTag,5,5);
569 if (status == MagickFalse)
574 case PartitionInterlace:
577 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
579 AppendImageFormat("Y",image->filename);
580 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
581 if (status == MagickFalse)
583 canvas_image=DestroyImageList(canvas_image);
584 image=DestroyImageList(image);
585 return((Image *) NULL);
587 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
588 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
590 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
591 for (i=0; i < (ssize_t) scene; i++)
592 for (y=0; y < (ssize_t) image->extract_info.height; y++)
594 pixels=(const unsigned char *) ReadBlobStream(image,length,
595 GetQuantumPixels(quantum_info),&count);
596 if (count != (ssize_t) length)
598 ThrowFileException(exception,CorruptImageError,
599 "UnexpectedEndOfFile",image->filename);
603 pixels=(const unsigned char *) ReadBlobStream(image,length,
604 GetQuantumPixels(quantum_info),&count);
605 for (y=0; y < (ssize_t) image->extract_info.height; y++)
607 if (count != (ssize_t) length)
609 ThrowFileException(exception,CorruptImageError,
610 "UnexpectedEndOfFile",image->filename);
613 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
615 if (q == (Quantum *) NULL)
617 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
618 quantum_info,RedQuantum,pixels,exception);
619 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
621 if (((y-image->extract_info.y) >= 0) &&
622 ((y-image->extract_info.y) < (ssize_t) image->rows))
624 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
625 canvas_image->columns,1,exception);
626 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
627 image->columns,1,exception);
628 if ((p == (const Quantum *) NULL) ||
629 (q == (Quantum *) NULL))
631 for (x=0; x < (ssize_t) image->columns; x++)
633 SetPixelRed(image,GetPixelRed(canvas_image,p),q);
634 p+=GetPixelChannels(canvas_image);
635 q+=GetPixelChannels(image);
637 if (SyncAuthenticPixels(image,exception) == MagickFalse)
640 pixels=(const unsigned char *) ReadBlobStream(image,length,
641 GetQuantumPixels(quantum_info),&count);
643 if (image->previous == (Image *) NULL)
645 status=SetImageProgress(image,LoadImageTag,1,5);
646 if (status == MagickFalse)
649 (void) CloseBlob(image);
650 AppendImageFormat("Cb",image->filename);
651 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
652 if (status == MagickFalse)
654 canvas_image=DestroyImageList(canvas_image);
655 image=DestroyImageList(image);
656 return((Image *) NULL);
658 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
659 for (i=0; i < (ssize_t) scene; i++)
660 for (y=0; y < (ssize_t) image->extract_info.height; y++)
662 pixels=(const unsigned char *) ReadBlobStream(image,length,
663 GetQuantumPixels(quantum_info),&count);
664 if (count != (ssize_t) length)
666 ThrowFileException(exception,CorruptImageError,
667 "UnexpectedEndOfFile",image->filename);
671 pixels=(const unsigned char *) ReadBlobStream(image,length,
672 GetQuantumPixels(quantum_info),&count);
673 for (y=0; y < (ssize_t) image->extract_info.height; y++)
675 if (count != (ssize_t) length)
677 ThrowFileException(exception,CorruptImageError,
678 "UnexpectedEndOfFile",image->filename);
681 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
683 if (q == (Quantum *) NULL)
685 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
686 quantum_info,GreenQuantum,pixels,exception);
687 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
689 if (((y-image->extract_info.y) >= 0) &&
690 ((y-image->extract_info.y) < (ssize_t) image->rows))
692 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
693 canvas_image->columns,1,exception);
694 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
695 image->columns,1,exception);
696 if ((p == (const Quantum *) NULL) ||
697 (q == (Quantum *) NULL))
699 for (x=0; x < (ssize_t) image->columns; x++)
701 SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
702 p+=GetPixelChannels(canvas_image);
703 q+=GetPixelChannels(image);
705 if (SyncAuthenticPixels(image,exception) == MagickFalse)
708 pixels=(const unsigned char *) ReadBlobStream(image,length,
709 GetQuantumPixels(quantum_info),&count);
711 if (image->previous == (Image *) NULL)
713 status=SetImageProgress(image,LoadImageTag,2,5);
714 if (status == MagickFalse)
717 (void) CloseBlob(image);
718 AppendImageFormat("Cr",image->filename);
719 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
720 if (status == MagickFalse)
722 canvas_image=DestroyImageList(canvas_image);
723 image=DestroyImageList(image);
724 return((Image *) NULL);
726 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
727 for (i=0; i < (ssize_t) scene; i++)
728 for (y=0; y < (ssize_t) image->extract_info.height; y++)
730 pixels=(const unsigned char *) ReadBlobStream(image,length,
731 GetQuantumPixels(quantum_info),&count);
732 if (count != (ssize_t) length)
734 ThrowFileException(exception,CorruptImageError,
735 "UnexpectedEndOfFile",image->filename);
739 pixels=(const unsigned char *) ReadBlobStream(image,length,
740 GetQuantumPixels(quantum_info),&count);
741 for (y=0; y < (ssize_t) image->extract_info.height; y++)
743 if (count != (ssize_t) length)
745 ThrowFileException(exception,CorruptImageError,
746 "UnexpectedEndOfFile",image->filename);
749 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
751 if (q == (Quantum *) NULL)
753 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
754 quantum_info,BlueQuantum,pixels,exception);
755 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
757 if (((y-image->extract_info.y) >= 0) &&
758 ((y-image->extract_info.y) < (ssize_t) image->rows))
760 p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
761 canvas_image->columns,1,exception);
762 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
763 image->columns,1,exception);
764 if ((p == (const Quantum *) NULL) ||
765 (q == (Quantum *) NULL))
767 for (x=0; x < (ssize_t) image->columns; x++)
769 SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
770 p+=GetPixelChannels(canvas_image);
771 q+=GetPixelChannels(image);
773 if (SyncAuthenticPixels(image,exception) == MagickFalse)
776 pixels=(const unsigned char *) ReadBlobStream(image,length,
777 GetQuantumPixels(quantum_info),&count);
779 if (image->previous == (Image *) NULL)
781 status=SetImageProgress(image,LoadImageTag,3,5);
782 if (status == MagickFalse)
785 if (image->alpha_trait != UndefinedPixelTrait)
787 (void) CloseBlob(image);
788 AppendImageFormat("A",image->filename);
789 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
790 if (status == MagickFalse)
792 canvas_image=DestroyImageList(canvas_image);
793 image=DestroyImageList(image);
794 return((Image *) NULL);
796 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
797 for (i=0; i < (ssize_t) scene; i++)
798 for (y=0; y < (ssize_t) image->extract_info.height; y++)
800 pixels=(const unsigned char *) ReadBlobStream(image,length,
801 GetQuantumPixels(quantum_info),&count);
802 if (count != (ssize_t) length)
804 ThrowFileException(exception,CorruptImageError,
805 "UnexpectedEndOfFile",image->filename);
809 pixels=(const unsigned char *) ReadBlobStream(image,length,
810 GetQuantumPixels(quantum_info),&count);
811 for (y=0; y < (ssize_t) image->extract_info.height; y++)
813 if (count != (ssize_t) length)
815 ThrowFileException(exception,CorruptImageError,
816 "UnexpectedEndOfFile",image->filename);
819 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
821 if (q == (Quantum *) NULL)
823 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
824 quantum_info,BlueQuantum,pixels,exception);
825 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
827 if (((y-image->extract_info.y) >= 0) &&
828 ((y-image->extract_info.y) < (ssize_t) image->rows))
830 p=GetVirtualPixels(canvas_image,
831 canvas_image->extract_info.x,0,canvas_image->columns,1,
833 q=GetAuthenticPixels(image,0,y-image->extract_info.y,
834 image->columns,1,exception);
835 if ((p == (const Quantum *) NULL) ||
836 (q == (Quantum *) NULL))
838 for (x=0; x < (ssize_t) image->columns; x++)
840 SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
841 p+=GetPixelChannels(canvas_image);
842 q+=GetPixelChannels(image);
844 if (SyncAuthenticPixels(image,exception) == MagickFalse)
847 pixels=(const unsigned char *) ReadBlobStream(image,length,
848 GetQuantumPixels(quantum_info),&count);
850 if (image->previous == (Image *) NULL)
852 status=SetImageProgress(image,LoadImageTag,4,5);
853 if (status == MagickFalse)
857 if (image->previous == (Image *) NULL)
859 status=SetImageProgress(image,LoadImageTag,5,5);
860 if (status == MagickFalse)
866 SetQuantumImageType(image,quantum_type);
868 Proceed to next image.
870 if (image_info->number_scenes != 0)
871 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
873 if (count == (ssize_t) length)
876 Allocate next image structure.
878 AcquireNextImage(image_info,image,exception);
879 if (GetNextImageInList(image) == (Image *) NULL)
881 image=DestroyImageList(image);
882 return((Image *) NULL);
884 image=SyncNextImageInList(image);
885 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
887 if (status == MagickFalse)
891 } while (count == (ssize_t) length);
892 quantum_info=DestroyQuantumInfo(quantum_info);
893 canvas_image=DestroyImage(canvas_image);
894 (void) CloseBlob(image);
895 return(GetFirstImageInList(image));
899 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 % R e g i s t e r Y C b C r I m a g e %
907 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
909 % RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
910 % the list of supported formats. The attributes include the image format
911 % tag, a method to read and/or write the format, whether the format
912 % supports the saving of more than one frame to the same file or blob,
913 % whether the format supports native in-memory I/O, and a brief
914 % description of the format.
916 % The format of the RegisterYCBCRImage method is:
918 % size_t RegisterYCBCRImage(void)
921 ModuleExport size_t RegisterYCBCRImage(void)
926 entry=AcquireMagickInfo("YCbCr","YCbCr","Raw Y, Cb, and Cr samples");
927 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
928 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
929 entry->flags|=CoderRawSupportFlag;
930 entry->flags|=CoderEndianSupportFlag;
931 (void) RegisterMagickInfo(entry);
932 entry=AcquireMagickInfo("YCbCr","YCbCrA","Raw Y, Cb, Cr, and alpha samples");
933 entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
934 entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
935 entry->flags|=CoderRawSupportFlag;
936 entry->flags|=CoderEndianSupportFlag;
937 (void) RegisterMagickInfo(entry);
938 return(MagickImageCoderSignature);
942 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
946 % U n r e g i s t e r Y C b C r I m a g e %
950 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
952 % UnregisterYCBCRImage() removes format registrations made by the
953 % YCbCr module from the list of supported formats.
955 % The format of the UnregisterYCBCRImage method is:
957 % UnregisterYCBCRImage(void)
960 ModuleExport void UnregisterYCBCRImage(void)
962 (void) UnregisterMagickInfo("YCbCr");
963 (void) UnregisterMagickInfo("YCbCrA");
967 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
971 % W r i t e Y C b C r I m a g e %
975 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977 % WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
980 % The format of the WriteYCBCRImage method is:
982 % MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
983 % Image *image,ExceptionInfo *exception)
985 % A description of each parameter follows.
987 % o image_info: the image info.
989 % o image: The image.
991 % o exception: return any errors or warnings in this structure.
994 static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
995 Image *image,ExceptionInfo *exception)
1009 register const Quantum
1023 Allocate memory for pixels.
1025 assert(image_info != (const ImageInfo *) NULL);
1026 assert(image_info->signature == MagickCoreSignature);
1027 assert(image != (Image *) NULL);
1028 assert(image->signature == MagickCoreSignature);
1029 if (image->debug != MagickFalse)
1030 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1031 if (image_info->interlace != PartitionInterlace)
1034 Open output image file.
1036 assert(exception != (ExceptionInfo *) NULL);
1037 assert(exception->signature == MagickCoreSignature);
1038 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1039 if (status == MagickFalse)
1042 quantum_type=RGBQuantum;
1043 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1045 quantum_type=RGBAQuantum;
1046 image->alpha_trait=BlendPixelTrait;
1052 Convert MIFF to YCbCr raster pixels.
1054 if (image->colorspace != YCbCrColorspace)
1055 (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1056 if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1057 (image->alpha_trait == UndefinedPixelTrait))
1058 (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1059 quantum_info=AcquireQuantumInfo(image_info,image);
1060 if (quantum_info == (QuantumInfo *) NULL)
1061 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1062 pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1063 switch (image_info->interlace)
1069 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1071 for (y=0; y < (ssize_t) image->rows; y++)
1073 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1074 if (p == (const Quantum *) NULL)
1076 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1077 quantum_type,pixels,exception);
1078 count=WriteBlob(image,length,pixels);
1079 if (count != (ssize_t) length)
1081 if (image->previous == (Image *) NULL)
1083 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1085 if (status == MagickFalse)
1094 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1096 for (y=0; y < (ssize_t) image->rows; y++)
1098 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1099 if (p == (const Quantum *) NULL)
1101 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1102 RedQuantum,pixels,exception);
1103 count=WriteBlob(image,length,pixels);
1104 if (count != (ssize_t) length)
1106 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1107 GreenQuantum,pixels,exception);
1108 count=WriteBlob(image,length,pixels);
1109 if (count != (ssize_t) length)
1111 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1112 BlueQuantum,pixels,exception);
1113 count=WriteBlob(image,length,pixels);
1114 if (count != (ssize_t) length)
1116 if (quantum_type == RGBAQuantum)
1118 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1119 AlphaQuantum,pixels,exception);
1120 count=WriteBlob(image,length,pixels);
1121 if (count != (ssize_t) length)
1124 if (image->previous == (Image *) NULL)
1126 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1128 if (status == MagickFalse)
1134 case PlaneInterlace:
1137 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1139 for (y=0; y < (ssize_t) image->rows; y++)
1141 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1142 if (p == (const Quantum *) NULL)
1144 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1145 RedQuantum,pixels,exception);
1146 count=WriteBlob(image,length,pixels);
1147 if (count != (ssize_t) length)
1150 if (image->previous == (Image *) NULL)
1152 status=SetImageProgress(image,SaveImageTag,1,5);
1153 if (status == MagickFalse)
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 GreenQuantum,pixels,exception);
1163 count=WriteBlob(image,length,pixels);
1164 if (count != (ssize_t) length)
1167 if (image->previous == (Image *) NULL)
1169 status=SetImageProgress(image,SaveImageTag,2,5);
1170 if (status == MagickFalse)
1173 for (y=0; y < (ssize_t) image->rows; y++)
1175 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1176 if (p == (const Quantum *) NULL)
1178 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1179 BlueQuantum,pixels,exception);
1180 count=WriteBlob(image,length,pixels);
1181 if (count != (ssize_t) length)
1184 if (image->previous == (Image *) NULL)
1186 status=SetImageProgress(image,SaveImageTag,3,5);
1187 if (status == MagickFalse)
1190 if (quantum_type == RGBAQuantum)
1192 for (y=0; y < (ssize_t) image->rows; y++)
1194 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1195 if (p == (const Quantum *) NULL)
1197 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1198 AlphaQuantum,pixels,exception);
1199 count=WriteBlob(image,length,pixels);
1200 if (count != (ssize_t) length)
1204 if (image_info->interlace == PartitionInterlace)
1205 (void) CopyMagickString(image->filename,image_info->filename,
1207 if (image->previous == (Image *) NULL)
1209 status=SetImageProgress(image,SaveImageTag,5,5);
1210 if (status == MagickFalse)
1215 case PartitionInterlace:
1218 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1220 AppendImageFormat("Y",image->filename);
1221 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1222 AppendBinaryBlobMode,exception);
1223 if (status == MagickFalse)
1225 for (y=0; y < (ssize_t) image->rows; y++)
1227 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1228 if (p == (const Quantum *) NULL)
1230 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1231 RedQuantum,pixels,exception);
1232 count=WriteBlob(image,length,pixels);
1233 if (count != (ssize_t) length)
1236 if (image->previous == (Image *) NULL)
1238 status=SetImageProgress(image,SaveImageTag,1,5);
1239 if (status == MagickFalse)
1242 (void) CloseBlob(image);
1243 AppendImageFormat("Cb",image->filename);
1244 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1245 AppendBinaryBlobMode,exception);
1246 if (status == MagickFalse)
1248 for (y=0; y < (ssize_t) image->rows; y++)
1250 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1251 if (p == (const Quantum *) NULL)
1253 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1254 GreenQuantum,pixels,exception);
1255 count=WriteBlob(image,length,pixels);
1256 if (count != (ssize_t) length)
1259 if (image->previous == (Image *) NULL)
1261 status=SetImageProgress(image,SaveImageTag,2,5);
1262 if (status == MagickFalse)
1265 (void) CloseBlob(image);
1266 AppendImageFormat("Cr",image->filename);
1267 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1268 AppendBinaryBlobMode,exception);
1269 if (status == MagickFalse)
1271 for (y=0; y < (ssize_t) image->rows; y++)
1273 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1274 if (p == (const Quantum *) NULL)
1276 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1277 BlueQuantum,pixels,exception);
1278 count=WriteBlob(image,length,pixels);
1279 if (count != (ssize_t) length)
1282 if (image->previous == (Image *) NULL)
1284 status=SetImageProgress(image,SaveImageTag,3,5);
1285 if (status == MagickFalse)
1288 if (quantum_type == RGBAQuantum)
1290 (void) CloseBlob(image);
1291 AppendImageFormat("A",image->filename);
1292 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1293 AppendBinaryBlobMode,exception);
1294 if (status == MagickFalse)
1296 for (y=0; y < (ssize_t) image->rows; y++)
1298 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1299 if (p == (const Quantum *) NULL)
1301 length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1302 AlphaQuantum,pixels,exception);
1303 count=WriteBlob(image,length,pixels);
1304 if (count != (ssize_t) length)
1307 if (image->previous == (Image *) NULL)
1309 status=SetImageProgress(image,SaveImageTag,4,5);
1310 if (status == MagickFalse)
1314 (void) CloseBlob(image);
1315 (void) CopyMagickString(image->filename,image_info->filename,
1317 if (image->previous == (Image *) NULL)
1319 status=SetImageProgress(image,SaveImageTag,5,5);
1320 if (status == MagickFalse)
1326 quantum_info=DestroyQuantumInfo(quantum_info);
1327 if (GetNextImageInList(image) == (Image *) NULL)
1329 image=SyncNextImageInList(image);
1330 status=SetImageProgress(image,SaveImagesTag,scene++,
1331 GetImageListLength(image));
1332 if (status == MagickFalse)
1334 } while (image_info->adjoin != MagickFalse);
1335 (void) CloseBlob(image);