blob: 598130511940aec20250390dec9e5e806816c381 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% Y Y U U V V %
7% Y Y U U V V %
8% Y U U V V %
9% Y U U V V %
10% Y UUU V %
11% %
12% %
13% Read/Write Raw CCIR 601 4:1:1 or 4:2:2 Image Format %
14% %
15% Software Design %
16% John Cristy %
17% July 1992 %
18% %
19% %
cristy16af1cb2009-12-11 21:38:29 +000020% Copyright 1999-2010 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% dedicated to making software imaging solutions freely available. %
22% %
23% You may not use this file except in compliance with the License. You may %
24% obtain a copy of the License at %
25% %
26% http://www.imagemagick.org/script/license.php %
27% %
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. %
33% %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40 Include declarations.
41*/
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/geometry.h"
51#include "magick/image.h"
52#include "magick/image-private.h"
53#include "magick/list.h"
54#include "magick/magick.h"
55#include "magick/memory_.h"
56#include "magick/monitor.h"
57#include "magick/monitor-private.h"
58#include "magick/resize.h"
59#include "magick/quantum-private.h"
60#include "magick/static.h"
61#include "magick/string_.h"
62#include "magick/module.h"
63#include "magick/utility.h"
64
65/*
66 Forward declarations.
67*/
68static MagickBooleanType
69 WriteYUVImage(const ImageInfo *,Image *);
70
71/*
72%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73% %
74% %
75% %
76% R e a d Y U V I m a g e %
77% %
78% %
79% %
80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81%
82% ReadYUVImage() reads an image with digital YUV (CCIR 601 4:1:1, plane
83% or partition interlaced, or 4:2:2 plane, partition interlaced or
84% noninterlaced) bytes and returns it. It allocates the memory necessary
85% for the new Image structure and returns a pointer to the new image.
86%
87% The format of the ReadYUVImage method is:
88%
89% Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
90%
91% A description of each parameter follows:
92%
93% o image_info: the image info.
94%
95% o exception: return any errors or warnings in this structure.
96%
97*/
98static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
99{
100 Image
101 *chroma_image,
102 *image,
103 *resize_image;
104
105 InterlaceType
106 interlace;
107
cristybb503372010-05-27 20:51:26 +0000108 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000109 horizontal_factor,
110 vertical_factor,
111 y;
112
113 MagickBooleanType
114 status;
115
116 register const PixelPacket
117 *chroma_pixels;
118
cristybb503372010-05-27 20:51:26 +0000119 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000120 x;
121
122 register PixelPacket
123 *q;
124
cristybb503372010-05-27 20:51:26 +0000125 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000126 i;
127
128 register unsigned char
129 *p;
130
131 ssize_t
132 count;
133
134 unsigned char
135 *scanline;
136
137 /*
138 Allocate image structure.
139 */
140 assert(image_info != (const ImageInfo *) NULL);
141 assert(image_info->signature == MagickSignature);
142 if (image_info->debug != MagickFalse)
143 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
144 image_info->filename);
145 assert(exception != (ExceptionInfo *) NULL);
146 assert(exception->signature == MagickSignature);
147 image=AcquireImage(image_info);
148 if ((image->columns == 0) || (image->rows == 0))
149 ThrowReaderException(OptionError,"MustSpecifyImageSize");
150 image->depth=8;
151 interlace=image_info->interlace;
152 horizontal_factor=2;
153 vertical_factor=2;
154 if (image_info->sampling_factor != (char *) NULL)
155 {
156 GeometryInfo
157 geometry_info;
158
159 MagickStatusType
160 flags;
161
162 flags=ParseGeometry(image_info->sampling_factor,&geometry_info);
cristybb503372010-05-27 20:51:26 +0000163 horizontal_factor=(ssize_t) geometry_info.rho;
164 vertical_factor=(ssize_t) geometry_info.sigma;
cristy3ed852e2009-09-05 21:47:34 +0000165 if ((flags & SigmaValue) == 0)
166 vertical_factor=horizontal_factor;
167 if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
168 (vertical_factor != 1) && (vertical_factor != 2))
169 ThrowReaderException(CorruptImageError,"UnexpectedSamplingFactor");
170 }
171 if ((interlace == UndefinedInterlace) ||
172 ((interlace == NoInterlace) && (vertical_factor == 2)))
173 {
174 interlace=NoInterlace; /* CCIR 4:2:2 */
175 if (vertical_factor == 2)
176 interlace=PlaneInterlace; /* CCIR 4:1:1 */
177 }
178 if (interlace != PartitionInterlace)
179 {
180 /*
181 Open image file.
182 */
183 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
184 if (status == MagickFalse)
185 {
186 image=DestroyImageList(image);
187 return((Image *) NULL);
188 }
189 for (i=0; i < image->offset; i++)
190 if (ReadBlobByte(image) == EOF)
191 {
192 ThrowFileException(exception,CorruptImageError,
193 "UnexpectedEndOfFile",image->filename);
194 break;
195 }
196 }
197 /*
198 Allocate memory for a scanline.
199 */
200 if (interlace == NoInterlace)
201 scanline=(unsigned char *) AcquireQuantumMemory((size_t) 2UL*
202 image->columns+2UL,sizeof(*scanline));
203 else
204 scanline=(unsigned char *) AcquireQuantumMemory((size_t) image->columns,
205 sizeof(*scanline));
206 if (scanline == (unsigned char *) NULL)
207 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
208 do
209 {
210 chroma_image=CloneImage(image,image->columns/horizontal_factor,
211 image->rows/vertical_factor,MagickTrue,exception);
212 if (chroma_image == (Image *) NULL)
213 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
214 /*
215 Convert raster image to pixel packets.
216 */
217 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
218 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
219 break;
220 if (interlace == PartitionInterlace)
221 {
222 AppendImageFormat("Y",image->filename);
223 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
224 if (status == MagickFalse)
225 {
226 image=DestroyImageList(image);
227 return((Image *) NULL);
228 }
229 }
cristybb503372010-05-27 20:51:26 +0000230 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000231 {
232 register PixelPacket
233 *chroma_pixels;
234
235 if (interlace == NoInterlace)
236 {
237 if ((y > 0) || (GetPreviousImageInList(image) == (Image *) NULL))
238 count=ReadBlob(image,(size_t) (2*image->columns),scanline);
239 p=scanline;
240 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
241 if (q == (PixelPacket *) NULL)
242 break;
243 chroma_pixels=QueueAuthenticPixels(chroma_image,0,y,
244 chroma_image->columns,1,exception);
245 if (chroma_pixels == (PixelPacket *) NULL)
246 break;
cristybb503372010-05-27 20:51:26 +0000247 for (x=0; x < (ssize_t) image->columns; x+=2)
cristy3ed852e2009-09-05 21:47:34 +0000248 {
249 chroma_pixels->red=(Quantum) 0;
250 chroma_pixels->green=ScaleCharToQuantum(*p++);
251 q->red=ScaleCharToQuantum(*p++);
252 q->green=(Quantum) 0;
253 q->blue=(Quantum) 0;
254 q++;
255 q->green=0;
256 q->blue=0;
257 chroma_pixels->blue=ScaleCharToQuantum(*p++);
258 q->red=ScaleCharToQuantum(*p++);
259 chroma_pixels++;
260 q++;
261 }
262 }
263 else
264 {
265 if ((y > 0) || (GetPreviousImageInList(image) == (Image *) NULL))
266 count=ReadBlob(image,(size_t) image->columns,scanline);
267 p=scanline;
268 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
269 if (q == (PixelPacket *) NULL)
270 break;
cristybb503372010-05-27 20:51:26 +0000271 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000272 {
273 q->red=ScaleCharToQuantum(*p++);
274 q->green=0;
275 q->blue=0;
276 q++;
277 }
278 }
279 if (SyncAuthenticPixels(image,exception) == MagickFalse)
280 break;
281 if (interlace == NoInterlace)
282 if (SyncAuthenticPixels(chroma_image,exception) == MagickFalse)
283 break;
284 if (image->previous == (Image *) NULL)
285 {
cristycee97112010-05-28 00:44:52 +0000286 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
287 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000288 if (status == MagickFalse)
289 break;
290 }
291 }
292 if (interlace == PartitionInterlace)
293 {
294 (void) CloseBlob(image);
295 AppendImageFormat("U",image->filename);
296 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
297 if (status == MagickFalse)
298 {
299 image=DestroyImageList(image);
300 return((Image *) NULL);
301 }
302 }
303 if (interlace != NoInterlace)
304 {
cristybb503372010-05-27 20:51:26 +0000305 for (y=0; y < (ssize_t) chroma_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000306 {
307 count=ReadBlob(image,(size_t) chroma_image->columns,scanline);
308 p=scanline;
309 q=QueueAuthenticPixels(chroma_image,0,y,chroma_image->columns,1,
310 exception);
311 if (q == (PixelPacket *) NULL)
312 break;
cristybb503372010-05-27 20:51:26 +0000313 for (x=0; x < (ssize_t) chroma_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000314 {
315 q->red=(Quantum) 0;
316 q->green=ScaleCharToQuantum(*p++);
317 q->blue=(Quantum) 0;
318 q++;
319 }
320 if (SyncAuthenticPixels(chroma_image,exception) == MagickFalse)
321 break;
322 }
323 if (interlace == PartitionInterlace)
324 {
325 (void) CloseBlob(image);
326 AppendImageFormat("V",image->filename);
327 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
328 if (status == MagickFalse)
329 {
330 image=DestroyImageList(image);
331 return((Image *) NULL);
332 }
333 }
cristybb503372010-05-27 20:51:26 +0000334 for (y=0; y < (ssize_t) chroma_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000335 {
336 count=ReadBlob(image,(size_t) chroma_image->columns,scanline);
337 p=scanline;
338 q=GetAuthenticPixels(chroma_image,0,y,chroma_image->columns,1,
339 exception);
340 if (q == (PixelPacket *) NULL)
341 break;
cristybb503372010-05-27 20:51:26 +0000342 for (x=0; x < (ssize_t) chroma_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000343 {
344 q->blue=ScaleCharToQuantum(*p++);
345 q++;
346 }
347 if (SyncAuthenticPixels(chroma_image,exception) == MagickFalse)
348 break;
349 }
350 }
351 /*
352 Scale image.
353 */
354 resize_image=ResizeImage(chroma_image,image->columns,image->rows,
355 TriangleFilter,1.0,exception);
356 chroma_image=DestroyImage(chroma_image);
357 if (resize_image == (Image *) NULL)
358 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
cristybb503372010-05-27 20:51:26 +0000359 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000360 {
361 q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
362 chroma_pixels=GetVirtualPixels(resize_image,0,y,resize_image->columns,1,
363 &resize_image->exception);
364 if ((q == (PixelPacket *) NULL) ||
365 (chroma_pixels == (const PixelPacket *) NULL))
366 break;
cristybb503372010-05-27 20:51:26 +0000367 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000368 {
369 q->green=chroma_pixels->green;
370 q->blue=chroma_pixels->blue;
371 chroma_pixels++;
372 q++;
373 }
374 if (SyncAuthenticPixels(image,exception) == MagickFalse)
375 break;
376 }
377 resize_image=DestroyImage(resize_image);
378 image->colorspace=YCbCrColorspace;
379 if (interlace == PartitionInterlace)
380 (void) CopyMagickString(image->filename,image_info->filename,
381 MaxTextExtent);
382 if (EOFBlob(image) != MagickFalse)
383 {
384 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
385 image->filename);
386 break;
387 }
388 /*
389 Proceed to next image.
390 */
391 if (image_info->number_scenes != 0)
392 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
393 break;
394 if (interlace == NoInterlace)
395 count=ReadBlob(image,(size_t) (2*image->columns),scanline);
396 else
397 count=ReadBlob(image,(size_t) image->columns,scanline);
398 if (count != 0)
399 {
400 /*
401 Allocate next image structure.
402 */
403 AcquireNextImage(image_info,image);
404 if (GetNextImageInList(image) == (Image *) NULL)
405 {
406 image=DestroyImageList(image);
407 return((Image *) NULL);
408 }
409 image=SyncNextImageInList(image);
410 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
411 GetBlobSize(image));
412 if (status == MagickFalse)
413 break;
414 }
415 } while (count != 0);
416 scanline=(unsigned char *) RelinquishMagickMemory(scanline);
417 (void) CloseBlob(image);
418 return(GetFirstImageInList(image));
419}
420
421/*
422%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423% %
424% %
425% %
426% R e g i s t e r Y U V I m a g e %
427% %
428% %
429% %
430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
431%
432% RegisterYUVImage() adds attributes for the YUV image format to
433% the list of supported formats. The attributes include the image format
434% tag, a method to read and/or write the format, whether the format
435% supports the saving of more than one frame to the same file or blob,
436% whether the format supports native in-memory I/O, and a brief
437% description of the format.
438%
439% The format of the RegisterYUVImage method is:
440%
cristybb503372010-05-27 20:51:26 +0000441% size_t RegisterYUVImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000442%
443*/
cristybb503372010-05-27 20:51:26 +0000444ModuleExport size_t RegisterYUVImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000445{
446 MagickInfo
447 *entry;
448
449 entry=SetMagickInfo("YUV");
450 entry->decoder=(DecodeImageHandler *) ReadYUVImage;
451 entry->encoder=(EncodeImageHandler *) WriteYUVImage;
452 entry->adjoin=MagickFalse;
453 entry->raw=MagickTrue;
454 entry->description=ConstantString("CCIR 601 4:1:1 or 4:2:2");
455 entry->module=ConstantString("YUV");
456 (void) RegisterMagickInfo(entry);
457 return(MagickImageCoderSignature);
458}
459
460/*
461%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462% %
463% %
464% %
465% U n r e g i s t e r Y U V I m a g e %
466% %
467% %
468% %
469%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470%
471% UnregisterYUVImage() removes format registrations made by the
472% YUV module from the list of supported formats.
473%
474% The format of the UnregisterYUVImage method is:
475%
476% UnregisterYUVImage(void)
477%
478*/
479ModuleExport void UnregisterYUVImage(void)
480{
481 (void) UnregisterMagickInfo("YUV");
482}
483
484/*
485%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486% %
487% %
488% %
489% W r i t e Y U V I m a g e %
490% %
491% %
492% %
493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
494%
495% WriteYUVImage() writes an image to a file in the digital YUV
496% (CCIR 601 4:1:1, plane or partition interlaced, or 4:2:2 plane, partition
497% interlaced or noninterlaced) bytes and returns it.
498%
499% The format of the WriteYUVImage method is:
500%
501% MagickBooleanType WriteYUVImage(const ImageInfo *image_info,Image *image)
502%
503% A description of each parameter follows.
504%
505% o image_info: the image info.
506%
507% o image: The image.
508%
509*/
510static MagickBooleanType WriteYUVImage(const ImageInfo *image_info,Image *image)
511{
512 Image
513 *chroma_image,
514 *yuv_image;
515
516 InterlaceType
517 interlace;
518
cristybb503372010-05-27 20:51:26 +0000519 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000520 horizontal_factor,
521 vertical_factor,
522 y;
523
524 MagickBooleanType
525 status;
526
527 MagickOffsetType
528 scene;
529
530 register const PixelPacket
531 *p,
532 *s;
533
cristybb503372010-05-27 20:51:26 +0000534 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000535 x;
536
cristybb503372010-05-27 20:51:26 +0000537 size_t
cristy3ed852e2009-09-05 21:47:34 +0000538 height,
539 width;
540
541 assert(image_info != (const ImageInfo *) NULL);
542 assert(image_info->signature == MagickSignature);
543 assert(image != (Image *) NULL);
544 assert(image->signature == MagickSignature);
545 if (image->debug != MagickFalse)
546 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
547 interlace=image->interlace;
548 horizontal_factor=2;
549 vertical_factor=2;
550 if (image_info->sampling_factor != (char *) NULL)
551 {
552 GeometryInfo
553 geometry_info;
554
555 MagickStatusType
556 flags;
557
558 flags=ParseGeometry(image_info->sampling_factor,&geometry_info);
cristybb503372010-05-27 20:51:26 +0000559 horizontal_factor=(ssize_t) geometry_info.rho;
560 vertical_factor=(ssize_t) geometry_info.sigma;
cristy3ed852e2009-09-05 21:47:34 +0000561 if ((flags & SigmaValue) == 0)
562 vertical_factor=horizontal_factor;
563 if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
564 (vertical_factor != 1) && (vertical_factor != 2))
565 ThrowWriterException(CorruptImageError,"UnexpectedSamplingFactor");
566 }
567 if ((interlace == UndefinedInterlace) ||
568 ((interlace == NoInterlace) && (vertical_factor == 2)))
569 {
570 interlace=NoInterlace; /* CCIR 4:2:2 */
571 if (vertical_factor == 2)
572 interlace=PlaneInterlace; /* CCIR 4:1:1 */
573 }
574 if (interlace != PartitionInterlace)
575 {
576 /*
577 Open output image file.
578 */
579 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
580 if (status == MagickFalse)
581 return(status);
582 }
583 else
584 {
585 AppendImageFormat("Y",image->filename);
586 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
587 if (status == MagickFalse)
588 return(status);
589 }
590 scene=0;
591 do
592 {
593 /*
594 Sample image to an even width and height, if necessary.
595 */
596 image->depth=8;
597 width=image->columns+(image->columns & (horizontal_factor-1));
598 height=image->rows+(image->rows & (vertical_factor-1));
599 yuv_image=ResizeImage(image,width,height,TriangleFilter,1.0,
600 &image->exception);
601 if (yuv_image == (Image *) NULL)
602 ThrowWriterException(ResourceLimitError,image->exception.reason);
603 (void) TransformImageColorspace(yuv_image,YCbCrColorspace);
604 /*
605 Downsample image.
606 */
607 chroma_image=ResizeImage(image,width/horizontal_factor,
608 height/vertical_factor,TriangleFilter,1.0,&image->exception);
609 if (chroma_image == (Image *) NULL)
610 ThrowWriterException(ResourceLimitError,image->exception.reason);
611 (void) TransformImageColorspace(chroma_image,YCbCrColorspace);
612 if (interlace == NoInterlace)
613 {
614 /*
615 Write noninterlaced YUV.
616 */
cristybb503372010-05-27 20:51:26 +0000617 for (y=0; y < (ssize_t) yuv_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000618 {
619 p=GetVirtualPixels(yuv_image,0,y,yuv_image->columns,1,
620 &yuv_image->exception);
621 if (p == (const PixelPacket *) NULL)
622 break;
623 s=GetVirtualPixels(chroma_image,0,y,chroma_image->columns,1,
624 &chroma_image->exception);
625 if (s == (const PixelPacket *) NULL)
626 break;
cristybb503372010-05-27 20:51:26 +0000627 for (x=0; x < (ssize_t) yuv_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000628 {
629 (void) WriteBlobByte(image,ScaleQuantumToChar(s->green));
cristyce70c172010-01-07 17:15:30 +0000630 (void) WriteBlobByte(image,ScaleQuantumToChar(GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +0000631 p++;
632 (void) WriteBlobByte(image,ScaleQuantumToChar(s->blue));
cristyce70c172010-01-07 17:15:30 +0000633 (void) WriteBlobByte(image,ScaleQuantumToChar(GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +0000634 p++;
635 s++;
636 x++;
637 }
638 if (image->previous == (Image *) NULL)
639 {
cristycee97112010-05-28 00:44:52 +0000640 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
641 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000642 if (status == MagickFalse)
643 break;
644 }
645 }
646 yuv_image=DestroyImage(yuv_image);
647 }
648 else
649 {
650 /*
651 Initialize Y channel.
652 */
cristybb503372010-05-27 20:51:26 +0000653 for (y=0; y < (ssize_t) yuv_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000654 {
655 p=GetVirtualPixels(yuv_image,0,y,yuv_image->columns,1,
656 &yuv_image->exception);
657 if (p == (const PixelPacket *) NULL)
658 break;
cristybb503372010-05-27 20:51:26 +0000659 for (x=0; x < (ssize_t) yuv_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000660 {
cristyce70c172010-01-07 17:15:30 +0000661 (void) WriteBlobByte(image,ScaleQuantumToChar(GetRedPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +0000662 p++;
663 }
664 if (image->previous == (Image *) NULL)
665 {
cristycee97112010-05-28 00:44:52 +0000666 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
667 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000668 if (status == MagickFalse)
669 break;
670 }
671 }
672 yuv_image=DestroyImage(yuv_image);
673 if (image->previous == (Image *) NULL)
674 {
675 status=SetImageProgress(image,SaveImageTag,1,3);
676 if (status == MagickFalse)
677 break;
678 }
679 /*
680 Initialize U channel.
681 */
682 if (interlace == PartitionInterlace)
683 {
684 (void) CloseBlob(image);
685 AppendImageFormat("U",image->filename);
686 status=OpenBlob(image_info,image,WriteBinaryBlobMode,
687 &image->exception);
688 if (status == MagickFalse)
689 return(status);
690 }
cristybb503372010-05-27 20:51:26 +0000691 for (y=0; y < (ssize_t) chroma_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000692 {
693 p=GetVirtualPixels(chroma_image,0,y,chroma_image->columns,1,
694 &chroma_image->exception);
695 if (p == (const PixelPacket *) NULL)
696 break;
cristybb503372010-05-27 20:51:26 +0000697 for (x=0; x < (ssize_t) chroma_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000698 {
cristyce70c172010-01-07 17:15:30 +0000699 (void) WriteBlobByte(image,ScaleQuantumToChar(GetGreenPixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +0000700 p++;
701 }
702 }
703 if (image->previous == (Image *) NULL)
704 {
705 status=SetImageProgress(image,SaveImageTag,2,3);
706 if (status == MagickFalse)
707 break;
708 }
709 /*
710 Initialize V channel.
711 */
712 if (interlace == PartitionInterlace)
713 {
714 (void) CloseBlob(image);
715 AppendImageFormat("V",image->filename);
716 status=OpenBlob(image_info,image,WriteBinaryBlobMode,
717 &image->exception);
718 if (status == MagickFalse)
719 return(status);
720 }
cristybb503372010-05-27 20:51:26 +0000721 for (y=0; y < (ssize_t) chroma_image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000722 {
723 p=GetVirtualPixels(chroma_image,0,y,chroma_image->columns,1,
724 &chroma_image->exception);
725 if (p == (const PixelPacket *) NULL)
726 break;
cristybb503372010-05-27 20:51:26 +0000727 for (x=0; x < (ssize_t) chroma_image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000728 {
cristyce70c172010-01-07 17:15:30 +0000729 (void) WriteBlobByte(image,ScaleQuantumToChar(GetBluePixelComponent(p)));
cristy3ed852e2009-09-05 21:47:34 +0000730 p++;
731 }
732 }
733 if (image->previous == (Image *) NULL)
734 {
735 status=SetImageProgress(image,SaveImageTag,2,3);
736 if (status == MagickFalse)
737 break;
738 }
739 }
740 chroma_image=DestroyImage(chroma_image);
741 if (interlace == PartitionInterlace)
742 (void) CopyMagickString(image->filename,image_info->filename,
743 MaxTextExtent);
744 if (GetNextImageInList(image) == (Image *) NULL)
745 break;
746 image=SyncNextImageInList(image);
747 status=SetImageProgress(image,SaveImagesTag,scene++,
748 GetImageListLength(image));
749 if (status == MagickFalse)
750 break;
751 } while (image_info->adjoin != MagickFalse);
752 (void) CloseBlob(image);
753 return(MagickTrue);
754}