~ubuntu-branches/ubuntu/intrepid/graphicsmagick/intrepid

« back to all changes in this revision

Viewing changes to coders/yuv.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Kobras
  • Date: 2006-05-06 16:28:08 UTC
  • Revision ID: james.westby@ubuntu.com-20060506162808-vt2ni3r5nytcszms
Tags: upstream-1.1.7
ImportĀ upstreamĀ versionĀ 1.1.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
% Copyright (C) 2003 GraphicsMagick Group
 
3
% Copyright (C) 2002 ImageMagick Studio
 
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
 
5
%
 
6
% This program is covered by multiple licenses, which are described in
 
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
 
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
 
9
%
 
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
11
%                                                                             %
 
12
%                                                                             %
 
13
%                                                                             %
 
14
%                            Y   Y  U   U  V   V                              %
 
15
%                             Y Y   U   U  V   V                              %
 
16
%                              Y    U   U  V   V                              %
 
17
%                              Y    U   U   V V                               %
 
18
%                              Y     UUU     V                                %
 
19
%                                                                             %
 
20
%                                                                             %
 
21
%            Read/Write Raw CCIR 601 4:1:1 or 4:2:2 Image Format.             %
 
22
%                                                                             %
 
23
%                                                                             %
 
24
%                              Software Design                                %
 
25
%                                John Cristy                                  %
 
26
%                                 July 1992                                   %
 
27
%                                                                             %
 
28
%                                                                             %
 
29
%                                                                             %
 
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
31
%
 
32
%
 
33
*/
 
34
 
 
35
/*
 
36
  Include declarations.
 
37
*/
 
38
#include "magick/studio.h"
 
39
#include "magick/blob.h"
 
40
#include "magick/cache.h"
 
41
#include "magick/magick.h"
 
42
#include "magick/monitor.h"
 
43
#include "magick/resize.h"
 
44
#include "magick/utility.h"
 
45
 
 
46
/*
 
47
  Forward declarations.
 
48
*/
 
49
static unsigned int
 
50
  WriteYUVImage(const ImageInfo *,Image *);
 
51
 
 
52
/*
 
53
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
54
%                                                                             %
 
55
%                                                                             %
 
56
%                                                                             %
 
57
%   R e a d Y U V I m a g e                                                   %
 
58
%                                                                             %
 
59
%                                                                             %
 
60
%                                                                             %
 
61
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
62
%
 
63
%  Method ReadYUVImage reads an image with digital YUV (CCIR 601 4:1:1, plane
 
64
%  or partition interlaced, or 4:2:2 plane, partition interlaced or
 
65
%  noninterlaced) bytes and returns it.  It allocates the memory necessary
 
66
%  for the new Image structure and returns a pointer to the new image.
 
67
%
 
68
%  The format of the ReadYUVImage method is:
 
69
%
 
70
%      Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
71
%
 
72
%  A description of each parameter follows:
 
73
%
 
74
%    o image:  Method ReadYUVImage returns a pointer to the image after
 
75
%      reading.  A null image is returned if there is a memory shortage or
 
76
%      if the image cannot be read.
 
77
%
 
78
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
79
%
 
80
%    o exception: return any errors or warnings in this structure.
 
81
%
 
82
%
 
83
*/
 
84
static Image *ReadYUVImage(const ImageInfo *image_info,ExceptionInfo *exception)
 
85
{
 
86
  Image
 
87
    *chroma_image,
 
88
    *image,
 
89
    *resize_image;
 
90
 
 
91
  long
 
92
    horizontal_factor,
 
93
    vertical_factor,
 
94
    y;
 
95
 
 
96
  register const PixelPacket
 
97
    *r;
 
98
 
 
99
  register long
 
100
    x;
 
101
 
 
102
  register PixelPacket
 
103
    *q,
 
104
    *s;
 
105
 
 
106
  register long
 
107
    i;
 
108
 
 
109
  register unsigned char
 
110
    *p;
 
111
 
 
112
  size_t
 
113
    count;
 
114
 
 
115
  unsigned char
 
116
    *scanline;
 
117
 
 
118
  unsigned int
 
119
    status;
 
120
 
 
121
  InterlaceType
 
122
    interlace;
 
123
 
 
124
  /*
 
125
    Allocate image structure.
 
126
  */
 
127
  assert(image_info != (const ImageInfo *) NULL);
 
128
  assert(image_info->signature == MagickSignature);
 
129
  assert(exception != (ExceptionInfo *) NULL);
 
130
  assert(exception->signature == MagickSignature);
 
131
  image=AllocateImage(image_info);
 
132
  if ((image->columns == 0) || (image->rows == 0))
 
133
    ThrowReaderException(OptionError,MustSpecifyImageSize,image);
 
134
  image->depth=8;
 
135
  interlace=image_info->interlace;
 
136
  horizontal_factor=2;
 
137
  vertical_factor=2;
 
138
  if (image_info->sampling_factor != (char *) NULL)
 
139
    {
 
140
      long
 
141
        factors;
 
142
 
 
143
      factors=sscanf(image_info->sampling_factor,"%ldx%ld",&horizontal_factor,
 
144
        &vertical_factor);
 
145
      if (factors != 2)
 
146
        vertical_factor=horizontal_factor;
 
147
      if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
 
148
          (vertical_factor != 1) && (vertical_factor != 2))
 
149
        ThrowReaderException(CorruptImageError,UnexpectedSamplingFactor,
 
150
          image);
 
151
    }
 
152
  if ((interlace == UndefinedInterlace) ||
 
153
      ((interlace == NoInterlace) && (vertical_factor == 2)))
 
154
    {
 
155
      interlace=NoInterlace;    /* CCIR 4:2:2 */
 
156
      if (vertical_factor == 2)
 
157
        interlace=PlaneInterlace; /* CCIR 4:1:1 */
 
158
    }
 
159
  if (interlace != PartitionInterlace)
 
160
    {
 
161
      /*
 
162
        Open image file.
 
163
      */
 
164
      status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
165
      if (status == False)
 
166
        ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
167
      for (i=0; i < image->offset; i++)
 
168
        (void) ReadBlobByte(image);
 
169
    }
 
170
  /*
 
171
    Allocate memory for a scanline.
 
172
  */
 
173
  if (interlace == NoInterlace)
 
174
    scanline=MagickAllocateMemory(unsigned char *,2*image->columns+2);
 
175
  else
 
176
    scanline=MagickAllocateMemory(unsigned char *,image->columns);
 
177
  if (scanline == (unsigned char *) NULL)
 
178
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
179
  do
 
180
  {
 
181
    chroma_image=CloneImage(image,image->columns/horizontal_factor,
 
182
      image->rows/vertical_factor,True,exception);
 
183
    if (chroma_image == (Image *) NULL)
 
184
      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
185
    /*
 
186
      Convert raster image to pixel packets.
 
187
    */
 
188
    if (image_info->ping && (image_info->subrange != 0))
 
189
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
190
        break;
 
191
    if (interlace == PartitionInterlace)
 
192
      {
 
193
        AppendImageFormat("Y",image->filename);
 
194
        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
195
        if (status == False)
 
196
          ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
197
      }
 
198
    for (y=0; y < (long) image->rows; y++)
 
199
    {
 
200
      if (interlace == NoInterlace)
 
201
        {
 
202
          if ((y > 0) || (image->previous == (Image *) NULL))
 
203
            (void) ReadBlob(image,2*image->columns,scanline);
 
204
          p=scanline;
 
205
          q=SetImagePixels(image,0,y,image->columns,1);
 
206
          if (q == (PixelPacket *) NULL)
 
207
            break;
 
208
          s=SetImagePixels(chroma_image,0,y,chroma_image->columns,1);
 
209
          if (s == (PixelPacket *) NULL)
 
210
            break;
 
211
          for (x=0; x < (long) image->columns; x+=2)
 
212
          {
 
213
            s->red=0;
 
214
            s->green=ScaleCharToQuantum(*p++);
 
215
            q->red=ScaleCharToQuantum(*p++);
 
216
            q->green=0;
 
217
            q->blue=0;
 
218
            q++;
 
219
            q->green=0;
 
220
            q->blue=0;
 
221
            s->blue=ScaleCharToQuantum(*p++);
 
222
            q->red=ScaleCharToQuantum(*p++);
 
223
            s++;
 
224
            q++;
 
225
          }
 
226
        }
 
227
      else
 
228
        {
 
229
          if ((y > 0) || (image->previous == (Image *) NULL))
 
230
            (void) ReadBlob(image,image->columns,scanline);
 
231
          p=scanline;
 
232
          q=SetImagePixels(image,0,y,image->columns,1);
 
233
          if (q == (PixelPacket *) NULL)
 
234
            break;
 
235
          for (x=0; x < (long) image->columns; x++)
 
236
          {
 
237
            q->red=ScaleCharToQuantum(*p++);
 
238
            q->green=0;
 
239
            q->blue=0;
 
240
            q++;
 
241
          }
 
242
        }
 
243
      if (!SyncImagePixels(image))
 
244
        break;
 
245
      if (interlace == NoInterlace)
 
246
        if (!SyncImagePixels(chroma_image))
 
247
          break;
 
248
      if (image->previous == (Image *) NULL)
 
249
        if (!MagickMonitor(LoadImageText,y,image->rows,exception))
 
250
          break;
 
251
    }
 
252
    if (interlace == PartitionInterlace)
 
253
      {
 
254
        CloseBlob(image);
 
255
        AppendImageFormat("U",image->filename);
 
256
        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
257
        if (status == False)
 
258
          ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
259
      }
 
260
    if (interlace != NoInterlace)
 
261
      {
 
262
        for (y=0; y < (long) chroma_image->rows; y++)
 
263
        {
 
264
          (void) ReadBlob(image,chroma_image->columns,scanline);
 
265
          p=scanline;
 
266
          q=SetImagePixels(chroma_image,0,y,chroma_image->columns,1);
 
267
          if (q == (PixelPacket *) NULL)
 
268
            break;
 
269
          for (x=0; x < (long) chroma_image->columns; x++)
 
270
          {
 
271
            q->red=0;
 
272
            q->green=ScaleCharToQuantum(*p++);
 
273
            q->blue=0;
 
274
            q++;
 
275
          }
 
276
          if (!SyncImagePixels(chroma_image))
 
277
            break;
 
278
        }
 
279
      if (interlace == PartitionInterlace)
 
280
        {
 
281
          CloseBlob(image);
 
282
          AppendImageFormat("V",image->filename);
 
283
          status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
 
284
          if (status == False)
 
285
            ThrowReaderException(FileOpenError,UnableToOpenFile,image);
 
286
        }
 
287
      for (y=0; y < (long) chroma_image->rows; y++)
 
288
      {
 
289
        (void) ReadBlob(image,chroma_image->columns,scanline);
 
290
        p=scanline;
 
291
        q=GetImagePixels(chroma_image,0,y,chroma_image->columns,1);
 
292
        if (q == (PixelPacket *) NULL)
 
293
          break;
 
294
        for (x=0; x < (long) chroma_image->columns; x++)
 
295
        {
 
296
          q->blue=ScaleCharToQuantum(*p++);
 
297
          q++;
 
298
        }
 
299
        if (!SyncImagePixels(chroma_image))
 
300
          break;
 
301
      }
 
302
    }
 
303
    /*
 
304
      Scale image.
 
305
    */
 
306
    resize_image=ResizeImage(chroma_image,image->columns,image->rows,
 
307
      TriangleFilter,1.0,exception);
 
308
    DestroyImage(chroma_image);
 
309
    if (resize_image == (Image *) NULL)
 
310
      ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
 
311
    for (y=0; y < (long) image->rows; y++)
 
312
    {
 
313
      q=GetImagePixels(image,0,y,image->columns,1);
 
314
      r=AcquireImagePixels(resize_image,0,y,resize_image->columns,1,
 
315
        &resize_image->exception);
 
316
      if ((q == (PixelPacket *) NULL) || (r == (const PixelPacket *) NULL))
 
317
        break;
 
318
      for (x=0; x < (long) image->columns; x++)
 
319
      {
 
320
        q->green=r->green;
 
321
        q->blue=r->blue;
 
322
        r++;
 
323
        q++;
 
324
      }
 
325
      if (!SyncImagePixels(image))
 
326
        break;
 
327
    }
 
328
    DestroyImage(resize_image);
 
329
    image->colorspace=YCbCrColorspace;
 
330
    TransformColorspace(image,RGBColorspace);
 
331
    if (interlace == PartitionInterlace)
 
332
      (void) strncpy(image->filename,image_info->filename,MaxTextExtent-1);
 
333
    if (EOFBlob(image))
 
334
      {
 
335
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
 
336
          image->filename);
 
337
        break;
 
338
      }
 
339
    /*
 
340
      Proceed to next image.
 
341
    */
 
342
    if (image_info->subrange != 0)
 
343
      if (image->scene >= (image_info->subimage+image_info->subrange-1))
 
344
        break;
 
345
    if (interlace == NoInterlace)
 
346
      count=ReadBlob(image,2*image->columns,(char *) scanline);
 
347
    else
 
348
      count=ReadBlob(image,image->columns,(char *) scanline);
 
349
    if (count != 0)
 
350
      {
 
351
        /*
 
352
          Allocate next image structure.
 
353
        */
 
354
        AllocateNextImage(image_info,image);
 
355
        if (image->next == (Image *) NULL)
 
356
          {
 
357
            DestroyImageList(image);
 
358
            return((Image *) NULL);
 
359
          }
 
360
        image=SyncNextImageInList(image);
 
361
        if (!MagickMonitor(LoadImagesText,TellBlob(image),GetBlobSize(image),exception))
 
362
          break;
 
363
      }
 
364
  } while (count != 0);
 
365
  MagickFreeMemory(scanline);
 
366
  while (image->previous != (Image *) NULL)
 
367
    image=image->previous;
 
368
  CloseBlob(image);
 
369
  return(image);
 
370
}
 
371
 
 
372
/*
 
373
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
374
%                                                                             %
 
375
%                                                                             %
 
376
%                                                                             %
 
377
%   R e g i s t e r Y U V I m a g e                                           %
 
378
%                                                                             %
 
379
%                                                                             %
 
380
%                                                                             %
 
381
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
382
%
 
383
%  Method RegisterYUVImage adds attributes for the YUV image format to
 
384
%  the list of supported formats.  The attributes include the image format
 
385
%  tag, a method to read and/or write the format, whether the format
 
386
%  supports the saving of more than one frame to the same file or blob,
 
387
%  whether the format supports native in-memory I/O, and a brief
 
388
%  description of the format.
 
389
%
 
390
%  The format of the RegisterYUVImage method is:
 
391
%
 
392
%      RegisterYUVImage(void)
 
393
%
 
394
*/
 
395
ModuleExport void RegisterYUVImage(void)
 
396
{
 
397
  MagickInfo
 
398
    *entry;
 
399
 
 
400
  entry=SetMagickInfo("YUV");
 
401
  entry->decoder=(DecoderHandler) ReadYUVImage;
 
402
  entry->encoder=(EncoderHandler) WriteYUVImage;
 
403
  entry->adjoin=False;
 
404
  entry->raw=True;
 
405
  entry->description=AcquireString("CCIR 601 4:1:1 or 4:2:2");
 
406
  entry->module=AcquireString("YUV");
 
407
  (void) RegisterMagickInfo(entry);
 
408
}
 
409
 
 
410
/*
 
411
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
412
%                                                                             %
 
413
%                                                                             %
 
414
%                                                                             %
 
415
%   U n r e g i s t e r Y U V I m a g e                                       %
 
416
%                                                                             %
 
417
%                                                                             %
 
418
%                                                                             %
 
419
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
420
%
 
421
%  Method UnregisterYUVImage removes format registrations made by the
 
422
%  YUV module from the list of supported formats.
 
423
%
 
424
%  The format of the UnregisterYUVImage method is:
 
425
%
 
426
%      UnregisterYUVImage(void)
 
427
%
 
428
*/
 
429
ModuleExport void UnregisterYUVImage(void)
 
430
{
 
431
  (void) UnregisterMagickInfo("YUV");
 
432
}
 
433
 
 
434
/*
 
435
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
436
%                                                                             %
 
437
%                                                                             %
 
438
%                                                                             %
 
439
%   W r i t e Y U V I m a g e                                                 %
 
440
%                                                                             %
 
441
%                                                                             %
 
442
%                                                                             %
 
443
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
444
%
 
445
%  Method WriteYUVImage writes an image to a file in the digital YUV
 
446
%  (CCIR 601 4:1:1, plane or partition interlaced, or 4:2:2 plane, partition
 
447
%  interlaced or noninterlaced) bytes and returns it.
 
448
%
 
449
%  The format of the WriteYUVImage method is:
 
450
%
 
451
%      unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image)
 
452
%
 
453
%  A description of each parameter follows.
 
454
%
 
455
%    o status: Method WriteYUVImage return True if the image is written.
 
456
%      False is returned is there is a memory shortage or if the image file
 
457
%      fails to write.
 
458
%
 
459
%    o image_info: Specifies a pointer to a ImageInfo structure.
 
460
%
 
461
%    o image:  A pointer to an Image structure.
 
462
%
 
463
%
 
464
*/
 
465
static unsigned int WriteYUVImage(const ImageInfo *image_info,Image *image)
 
466
{
 
467
  Image
 
468
    *chroma_image,
 
469
    *yuv_image;
 
470
 
 
471
  InterlaceType
 
472
    interlace;
 
473
 
 
474
  long
 
475
    horizontal_factor,
 
476
    vertical_factor,
 
477
    y;
 
478
 
 
479
  register const PixelPacket
 
480
    *p,
 
481
    *s;
 
482
 
 
483
  register long
 
484
    x;
 
485
 
 
486
  unsigned int
 
487
    status;
 
488
 
 
489
  unsigned long
 
490
    scene,
 
491
    height,
 
492
    width;
 
493
 
 
494
  assert(image_info != (const ImageInfo *) NULL);
 
495
  assert(image_info->signature == MagickSignature);
 
496
  assert(image != (Image *) NULL);
 
497
  assert(image->signature == MagickSignature);
 
498
  interlace=image_info->interlace;
 
499
  horizontal_factor=2;
 
500
  vertical_factor=2;
 
501
  if (image_info->sampling_factor != (char *) NULL)
 
502
    {
 
503
      long
 
504
        factors;
 
505
 
 
506
      factors=sscanf(image_info->sampling_factor,"%ldx%ld",&horizontal_factor,
 
507
        &vertical_factor);
 
508
      if (factors != 2)
 
509
        vertical_factor=horizontal_factor;
 
510
      if ((horizontal_factor != 1) && (horizontal_factor != 2) &&
 
511
          (vertical_factor != 1) && (vertical_factor != 2))
 
512
        ThrowWriterException(CorruptImageError,UnexpectedSamplingFactor,
 
513
          image);
 
514
    }
 
515
  if ((interlace == UndefinedInterlace) ||
 
516
      ((interlace == NoInterlace) && (vertical_factor == 2)))
 
517
    {
 
518
      interlace=NoInterlace;    /* CCIR 4:2:2 */
 
519
      if (vertical_factor == 2)
 
520
        interlace=PlaneInterlace; /* CCIR 4:1:1 */
 
521
    }
 
522
  if (interlace != PartitionInterlace)
 
523
    {
 
524
      /*
 
525
        Open output image file.
 
526
      */
 
527
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
528
      if (status == False)
 
529
        ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
530
    }
 
531
  else
 
532
    {
 
533
      AppendImageFormat("Y",image->filename);
 
534
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
 
535
      if (status == False)
 
536
        ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
537
    }
 
538
  scene=0;
 
539
  do
 
540
  {
 
541
    /*
 
542
      Sample image to an even width and height, if necessary.
 
543
    */
 
544
    image->depth=8;
 
545
    TransformColorspace(image,RGBColorspace);
 
546
    width=image->columns+(image->columns & (horizontal_factor-1));
 
547
    height=image->rows+(image->rows & (vertical_factor-1));
 
548
    yuv_image=ResizeImage(image,width,height,TriangleFilter,1.0,
 
549
      &image->exception);
 
550
    if (yuv_image == (Image *) NULL)
 
551
      ThrowWriterException2(ResourceLimitError,image->exception.reason,image);
 
552
    TransformColorspace(yuv_image,YCbCrColorspace);
 
553
    /*
 
554
      Downsample image.
 
555
    */
 
556
    chroma_image=ResizeImage(image,width/horizontal_factor,
 
557
      height/vertical_factor,TriangleFilter,1.0,&image->exception);
 
558
    if (chroma_image == (Image *) NULL)
 
559
      ThrowWriterException2(ResourceLimitError,image->exception.reason,image);
 
560
    TransformColorspace(chroma_image,YCbCrColorspace);
 
561
    if (interlace == NoInterlace)
 
562
      {
 
563
        /*
 
564
          Write noninterlaced YUV.
 
565
        */
 
566
        for (y=0; y < (long) yuv_image->rows; y++)
 
567
        {
 
568
          p=AcquireImagePixels(yuv_image,0,y,yuv_image->columns,1,
 
569
            &yuv_image->exception);
 
570
          if (p == (const PixelPacket *) NULL)
 
571
            break;
 
572
          s=AcquireImagePixels(chroma_image,0,y,chroma_image->columns,1,
 
573
            &chroma_image->exception);
 
574
          if (s == (const PixelPacket *) NULL)
 
575
            break;
 
576
          for (x=0; x < (long) yuv_image->columns; x++)
 
577
          {
 
578
            (void) WriteBlobByte(image,ScaleQuantumToChar(s->green));
 
579
            (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
 
580
            p++;
 
581
            (void) WriteBlobByte(image,ScaleQuantumToChar(s->blue));
 
582
            (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
 
583
            p++;
 
584
            s++;
 
585
            x++;
 
586
          }
 
587
          if (image->previous == (Image *) NULL)
 
588
            if (QuantumTick(y,image->rows))
 
589
              if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
590
                break;
 
591
        }
 
592
        DestroyImage(yuv_image);
 
593
      }
 
594
    else
 
595
      {
 
596
        /*
 
597
          Initialize Y channel.
 
598
        */
 
599
        for (y=0; y < (long) yuv_image->rows; y++)
 
600
        {
 
601
          p=AcquireImagePixels(yuv_image,0,y,yuv_image->columns,1,
 
602
            &yuv_image->exception);
 
603
          if (p == (const PixelPacket *) NULL)
 
604
            break;
 
605
          for (x=0; x < (long) yuv_image->columns; x++)
 
606
          {
 
607
            (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
 
608
            p++;
 
609
          }
 
610
          if (image->previous == (Image *) NULL)
 
611
            if (QuantumTick(y,image->rows))
 
612
              if (!MagickMonitor(SaveImageText,y,image->rows,&image->exception))
 
613
                break;
 
614
        }
 
615
        DestroyImage(yuv_image);
 
616
        /*
 
617
          Initialize U channel.
 
618
        */
 
619
        if (interlace == PartitionInterlace)
 
620
          {
 
621
            CloseBlob(image);
 
622
            AppendImageFormat("U",image->filename);
 
623
            status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
624
              &image->exception);
 
625
            if (status == False)
 
626
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
627
          }
 
628
        for (y=0; y < (long) chroma_image->rows; y++)
 
629
        {
 
630
          p=AcquireImagePixels(chroma_image,0,y,chroma_image->columns,1,
 
631
            &chroma_image->exception);
 
632
          if (p == (const PixelPacket *) NULL)
 
633
            break;
 
634
          for (x=0; x < (long) chroma_image->columns; x++)
 
635
          {
 
636
            (void) WriteBlobByte(image,ScaleQuantumToChar(p->green));
 
637
            p++;
 
638
          }
 
639
        }
 
640
        /*
 
641
          Initialize V channel.
 
642
        */
 
643
        if (interlace == PartitionInterlace)
 
644
          {
 
645
            CloseBlob(image);
 
646
            AppendImageFormat("V",image->filename);
 
647
            status=OpenBlob(image_info,image,WriteBinaryBlobMode,
 
648
              &image->exception);
 
649
            if (status == False)
 
650
              ThrowWriterException(FileOpenError,UnableToOpenFile,image);
 
651
          }
 
652
        for (y=0; y < (long) chroma_image->rows; y++)
 
653
        {
 
654
          p=AcquireImagePixels(chroma_image,0,y,chroma_image->columns,1,
 
655
            &chroma_image->exception);
 
656
          if (p == (const PixelPacket *) NULL)
 
657
            break;
 
658
          for (x=0; x < (long) chroma_image->columns; x++)
 
659
          {
 
660
            (void) WriteBlobByte(image,ScaleQuantumToChar(p->blue));
 
661
            p++;
 
662
          }
 
663
        }
 
664
      }
 
665
    DestroyImage(chroma_image);
 
666
    if (interlace == PartitionInterlace)
 
667
      (void) strncpy(image->filename,image_info->filename,MaxTextExtent-1);
 
668
    if (image->next == (Image *) NULL)
 
669
      break;
 
670
    image=SyncNextImageInList(image);
 
671
    status=MagickMonitor(SaveImagesText,scene++,GetImageListLength(image),
 
672
      &image->exception);
 
673
    if (status == False)
 
674
      break;
 
675
  } while (image_info->adjoin);
 
676
  if (image_info->adjoin)
 
677
    while (image->previous != (Image *) NULL)
 
678
      image=image->previous;
 
679
  CloseBlob(image);
 
680
  return(True);
 
681
}