blob: ede8af19498c716348bae7456e034bbfbeaa2e03 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% Y Y YYYC BBBB YYYC RRRR %
7% Y Y C B B C R R %
8% Y C BBBB C RRRR %
9% Y C B B C R R %
10% Y YYYC BBBB YYYC R R %
11% %
12% %
13% Read/Write Raw YCbCr 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/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"
64
65/*
66 Forward declarations.
67*/
68static MagickBooleanType
69 WriteYCBCRImage(const ImageInfo *,Image *);
70
71/*
72%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73% %
74% %
75% %
76% R e a d Y C b C r I m a g e %
77% %
78% %
79% %
80%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81%
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.
85%
86% The format of the ReadYCBCRImage method is:
87%
88% Image *ReadYCBCRImage(const ImageInfo *image_info,
89% 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 *ReadYCBCRImage(const ImageInfo *image_info,
99 ExceptionInfo *exception)
100{
101 Image
102 *canvas_image,
103 *image;
104
cristybb503372010-05-27 20:51:26 +0000105 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000106 y;
107
108 MagickBooleanType
109 status;
110
111 MagickOffsetType
112 scene;
113
114 QuantumInfo
115 *quantum_info;
116
117 QuantumType
118 quantum_type;
119
120 register const PixelPacket
121 *p;
122
cristybb503372010-05-27 20:51:26 +0000123 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000124 i,
125 x;
126
127 register PixelPacket
128 *q;
129
130 ssize_t
131 count;
132
133 size_t
134 length;
135
136 unsigned char
137 *pixels;
138
139 /*
140 Open image file.
141 */
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)
154 {
155 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
156 if (status == MagickFalse)
157 {
158 image=DestroyImageList(image);
159 return((Image *) NULL);
160 }
cristyd4297022010-09-16 22:59:09 +0000161 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
162 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
163 image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000164 }
165 /*
166 Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
167 */
168 canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
169 exception);
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)
177 {
178 quantum_type=RGBAQuantum;
179 image->matte=MagickTrue;
180 }
181 if (image_info->number_scenes != 0)
182 while (image->scene < image_info->scene)
183 {
184 /*
185 Skip to next image.
186 */
187 image->scene++;
188 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
cristybb503372010-05-27 20:51:26 +0000189 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +0000190 {
191 count=ReadBlob(image,length,pixels);
192 if (count != (ssize_t) length)
193 break;
194 }
195 }
196 count=0;
197 length=0;
198 scene=0;
199 do
200 {
201 /*
202 Read pixels to virtual canvas image then push to image.
203 */
204 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
205 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
206 break;
207 image->colorspace=YCbCrColorspace;
208 switch (image_info->interlace)
209 {
210 case NoInterlace:
211 default:
212 {
213 /*
214 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
215 */
216 if (scene == 0)
217 {
218 length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
219 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000220 }
cristybb503372010-05-27 20:51:26 +0000221 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000222 {
cristy21da32d2009-09-12 14:56:09 +0000223 if (count != (ssize_t) length)
224 {
225 ThrowFileException(exception,CorruptImageError,
226 "UnexpectedEndOfFile",image->filename);
227 break;
228 }
cristy3ed852e2009-09-05 21:47:34 +0000229 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
230 exception);
231 if (q == (PixelPacket *) NULL)
232 break;
233 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
234 quantum_info,quantum_type,pixels,exception);
235 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
236 break;
237 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000238 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000239 {
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))
246 break;
cristybb503372010-05-27 20:51:26 +0000247 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000248 {
cristyce70c172010-01-07 17:15:30 +0000249 SetRedPixelComponent(q,GetRedPixelComponent(p));
250 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
251 SetBluePixelComponent(q,GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000252 if (image->matte != MagickFalse)
cristyce70c172010-01-07 17:15:30 +0000253 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000254 p++;
255 q++;
256 }
257 if (SyncAuthenticPixels(image,exception) == MagickFalse)
258 break;
259 }
260 if (image->previous == (Image *) NULL)
261 {
cristycee97112010-05-28 00:44:52 +0000262 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
263 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000264 if (status == MagickFalse)
265 break;
266 }
267 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000268 }
269 break;
270 }
271 case LineInterlace:
272 {
273 static QuantumType
274 quantum_types[4] =
275 {
276 RedQuantum,
277 GreenQuantum,
278 BlueQuantum,
279 OpacityQuantum
280 };
281
282 /*
283 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
284 */
285 if (scene == 0)
286 {
287 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
288 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000289 }
cristybb503372010-05-27 20:51:26 +0000290 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000291 {
292 for (i=0; i < (image->matte != MagickFalse ? 4 : 3); i++)
293 {
cristy21da32d2009-09-12 14:56:09 +0000294 if (count != (ssize_t) length)
295 {
296 ThrowFileException(exception,CorruptImageError,
297 "UnexpectedEndOfFile",image->filename);
298 break;
299 }
cristy3ed852e2009-09-05 21:47:34 +0000300 quantum_type=quantum_types[i];
301 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
302 exception);
303 if (q == (PixelPacket *) NULL)
304 break;
305 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
306 quantum_info,quantum_type,pixels,exception);
307 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
308 break;
309 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000310 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000311 {
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))
318 break;
cristybb503372010-05-27 20:51:26 +0000319 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000320 {
321 switch (quantum_type)
322 {
cristyce70c172010-01-07 17:15:30 +0000323 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;
cristy3ed852e2009-09-05 21:47:34 +0000327 default: break;
328 }
329 p++;
330 q++;
331 }
332 if (SyncAuthenticPixels(image,exception) == MagickFalse)
333 break;
334 }
335 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000336 }
337 if (image->previous == (Image *) NULL)
338 {
cristycee97112010-05-28 00:44:52 +0000339 status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
340 image->rows);
cristy3ed852e2009-09-05 21:47:34 +0000341 if (status == MagickFalse)
342 break;
343 }
344 }
345 break;
346 }
347 case PlaneInterlace:
348 {
349 /*
350 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
351 */
352 if (scene == 0)
353 {
354 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
355 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000356 }
cristybb503372010-05-27 20:51:26 +0000357 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000358 {
cristy21da32d2009-09-12 14:56:09 +0000359 if (count != (ssize_t) length)
360 {
361 ThrowFileException(exception,CorruptImageError,
362 "UnexpectedEndOfFile",image->filename);
363 break;
364 }
cristy3ed852e2009-09-05 21:47:34 +0000365 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
366 exception);
367 if (q == (PixelPacket *) NULL)
368 break;
369 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
370 quantum_info,RedQuantum,pixels,exception);
371 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
372 break;
373 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000374 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000375 {
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))
382 break;
cristybb503372010-05-27 20:51:26 +0000383 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000384 {
cristyce70c172010-01-07 17:15:30 +0000385 SetRedPixelComponent(q,GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000386 p++;
387 q++;
388 }
389 if (SyncAuthenticPixels(image,exception) == MagickFalse)
390 break;
391 }
392 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000393 }
394 if (image->previous == (Image *) NULL)
395 {
396 status=SetImageProgress(image,LoadImageTag,1,5);
397 if (status == MagickFalse)
398 break;
399 }
cristybb503372010-05-27 20:51:26 +0000400 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000401 {
cristy21da32d2009-09-12 14:56:09 +0000402 if (count != (ssize_t) length)
403 {
404 ThrowFileException(exception,CorruptImageError,
405 "UnexpectedEndOfFile",image->filename);
406 break;
407 }
cristy3ed852e2009-09-05 21:47:34 +0000408 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
409 exception);
410 if (q == (PixelPacket *) NULL)
411 break;
412 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
413 quantum_info,GreenQuantum,pixels,exception);
414 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
415 break;
416 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000417 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000418 {
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))
425 break;
cristybb503372010-05-27 20:51:26 +0000426 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000427 {
cristyce70c172010-01-07 17:15:30 +0000428 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000429 p++;
430 q++;
431 }
432 if (SyncAuthenticPixels(image,exception) == MagickFalse)
433 break;
434 }
435 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000436 }
437 if (image->previous == (Image *) NULL)
438 {
439 status=SetImageProgress(image,LoadImageTag,2,5);
440 if (status == MagickFalse)
441 break;
442 }
cristybb503372010-05-27 20:51:26 +0000443 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000444 {
cristy21da32d2009-09-12 14:56:09 +0000445 if (count != (ssize_t) length)
446 {
447 ThrowFileException(exception,CorruptImageError,
448 "UnexpectedEndOfFile",image->filename);
449 break;
450 }
cristy3ed852e2009-09-05 21:47:34 +0000451 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
452 exception);
453 if (q == (PixelPacket *) NULL)
454 break;
455 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
456 quantum_info,BlueQuantum,pixels,exception);
457 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
458 break;
459 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000460 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000461 {
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))
468 break;
cristybb503372010-05-27 20:51:26 +0000469 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000470 {
cristyce70c172010-01-07 17:15:30 +0000471 SetBluePixelComponent(q,GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000472 p++;
473 q++;
474 }
475 if (SyncAuthenticPixels(image,exception) == MagickFalse)
476 break;
477 }
478 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000479 }
480 if (image->previous == (Image *) NULL)
481 {
482 status=SetImageProgress(image,LoadImageTag,3,5);
483 if (status == MagickFalse)
484 break;
485 }
486 if (image->matte != MagickFalse)
487 {
cristybb503372010-05-27 20:51:26 +0000488 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000489 {
cristy21da32d2009-09-12 14:56:09 +0000490 if (count != (ssize_t) length)
491 {
492 ThrowFileException(exception,CorruptImageError,
493 "UnexpectedEndOfFile",image->filename);
494 break;
495 }
cristy3ed852e2009-09-05 21:47:34 +0000496 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
497 exception);
498 if (q == (PixelPacket *) NULL)
499 break;
500 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
501 quantum_info,AlphaQuantum,pixels,exception);
502 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
503 break;
504 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000505 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000506 {
507 p=GetVirtualPixels(canvas_image,
508 canvas_image->extract_info.x,0,canvas_image->columns,1,
509 exception);
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))
514 break;
cristybb503372010-05-27 20:51:26 +0000515 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000516 {
cristyce70c172010-01-07 17:15:30 +0000517 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000518 p++;
519 q++;
520 }
521 if (SyncAuthenticPixels(image,exception) == MagickFalse)
522 break;
523 }
524 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000525 }
526 if (image->previous == (Image *) NULL)
527 {
528 status=SetImageProgress(image,LoadImageTag,4,5);
529 if (status == MagickFalse)
530 break;
531 }
532 }
533 if (image->previous == (Image *) NULL)
534 {
535 status=SetImageProgress(image,LoadImageTag,5,5);
536 if (status == MagickFalse)
537 break;
538 }
539 break;
540 }
541 case PartitionInterlace:
542 {
543 /*
544 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
545 */
546 AppendImageFormat("Y",image->filename);
547 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
548 if (status == MagickFalse)
549 {
550 canvas_image=DestroyImageList(canvas_image);
551 image=DestroyImageList(image);
552 return((Image *) NULL);
553 }
cristyd4297022010-09-16 22:59:09 +0000554 if (DiscardBlobBytes(image,image->offset) == MagickFalse)
555 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
556 image->filename);
cristy3ed852e2009-09-05 21:47:34 +0000557 length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
cristybb503372010-05-27 20:51:26 +0000558 for (i=0; i < (ssize_t) scene; i++)
559 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000560 if (ReadBlob(image,length,pixels) != (ssize_t) length)
561 {
562 ThrowFileException(exception,CorruptImageError,
563 "UnexpectedEndOfFile",image->filename);
564 break;
565 }
566 count=ReadBlob(image,length,pixels);
cristybb503372010-05-27 20:51:26 +0000567 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000568 {
cristy21da32d2009-09-12 14:56:09 +0000569 if (count != (ssize_t) length)
570 {
571 ThrowFileException(exception,CorruptImageError,
572 "UnexpectedEndOfFile",image->filename);
573 break;
574 }
cristy3ed852e2009-09-05 21:47:34 +0000575 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
576 exception);
577 if (q == (PixelPacket *) NULL)
578 break;
579 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
580 quantum_info,RedQuantum,pixels,exception);
581 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
582 break;
583 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000584 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000585 {
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))
592 break;
cristybb503372010-05-27 20:51:26 +0000593 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000594 {
cristyce70c172010-01-07 17:15:30 +0000595 SetRedPixelComponent(q,GetRedPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000596 p++;
597 q++;
598 }
599 if (SyncAuthenticPixels(image,exception) == MagickFalse)
600 break;
601 }
602 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000603 }
604 if (image->previous == (Image *) NULL)
605 {
606 status=SetImageProgress(image,LoadImageTag,1,5);
607 if (status == MagickFalse)
608 break;
609 }
610 (void) CloseBlob(image);
611 AppendImageFormat("Cb",image->filename);
612 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
613 if (status == MagickFalse)
614 {
615 canvas_image=DestroyImageList(canvas_image);
616 image=DestroyImageList(image);
617 return((Image *) NULL);
618 }
619 length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
cristybb503372010-05-27 20:51:26 +0000620 for (i=0; i < (ssize_t) scene; i++)
621 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000622 if (ReadBlob(image,length,pixels) != (ssize_t) length)
623 {
624 ThrowFileException(exception,CorruptImageError,
625 "UnexpectedEndOfFile",image->filename);
626 break;
627 }
628 count=ReadBlob(image,length,pixels);
cristybb503372010-05-27 20:51:26 +0000629 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000630 {
cristy21da32d2009-09-12 14:56:09 +0000631 if (count != (ssize_t) length)
632 {
633 ThrowFileException(exception,CorruptImageError,
634 "UnexpectedEndOfFile",image->filename);
635 break;
636 }
cristy3ed852e2009-09-05 21:47:34 +0000637 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
638 exception);
639 if (q == (PixelPacket *) NULL)
640 break;
641 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
642 quantum_info,GreenQuantum,pixels,exception);
643 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
644 break;
645 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000646 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000647 {
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))
654 break;
cristybb503372010-05-27 20:51:26 +0000655 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000656 {
cristyce70c172010-01-07 17:15:30 +0000657 SetGreenPixelComponent(q,GetGreenPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000658 p++;
659 q++;
660 }
661 if (SyncAuthenticPixels(image,exception) == MagickFalse)
662 break;
663 }
664 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000665 }
666 if (image->previous == (Image *) NULL)
667 {
668 status=SetImageProgress(image,LoadImageTag,2,5);
669 if (status == MagickFalse)
670 break;
671 }
672 (void) CloseBlob(image);
673 AppendImageFormat("Cr",image->filename);
674 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
675 if (status == MagickFalse)
676 {
677 canvas_image=DestroyImageList(canvas_image);
678 image=DestroyImageList(image);
679 return((Image *) NULL);
680 }
681 length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
cristybb503372010-05-27 20:51:26 +0000682 for (i=0; i < (ssize_t) scene; i++)
683 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000684 if (ReadBlob(image,length,pixels) != (ssize_t) length)
685 {
686 ThrowFileException(exception,CorruptImageError,
687 "UnexpectedEndOfFile",image->filename);
688 break;
689 }
690 count=ReadBlob(image,length,pixels);
cristybb503372010-05-27 20:51:26 +0000691 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000692 {
cristy21da32d2009-09-12 14:56:09 +0000693 if (count != (ssize_t) length)
694 {
695 ThrowFileException(exception,CorruptImageError,
696 "UnexpectedEndOfFile",image->filename);
697 break;
698 }
cristy3ed852e2009-09-05 21:47:34 +0000699 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
700 exception);
701 if (q == (PixelPacket *) NULL)
702 break;
703 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
704 quantum_info,BlueQuantum,pixels,exception);
705 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
706 break;
707 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000708 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000709 {
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))
716 break;
cristybb503372010-05-27 20:51:26 +0000717 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000718 {
cristyce70c172010-01-07 17:15:30 +0000719 SetBluePixelComponent(q,GetBluePixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000720 p++;
721 q++;
722 }
723 if (SyncAuthenticPixels(image,exception) == MagickFalse)
724 break;
725 }
726 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000727 }
728 if (image->previous == (Image *) NULL)
729 {
730 status=SetImageProgress(image,LoadImageTag,3,5);
731 if (status == MagickFalse)
732 break;
733 }
734 if (image->matte != MagickFalse)
735 {
736 (void) CloseBlob(image);
737 AppendImageFormat("A",image->filename);
738 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
739 if (status == MagickFalse)
740 {
741 canvas_image=DestroyImageList(canvas_image);
742 image=DestroyImageList(image);
743 return((Image *) NULL);
744 }
745 length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
cristybb503372010-05-27 20:51:26 +0000746 for (i=0; i < (ssize_t) scene; i++)
747 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000748 if (ReadBlob(image,length,pixels) != (ssize_t) length)
749 {
750 ThrowFileException(exception,CorruptImageError,
751 "UnexpectedEndOfFile",image->filename);
752 break;
753 }
754 count=ReadBlob(image,length,pixels);
cristybb503372010-05-27 20:51:26 +0000755 for (y=0; y < (ssize_t) image->extract_info.height; y++)
cristy3ed852e2009-09-05 21:47:34 +0000756 {
cristy21da32d2009-09-12 14:56:09 +0000757 if (count != (ssize_t) length)
758 {
759 ThrowFileException(exception,CorruptImageError,
760 "UnexpectedEndOfFile",image->filename);
761 break;
762 }
cristy3ed852e2009-09-05 21:47:34 +0000763 q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
764 exception);
765 if (q == (PixelPacket *) NULL)
766 break;
767 length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
768 quantum_info,BlueQuantum,pixels,exception);
769 if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
770 break;
771 if (((y-image->extract_info.y) >= 0) &&
cristybb503372010-05-27 20:51:26 +0000772 ((y-image->extract_info.y) < (ssize_t) image->rows))
cristy3ed852e2009-09-05 21:47:34 +0000773 {
774 p=GetVirtualPixels(canvas_image,
775 canvas_image->extract_info.x,0,canvas_image->columns,1,
776 exception);
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))
781 break;
cristybb503372010-05-27 20:51:26 +0000782 for (x=0; x < (ssize_t) image->columns; x++)
cristy3ed852e2009-09-05 21:47:34 +0000783 {
cristyce70c172010-01-07 17:15:30 +0000784 SetOpacityPixelComponent(q,GetOpacityPixelComponent(p));
cristy3ed852e2009-09-05 21:47:34 +0000785 p++;
786 q++;
787 }
788 if (SyncAuthenticPixels(image,exception) == MagickFalse)
789 break;
790 }
791 count=ReadBlob(image,length,pixels);
cristy3ed852e2009-09-05 21:47:34 +0000792 }
793 if (image->previous == (Image *) NULL)
794 {
795 status=SetImageProgress(image,LoadImageTag,4,5);
796 if (status == MagickFalse)
797 break;
798 }
799 }
800 if (image->previous == (Image *) NULL)
801 {
802 status=SetImageProgress(image,LoadImageTag,5,5);
803 if (status == MagickFalse)
804 break;
805 }
806 break;
807 }
808 }
809 SetQuantumImageType(image,quantum_type);
cristy3ed852e2009-09-05 21:47:34 +0000810 /*
811 Proceed to next image.
812 */
813 if (image_info->number_scenes != 0)
814 if (image->scene >= (image_info->scene+image_info->number_scenes-1))
815 break;
816 if (count == (ssize_t) length)
817 {
818 /*
819 Allocate next image structure.
820 */
821 AcquireNextImage(image_info,image);
822 if (GetNextImageInList(image) == (Image *) NULL)
823 {
824 image=DestroyImageList(image);
825 return((Image *) NULL);
826 }
827 image=SyncNextImageInList(image);
828 status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
829 GetBlobSize(image));
830 if (status == MagickFalse)
831 break;
832 }
833 scene++;
834 } while (count == (ssize_t) length);
cristy3ed852e2009-09-05 21:47:34 +0000835 quantum_info=DestroyQuantumInfo(quantum_info);
cristy01a3f332009-10-27 14:17:37 +0000836 InheritException(&image->exception,&canvas_image->exception);
cristy3ed852e2009-09-05 21:47:34 +0000837 canvas_image=DestroyImage(canvas_image);
838 (void) CloseBlob(image);
839 return(GetFirstImageInList(image));
840}
841
842/*
843%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
844% %
845% %
846% %
847% R e g i s t e r Y C b C r I m a g e %
848% %
849% %
850% %
851%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
852%
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.
859%
860% The format of the RegisterYCBCRImage method is:
861%
cristybb503372010-05-27 20:51:26 +0000862% size_t RegisterYCBCRImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000863%
864*/
cristybb503372010-05-27 20:51:26 +0000865ModuleExport size_t RegisterYCBCRImage(void)
cristy3ed852e2009-09-05 21:47:34 +0000866{
867 MagickInfo
868 *entry;
869
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);
887}
888
889/*
890%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
891% %
892% %
893% %
894% U n r e g i s t e r Y C b C r I m a g e %
895% %
896% %
897% %
898%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
899%
900% UnregisterYCBCRImage() removes format registrations made by the
901% YCbCr module from the list of supported formats.
902%
903% The format of the UnregisterYCBCRImage method is:
904%
905% UnregisterYCBCRImage(void)
906%
907*/
908ModuleExport void UnregisterYCBCRImage(void)
909{
910 (void) UnregisterMagickInfo("YCbCr");
911 (void) UnregisterMagickInfo("YCbCrA");
912}
913
914/*
915%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916% %
917% %
918% %
919% W r i t e Y C b C r I m a g e %
920% %
921% %
922% %
923%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924%
925% WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
926% rasterfile format.
927%
928% The format of the WriteYCBCRImage method is:
929%
930% MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
931% Image *image)
932%
933% A description of each parameter follows.
934%
935% o image_info: the image info.
936%
937% o image: The image.
938%
939*/
940static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
941 Image *image)
942{
cristybb503372010-05-27 20:51:26 +0000943 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000944 y;
945
946 MagickBooleanType
947 status;
948
949 MagickOffsetType
950 scene;
951
952 QuantumInfo
953 *quantum_info;
954
955 QuantumType
956 quantum_type;
957
958 register const PixelPacket
959 *p;
960
961 ssize_t
962 count;
963
964 size_t
965 length;
966
967 unsigned char
968 *pixels;
969
970 /*
971 Allocate memory for pixels.
972 */
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)
980 {
981 /*
982 Open output image file.
983 */
984 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
985 if (status == MagickFalse)
986 return(status);
987 }
988 quantum_type=RGBQuantum;
989 if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
990 {
991 quantum_type=RGBAQuantum;
992 image->matte=MagickTrue;
993 }
994 scene=0;
995 do
996 {
997 /*
998 Convert MIFF to YCbCr raster pixels.
999 */
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)
1010 {
1011 case NoInterlace:
1012 default:
1013 {
1014 /*
1015 No interlacing: YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1016 */
cristybb503372010-05-27 20:51:26 +00001017 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001018 {
1019 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1020 if (p == (const PixelPacket *) NULL)
1021 break;
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)
1026 break;
1027 if (image->previous == (Image *) NULL)
1028 {
cristycee97112010-05-28 00:44:52 +00001029 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1030 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001031 if (status == MagickFalse)
1032 break;
1033 }
1034 }
1035 break;
1036 }
1037 case LineInterlace:
1038 {
1039 /*
1040 Line interlacing: YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1041 */
cristybb503372010-05-27 20:51:26 +00001042 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001043 {
1044 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1045 if (p == (const PixelPacket *) NULL)
1046 break;
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)
1051 break;
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)
1056 break;
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)
1061 break;
1062 if (quantum_type == RGBAQuantum)
1063 {
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)
1068 break;
1069 }
1070 if (image->previous == (Image *) NULL)
1071 {
cristycee97112010-05-28 00:44:52 +00001072 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1073 image->rows);
cristy3ed852e2009-09-05 21:47:34 +00001074 if (status == MagickFalse)
1075 break;
1076 }
1077 }
1078 break;
1079 }
1080 case PlaneInterlace:
1081 {
1082 /*
1083 Plane interlacing: YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1084 */
cristybb503372010-05-27 20:51:26 +00001085 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001086 {
1087 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1088 if (p == (const PixelPacket *) NULL)
1089 break;
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)
1094 break;
1095 }
1096 if (image->previous == (Image *) NULL)
1097 {
1098 status=SetImageProgress(image,SaveImageTag,1,5);
1099 if (status == MagickFalse)
1100 break;
1101 }
cristybb503372010-05-27 20:51:26 +00001102 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001103 {
1104 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1105 if (p == (const PixelPacket *) NULL)
1106 break;
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)
1111 break;
1112 }
1113 if (image->previous == (Image *) NULL)
1114 {
1115 status=SetImageProgress(image,SaveImageTag,2,5);
1116 if (status == MagickFalse)
1117 break;
1118 }
cristybb503372010-05-27 20:51:26 +00001119 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001120 {
1121 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1122 if (p == (const PixelPacket *) NULL)
1123 break;
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)
1128 break;
1129 }
1130 if (image->previous == (Image *) NULL)
1131 {
1132 status=SetImageProgress(image,SaveImageTag,3,5);
1133 if (status == MagickFalse)
1134 break;
1135 }
1136 if (quantum_type == RGBAQuantum)
1137 {
cristybb503372010-05-27 20:51:26 +00001138 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001139 {
1140 p=GetVirtualPixels(image,0,y,image->columns,1,
1141 &image->exception);
1142 if (p == (const PixelPacket *) NULL)
1143 break;
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)
1148 break;
1149 }
1150 }
1151 if (image_info->interlace == PartitionInterlace)
1152 (void) CopyMagickString(image->filename,image_info->filename,
1153 MaxTextExtent);
1154 if (image->previous == (Image *) NULL)
1155 {
1156 status=SetImageProgress(image,SaveImageTag,5,5);
1157 if (status == MagickFalse)
1158 break;
1159 }
1160 break;
1161 }
1162 case PartitionInterlace:
1163 {
1164 /*
1165 Partition interlacing: YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1166 */
1167 AppendImageFormat("Y",image->filename);
1168 status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1169 AppendBinaryBlobMode,&image->exception);
1170 if (status == MagickFalse)
1171 return(status);
cristybb503372010-05-27 20:51:26 +00001172 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001173 {
1174 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1175 if (p == (const PixelPacket *) NULL)
1176 break;
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)
1181 break;
1182 }
1183 if (image->previous == (Image *) NULL)
1184 {
1185 status=SetImageProgress(image,SaveImageTag,1,5);
1186 if (status == MagickFalse)
1187 break;
1188 }
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)
1194 return(status);
cristybb503372010-05-27 20:51:26 +00001195 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001196 {
1197 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1198 if (p == (const PixelPacket *) NULL)
1199 break;
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)
1204 break;
1205 }
1206 if (image->previous == (Image *) NULL)
1207 {
1208 status=SetImageProgress(image,SaveImageTag,2,5);
1209 if (status == MagickFalse)
1210 break;
1211 }
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)
1217 return(status);
cristybb503372010-05-27 20:51:26 +00001218 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001219 {
1220 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1221 if (p == (const PixelPacket *) NULL)
1222 break;
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)
1227 break;
1228 }
1229 if (image->previous == (Image *) NULL)
1230 {
1231 status=SetImageProgress(image,SaveImageTag,3,5);
1232 if (status == MagickFalse)
1233 break;
1234 }
1235 if (quantum_type == RGBAQuantum)
1236 {
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)
1242 return(status);
cristybb503372010-05-27 20:51:26 +00001243 for (y=0; y < (ssize_t) image->rows; y++)
cristy3ed852e2009-09-05 21:47:34 +00001244 {
1245 p=GetVirtualPixels(image,0,y,image->columns,1,
1246 &image->exception);
1247 if (p == (const PixelPacket *) NULL)
1248 break;
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)
1253 break;
1254 }
1255 if (image->previous == (Image *) NULL)
1256 {
1257 status=SetImageProgress(image,SaveImageTag,4,5);
1258 if (status == MagickFalse)
1259 break;
1260 }
1261 }
1262 (void) CloseBlob(image);
1263 (void) CopyMagickString(image->filename,image_info->filename,
1264 MaxTextExtent);
1265 if (image->previous == (Image *) NULL)
1266 {
1267 status=SetImageProgress(image,SaveImageTag,5,5);
1268 if (status == MagickFalse)
1269 break;
1270 }
1271 break;
1272 }
1273 }
1274 quantum_info=DestroyQuantumInfo(quantum_info);
1275 if (GetNextImageInList(image) == (Image *) NULL)
1276 break;
1277 image=SyncNextImageInList(image);
1278 status=SetImageProgress(image,SaveImagesTag,scene++,
1279 GetImageListLength(image));
1280 if (status == MagickFalse)
1281 break;
1282 } while (image_info->adjoin != MagickFalse);
1283 (void) CloseBlob(image);
1284 return(MagickTrue);
1285}