Coverage Report

Created: 2025-11-14 07:32

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/ycbcr.c
Line
Count
Source
1
/*
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
%                                   Cristy                                    %
17
%                                 July 1992                                   %
18
%                                                                             %
19
%                                                                             %
20
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
21
%  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
%    https://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 "MagickCore/studio.h"
43
#include "MagickCore/blob.h"
44
#include "MagickCore/blob-private.h"
45
#include "MagickCore/cache.h"
46
#include "MagickCore/channel.h"
47
#include "MagickCore/colorspace.h"
48
#include "MagickCore/constitute.h"
49
#include "MagickCore/exception.h"
50
#include "MagickCore/exception-private.h"
51
#include "MagickCore/image.h"
52
#include "MagickCore/image-private.h"
53
#include "MagickCore/list.h"
54
#include "MagickCore/magick.h"
55
#include "MagickCore/memory_.h"
56
#include "MagickCore/monitor.h"
57
#include "MagickCore/monitor-private.h"
58
#include "MagickCore/pixel-accessor.h"
59
#include "MagickCore/quantum-private.h"
60
#include "MagickCore/static.h"
61
#include "MagickCore/statistic.h"
62
#include "MagickCore/string_.h"
63
#include "MagickCore/module.h"
64
#include "MagickCore/utility.h"
65

66
/*
67
  Forward declarations.
68
*/
69
static MagickBooleanType
70
  WriteYCBCRImage(const ImageInfo *,Image *,ExceptionInfo *);
71

72
/*
73
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74
%                                                                             %
75
%                                                                             %
76
%                                                                             %
77
%   R e a d Y C b C r I m a g e                                               %
78
%                                                                             %
79
%                                                                             %
80
%                                                                             %
81
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
82
%
83
%  ReadYCBCRImage() reads an image of raw YCbCr or YCbCrA samples and returns
84
%  it. It allocates the memory necessary for the new Image structure and
85
%  returns a pointer to the new image.
86
%
87
%  The format of the ReadYCBCRImage method is:
88
%
89
%      Image *ReadYCBCRImage(const ImageInfo *image_info,
90
%        ExceptionInfo *exception)
91
%
92
%  A description of each parameter follows:
93
%
94
%    o image_info: the image info.
95
%
96
%    o exception: return any errors or warnings in this structure.
97
%
98
*/
99
static Image *ReadYCBCRImage(const ImageInfo *image_info,
100
  ExceptionInfo *exception)
101
307
{
102
307
  const void
103
307
    *stream;
104
105
307
  Image
106
307
    *canvas_image,
107
307
    *image;
108
109
307
  MagickBooleanType
110
307
    status;
111
112
307
  MagickOffsetType
113
307
    scene;
114
115
307
  QuantumInfo
116
307
    *quantum_info;
117
118
307
  QuantumType
119
307
    quantum_type;
120
121
307
  ssize_t
122
307
    i;
123
124
307
  size_t
125
307
    length;
126
127
307
  ssize_t
128
307
    count,
129
307
    y;
130
131
307
  unsigned char
132
307
    *pixels;
133
134
  /*
135
    Open image file.
136
  */
137
307
  assert(image_info != (const ImageInfo *) NULL);
138
307
  assert(image_info->signature == MagickCoreSignature);
139
307
  assert(exception != (ExceptionInfo *) NULL);
140
307
  assert(exception->signature == MagickCoreSignature);
141
307
  if (IsEventLogging() != MagickFalse)
142
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
143
0
      image_info->filename);
144
307
  image=AcquireImage(image_info,exception);
145
307
  if ((image->columns == 0) || (image->rows == 0))
146
307
    ThrowReaderException(OptionError,"MustSpecifyImageSize");
147
0
  status=SetImageExtent(image,image->columns,image->rows,exception);
148
0
  if (status == MagickFalse)
149
0
    return(DestroyImageList(image));
150
0
  (void) SetImageColorspace(image,YCbCrColorspace,exception);
151
0
  if (image_info->interlace != PartitionInterlace)
152
0
    {
153
0
      status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
154
0
      if (status == MagickFalse)
155
0
        {
156
0
          image=DestroyImageList(image);
157
0
          return((Image *) NULL);
158
0
        }
159
0
      if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
160
0
        ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile",
161
0
          image->filename);
162
0
    }
163
  /*
164
    Create virtual canvas to support cropping (i.e. image.rgb[100x100+10+20]).
165
  */
166
0
  canvas_image=CloneImage(image,image->extract_info.width,1,MagickFalse,
167
0
    exception);
168
0
  if (canvas_image == (Image *) NULL)
169
0
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
170
0
  (void) SetImageVirtualPixelMethod(canvas_image,BlackVirtualPixelMethod,
171
0
    exception);
172
0
  quantum_info=AcquireQuantumInfo(image_info,canvas_image);
173
0
  if (quantum_info == (QuantumInfo *) NULL)
174
0
    {
175
0
      canvas_image=DestroyImage(canvas_image);
176
0
      ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
177
0
    }
178
0
  quantum_type=RGBQuantum;
179
0
  if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
180
0
    {
181
0
      quantum_type=RGBAQuantum;
182
0
      canvas_image->alpha_trait=BlendPixelTrait;
183
0
    }
184
0
  pixels=GetQuantumPixels(quantum_info);
185
0
  if (image_info->number_scenes != 0)
186
0
    while (image->scene < image_info->scene)
187
0
    {
188
      /*
189
        Skip to next image.
190
      */
191
0
      image->scene++;
192
0
      length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
193
0
      for (y=0; y < (ssize_t) image->rows; y++)
194
0
      {
195
0
        stream=ReadBlobStream(image,length,pixels,&count);
196
0
        if (count != (ssize_t) length)
197
0
          break;
198
0
      }
199
0
    }
200
0
  count=0;
201
0
  length=0;
202
0
  scene=0;
203
0
  status=MagickTrue;
204
0
  stream=NULL;
205
0
  do
206
0
  {
207
    /*
208
      Read pixels to virtual canvas image then push to image.
209
    */
210
0
    image->alpha_trait=canvas_image->alpha_trait;
211
0
    if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0))
212
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
213
0
        break;
214
0
    status=SetImageExtent(image,image->columns,image->rows,exception);
215
0
    if (status == MagickFalse)
216
0
      break;
217
0
    if (SetImageColorspace(image,YCbCrColorspace,exception) == MagickFalse)
218
0
      break;
219
0
    switch (image_info->interlace)
220
0
    {
221
0
      case NoInterlace:
222
0
      default:
223
0
      {
224
        /*
225
          No interlacing:  YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
226
        */
227
0
        if (scene == 0)
228
0
          {
229
0
            length=GetQuantumExtent(canvas_image,quantum_info,quantum_type);
230
0
            stream=ReadBlobStream(image,length,pixels,&count);
231
0
          }
232
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
233
0
        {
234
0
          const Quantum
235
0
            *magick_restrict p;
236
237
0
          Quantum
238
0
            *magick_restrict q;
239
240
0
          ssize_t
241
0
            x;
242
243
0
          if (count != (ssize_t) length)
244
0
            {
245
0
              status=MagickFalse;
246
0
              ThrowFileException(exception,CorruptImageError,
247
0
                "UnexpectedEndOfFile",image->filename);
248
0
              break;
249
0
            }
250
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
251
0
            exception);
252
0
          if (q == (Quantum *) NULL)
253
0
            break;
254
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
255
0
            quantum_info,quantum_type,(unsigned char *) stream,exception);
256
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
257
0
            break;
258
0
          if (((y-image->extract_info.y) >= 0) &&
259
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
260
0
            {
261
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
262
0
                canvas_image->columns,1,exception);
263
0
              q=QueueAuthenticPixels(image,0,y-image->extract_info.y,
264
0
                image->columns,1,exception);
265
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
266
0
                break;
267
0
              for (x=0; x < (ssize_t) image->columns; x++)
268
0
              {
269
0
                SetPixelRed(image,GetPixelRed(canvas_image,p),q);
270
0
                SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
271
0
                SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
272
0
                SetPixelAlpha(image,OpaqueAlpha,q);
273
0
                if (image->alpha_trait != UndefinedPixelTrait)
274
0
                  SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
275
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
276
0
                q+=(ptrdiff_t) GetPixelChannels(image);
277
0
              }
278
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
279
0
                break;
280
0
            }
281
0
          if (image->previous == (Image *) NULL)
282
0
            {
283
0
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
284
0
                image->rows);
285
0
              if (status == MagickFalse)
286
0
                break;
287
0
            }
288
0
          stream=ReadBlobStream(image,length,pixels,&count);
289
0
        }
290
0
        break;
291
0
      }
292
0
      case LineInterlace:
293
0
      {
294
0
        static QuantumType
295
0
          quantum_types[4] =
296
0
          {
297
0
            RedQuantum,
298
0
            GreenQuantum,
299
0
            BlueQuantum,
300
0
            AlphaQuantum
301
0
          };
302
303
        /*
304
          Line interlacing:  YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
305
        */
306
0
        if (scene == 0)
307
0
          {
308
0
            length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
309
0
            stream=ReadBlobStream(image,length,pixels,&count);
310
0
          }
311
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
312
0
        {
313
0
          for (i=0; i < (ssize_t) (image->alpha_trait != UndefinedPixelTrait ? 4 : 3); i++)
314
0
          {
315
0
            const Quantum
316
0
              *magick_restrict p;
317
318
0
            Quantum
319
0
              *magick_restrict q;
320
321
0
            ssize_t
322
0
              x;
323
324
0
            if (count != (ssize_t) length)
325
0
              {
326
0
                status=MagickFalse;
327
0
                ThrowFileException(exception,CorruptImageError,
328
0
                  "UnexpectedEndOfFile",image->filename);
329
0
                break;
330
0
              }
331
0
            quantum_type=quantum_types[i];
332
0
            q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
333
0
              exception);
334
0
            if (q == (Quantum *) NULL)
335
0
              break;
336
0
            length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
337
0
              quantum_info,quantum_type,(unsigned char *) stream,exception);
338
0
            if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
339
0
              break;
340
0
            if (((y-image->extract_info.y) >= 0) &&
341
0
                ((y-image->extract_info.y) < (ssize_t) image->rows))
342
0
              {
343
0
                p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
344
0
                  0,canvas_image->columns,1,exception);
345
0
                q=GetAuthenticPixels(image,0,y-image->extract_info.y,
346
0
                  image->columns,1,exception);
347
0
                if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
348
0
                  break;
349
0
                for (x=0; x < (ssize_t) image->columns; x++)
350
0
                {
351
0
                  switch (quantum_type)
352
0
                  {
353
0
                    case RedQuantum:
354
0
                    {
355
0
                      SetPixelRed(image,GetPixelRed(canvas_image,p),q);
356
0
                      break;
357
0
                    }
358
0
                    case GreenQuantum:
359
0
                    {
360
0
                      SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
361
0
                      break;
362
0
                    }
363
0
                    case BlueQuantum:
364
0
                    {
365
0
                      SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
366
0
                      break;
367
0
                    }
368
0
                    case AlphaQuantum:
369
0
                    {
370
0
                      SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
371
0
                      break;
372
0
                    }
373
0
                    default:
374
0
                      break;
375
0
                  }
376
0
                  p+=(ptrdiff_t) GetPixelChannels(canvas_image);
377
0
                  q+=(ptrdiff_t) GetPixelChannels(image);
378
0
                }
379
0
                if (SyncAuthenticPixels(image,exception) == MagickFalse)
380
0
                  break;
381
0
              }
382
0
            stream=ReadBlobStream(image,length,pixels,&count);
383
0
          }
384
0
          if (image->previous == (Image *) NULL)
385
0
            {
386
0
              status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
387
0
                image->rows);
388
0
              if (status == MagickFalse)
389
0
                break;
390
0
            }
391
0
        }
392
0
        break;
393
0
      }
394
0
      case PlaneInterlace:
395
0
      {
396
        /*
397
          Plane interlacing:  YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
398
        */
399
0
        if (scene == 0)
400
0
          {
401
0
            length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
402
0
            stream=ReadBlobStream(image,length,pixels,&count);
403
0
          }
404
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
405
0
        {
406
0
          const Quantum
407
0
            *magick_restrict p;
408
409
0
          Quantum
410
0
            *magick_restrict q;
411
412
0
          ssize_t
413
0
            x;
414
415
0
          if (count != (ssize_t) length)
416
0
            {
417
0
              status=MagickFalse;
418
0
              ThrowFileException(exception,CorruptImageError,
419
0
                "UnexpectedEndOfFile",image->filename);
420
0
              break;
421
0
            }
422
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
423
0
            exception);
424
0
          if (q == (Quantum *) NULL)
425
0
            break;
426
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
427
0
            quantum_info,RedQuantum,(unsigned char *) stream,exception);
428
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
429
0
            break;
430
0
          if (((y-image->extract_info.y) >= 0) &&
431
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
432
0
            {
433
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
434
0
                canvas_image->columns,1,exception);
435
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
436
0
                image->columns,1,exception);
437
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
438
0
                break;
439
0
              for (x=0; x < (ssize_t) image->columns; x++)
440
0
              {
441
0
                SetPixelRed(image,GetPixelRed(canvas_image,p),q);
442
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
443
0
                q+=(ptrdiff_t) GetPixelChannels(image);
444
0
              }
445
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
446
0
                break;
447
0
            }
448
0
          stream=ReadBlobStream(image,length,pixels,&count);
449
0
        }
450
0
        if (image->previous == (Image *) NULL)
451
0
          {
452
0
            status=SetImageProgress(image,LoadImageTag,1,5);
453
0
            if (status == MagickFalse)
454
0
              break;
455
0
          }
456
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
457
0
        {
458
0
          const Quantum
459
0
            *magick_restrict p;
460
461
0
          Quantum
462
0
            *magick_restrict q;
463
464
0
          ssize_t
465
0
            x;
466
467
0
          if (count != (ssize_t) length)
468
0
            {
469
0
              status=MagickFalse;
470
0
              ThrowFileException(exception,CorruptImageError,
471
0
                "UnexpectedEndOfFile",image->filename);
472
0
              break;
473
0
            }
474
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
475
0
            exception);
476
0
          if (q == (Quantum *) NULL)
477
0
            break;
478
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
479
0
            quantum_info,GreenQuantum,(unsigned char *) stream,exception);
480
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
481
0
            break;
482
0
          if (((y-image->extract_info.y) >= 0) &&
483
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
484
0
            {
485
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
486
0
                canvas_image->columns,1,exception);
487
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
488
0
                image->columns,1,exception);
489
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
490
0
                break;
491
0
              for (x=0; x < (ssize_t) image->columns; x++)
492
0
              {
493
0
                SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
494
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
495
0
                q+=(ptrdiff_t) GetPixelChannels(image);
496
0
              }
497
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
498
0
                break;
499
0
            }
500
0
          stream=ReadBlobStream(image,length,pixels,&count);
501
0
        }
502
0
        if (image->previous == (Image *) NULL)
503
0
          {
504
0
            status=SetImageProgress(image,LoadImageTag,2,5);
505
0
            if (status == MagickFalse)
506
0
              break;
507
0
          }
508
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
509
0
        {
510
0
          const Quantum
511
0
            *magick_restrict p;
512
513
0
          Quantum
514
0
            *magick_restrict q;
515
516
0
          ssize_t
517
0
            x;
518
519
0
          if (count != (ssize_t) length)
520
0
            {
521
0
              status=MagickFalse;
522
0
              ThrowFileException(exception,CorruptImageError,
523
0
                "UnexpectedEndOfFile",image->filename);
524
0
              break;
525
0
            }
526
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
527
0
            exception);
528
0
          if (q == (Quantum *) NULL)
529
0
            break;
530
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
531
0
            quantum_info,BlueQuantum,(unsigned char *) stream,exception);
532
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
533
0
            break;
534
0
          if (((y-image->extract_info.y) >= 0) &&
535
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
536
0
            {
537
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
538
0
                canvas_image->columns,1,exception);
539
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
540
0
                image->columns,1,exception);
541
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
542
0
                break;
543
0
              for (x=0; x < (ssize_t) image->columns; x++)
544
0
              {
545
0
                SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
546
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
547
0
                q+=(ptrdiff_t) GetPixelChannels(image);
548
0
              }
549
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
550
0
                break;
551
0
            }
552
0
          stream=ReadBlobStream(image,length,pixels,&count);
553
0
        }
554
0
        if (image->previous == (Image *) NULL)
555
0
          {
556
0
            status=SetImageProgress(image,LoadImageTag,3,5);
557
0
            if (status == MagickFalse)
558
0
              break;
559
0
          }
560
0
        if (image->alpha_trait != UndefinedPixelTrait)
561
0
          {
562
0
            for (y=0; y < (ssize_t) image->extract_info.height; y++)
563
0
            {
564
0
              const Quantum
565
0
                *magick_restrict p;
566
567
0
              Quantum
568
0
                *magick_restrict q;
569
570
0
              ssize_t
571
0
                x;
572
573
0
              if (count != (ssize_t) length)
574
0
                {
575
0
                  status=MagickFalse;
576
0
                  ThrowFileException(exception,CorruptImageError,
577
0
                    "UnexpectedEndOfFile",image->filename);
578
0
                  break;
579
0
                }
580
0
              q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
581
0
                exception);
582
0
              if (q == (Quantum *) NULL)
583
0
                break;
584
0
              length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
585
0
                quantum_info,AlphaQuantum,(unsigned char *) stream,exception);
586
0
              if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
587
0
                break;
588
0
              if (((y-image->extract_info.y) >= 0) &&
589
0
                  ((y-image->extract_info.y) < (ssize_t) image->rows))
590
0
                {
591
0
                  p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
592
0
                    0,canvas_image->columns,1,exception);
593
0
                  q=GetAuthenticPixels(image,0,y-image->extract_info.y,
594
0
                    image->columns,1,exception);
595
0
                  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
596
0
                    break;
597
0
                  for (x=0; x < (ssize_t) image->columns; x++)
598
0
                  {
599
0
                    SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
600
0
                    p+=(ptrdiff_t) GetPixelChannels(canvas_image);
601
0
                    q+=(ptrdiff_t) GetPixelChannels(image);
602
0
                  }
603
0
                  if (SyncAuthenticPixels(image,exception) == MagickFalse)
604
0
                    break;
605
0
                }
606
0
              stream=ReadBlobStream(image,length,pixels,&count);
607
0
            }
608
0
            if (image->previous == (Image *) NULL)
609
0
              {
610
0
                status=SetImageProgress(image,LoadImageTag,4,5);
611
0
                if (status == MagickFalse)
612
0
                  break;
613
0
              }
614
0
          }
615
0
        if (image->previous == (Image *) NULL)
616
0
          {
617
0
            status=SetImageProgress(image,LoadImageTag,5,5);
618
0
            if (status == MagickFalse)
619
0
              break;
620
0
          }
621
0
        break;
622
0
      }
623
0
      case PartitionInterlace:
624
0
      {
625
        /*
626
          Partition interlacing:  YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
627
        */
628
0
        AppendImageFormat("Y",image->filename);
629
0
        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
630
0
        if (status == MagickFalse)
631
0
          break;
632
0
        if (DiscardBlobBytes(image,(MagickSizeType) image->offset) == MagickFalse)
633
0
          {
634
0
            status=MagickFalse;
635
0
            ThrowFileException(exception,CorruptImageError,
636
0
              "UnexpectedEndOfFile",image->filename);
637
0
            break;
638
0
          }
639
0
        length=GetQuantumExtent(canvas_image,quantum_info,RedQuantum);
640
0
        for (i=0; i < (ssize_t) scene; i++)
641
0
        {
642
0
          for (y=0; y < (ssize_t) image->extract_info.height; y++)
643
0
          {
644
0
            stream=ReadBlobStream(image,length,pixels,&count);
645
0
            if (count != (ssize_t) length)
646
0
              break;
647
0
          }
648
0
          if (count != (ssize_t) length)
649
0
            break;
650
0
        }
651
0
        stream=ReadBlobStream(image,length,pixels,&count);
652
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
653
0
        {
654
0
          const Quantum
655
0
            *magick_restrict p;
656
657
0
          Quantum
658
0
            *magick_restrict q;
659
660
0
          ssize_t
661
0
            x;
662
663
0
          if (count != (ssize_t) length)
664
0
            {
665
0
              status=MagickFalse;
666
0
              ThrowFileException(exception,CorruptImageError,
667
0
                "UnexpectedEndOfFile",image->filename);
668
0
              break;
669
0
            }
670
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
671
0
            exception);
672
0
          if (q == (Quantum *) NULL)
673
0
            break;
674
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
675
0
            quantum_info,RedQuantum,(unsigned char *) stream,exception);
676
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
677
0
            break;
678
0
          if (((y-image->extract_info.y) >= 0) &&
679
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
680
0
            {
681
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
682
0
                canvas_image->columns,1,exception);
683
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
684
0
                image->columns,1,exception);
685
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
686
0
                break;
687
0
              for (x=0; x < (ssize_t) image->columns; x++)
688
0
              {
689
0
                SetPixelRed(image,GetPixelRed(canvas_image,p),q);
690
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
691
0
                q+=(ptrdiff_t) GetPixelChannels(image);
692
0
              }
693
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
694
0
                break;
695
0
            }
696
0
          stream=ReadBlobStream(image,length,pixels,&count);
697
0
        }
698
0
        if (image->previous == (Image *) NULL)
699
0
          {
700
0
            status=SetImageProgress(image,LoadImageTag,1,5);
701
0
            if (status == MagickFalse)
702
0
              break;
703
0
          }
704
0
        if (CloseBlob(image) == MagickFalse)
705
0
          break;
706
0
        AppendImageFormat("Cb",image->filename);
707
0
        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
708
0
        if (status == MagickFalse)
709
0
          break;
710
0
        length=GetQuantumExtent(canvas_image,quantum_info,GreenQuantum);
711
0
        for (i=0; i < (ssize_t) scene; i++)
712
0
        {
713
0
          for (y=0; y < (ssize_t) image->extract_info.height; y++)
714
0
          {
715
0
            stream=ReadBlobStream(image,length,pixels,&count);
716
0
            if (count != (ssize_t) length)
717
0
              break;
718
0
          }
719
0
          if (count != (ssize_t) length)
720
0
            break;
721
0
        }
722
0
        stream=ReadBlobStream(image,length,pixels,&count);
723
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
724
0
        {
725
0
          const Quantum
726
0
            *magick_restrict p;
727
728
0
          Quantum
729
0
            *magick_restrict q;
730
731
0
          ssize_t
732
0
            x;
733
734
0
          if (count != (ssize_t) length)
735
0
            {
736
0
              status=MagickFalse;
737
0
              ThrowFileException(exception,CorruptImageError,
738
0
                "UnexpectedEndOfFile",image->filename);
739
0
              break;
740
0
            }
741
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
742
0
            exception);
743
0
          if (q == (Quantum *) NULL)
744
0
            break;
745
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
746
0
            quantum_info,GreenQuantum,(unsigned char *) stream,exception);
747
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
748
0
            break;
749
0
          if (((y-image->extract_info.y) >= 0) &&
750
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
751
0
            {
752
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
753
0
                canvas_image->columns,1,exception);
754
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
755
0
                image->columns,1,exception);
756
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
757
0
                break;
758
0
              for (x=0; x < (ssize_t) image->columns; x++)
759
0
              {
760
0
                SetPixelGreen(image,GetPixelGreen(canvas_image,p),q);
761
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
762
0
                q+=(ptrdiff_t) GetPixelChannels(image);
763
0
              }
764
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
765
0
                break;
766
0
           }
767
0
          stream=ReadBlobStream(image,length,pixels,&count);
768
0
        }
769
0
        if (image->previous == (Image *) NULL)
770
0
          {
771
0
            status=SetImageProgress(image,LoadImageTag,2,5);
772
0
            if (status == MagickFalse)
773
0
              break;
774
0
          }
775
0
        if (CloseBlob(image) == MagickFalse)
776
0
          break;
777
0
        AppendImageFormat("Cr",image->filename);
778
0
        status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
779
0
        if (status == MagickFalse)
780
0
          break;
781
0
        length=GetQuantumExtent(canvas_image,quantum_info,BlueQuantum);
782
0
        for (i=0; i < (ssize_t) scene; i++)
783
0
        {
784
0
          for (y=0; y < (ssize_t) image->extract_info.height; y++)
785
0
          {
786
0
            stream=ReadBlobStream(image,length,pixels,&count);
787
0
            if (count != (ssize_t) length)
788
0
              break;
789
0
          }
790
0
          if (count != (ssize_t) length)
791
0
            break;
792
0
        }
793
0
        stream=ReadBlobStream(image,length,pixels,&count);
794
0
        for (y=0; y < (ssize_t) image->extract_info.height; y++)
795
0
        {
796
0
          const Quantum
797
0
            *magick_restrict p;
798
799
0
          Quantum
800
0
            *magick_restrict q;
801
802
0
          ssize_t
803
0
            x;
804
805
0
          if (count != (ssize_t) length)
806
0
            {
807
0
              status=MagickFalse;
808
0
              ThrowFileException(exception,CorruptImageError,
809
0
                "UnexpectedEndOfFile",image->filename);
810
0
              break;
811
0
            }
812
0
          q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
813
0
            exception);
814
0
          if (q == (Quantum *) NULL)
815
0
            break;
816
0
          length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
817
0
            quantum_info,BlueQuantum,(unsigned char *) stream,exception);
818
0
          if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
819
0
            break;
820
0
          if (((y-image->extract_info.y) >= 0) &&
821
0
              ((y-image->extract_info.y) < (ssize_t) image->rows))
822
0
            {
823
0
              p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,0,
824
0
                canvas_image->columns,1,exception);
825
0
              q=GetAuthenticPixels(image,0,y-image->extract_info.y,
826
0
                image->columns,1,exception);
827
0
              if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
828
0
                break;
829
0
              for (x=0; x < (ssize_t) image->columns; x++)
830
0
              {
831
0
                SetPixelBlue(image,GetPixelBlue(canvas_image,p),q);
832
0
                p+=(ptrdiff_t) GetPixelChannels(canvas_image);
833
0
                q+=(ptrdiff_t) GetPixelChannels(image);
834
0
              }
835
0
              if (SyncAuthenticPixels(image,exception) == MagickFalse)
836
0
                break;
837
0
           }
838
0
          stream=ReadBlobStream(image,length,pixels,&count);
839
0
        }
840
0
        if (image->previous == (Image *) NULL)
841
0
          {
842
0
            status=SetImageProgress(image,LoadImageTag,3,5);
843
0
            if (status == MagickFalse)
844
0
              break;
845
0
          }
846
0
        if (image->alpha_trait != UndefinedPixelTrait)
847
0
          {
848
0
            (void) CloseBlob(image);
849
0
            if (CloseBlob(image) == MagickFalse)
850
0
              break;
851
0
            AppendImageFormat("A",image->filename);
852
0
            status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
853
0
            if (status == MagickFalse)
854
0
              break;
855
0
            length=GetQuantumExtent(canvas_image,quantum_info,AlphaQuantum);
856
0
            for (i=0; i < (ssize_t) scene; i++)
857
0
            {
858
0
              for (y=0; y < (ssize_t) image->extract_info.height; y++)
859
0
              {
860
0
                stream=ReadBlobStream(image,length,pixels,&count);
861
0
                if (count != (ssize_t) length)
862
0
                  break;
863
0
              }
864
0
              if (count != (ssize_t) length)
865
0
                break;
866
0
            }
867
0
            stream=ReadBlobStream(image,length,pixels,&count);
868
0
            for (y=0; y < (ssize_t) image->extract_info.height; y++)
869
0
            {
870
0
              const Quantum
871
0
                *magick_restrict p;
872
873
0
              Quantum
874
0
                *magick_restrict q;
875
876
0
              ssize_t
877
0
                x;
878
879
0
              if (count != (ssize_t) length)
880
0
                {
881
0
                  status=MagickFalse;
882
0
                  ThrowFileException(exception,CorruptImageError,
883
0
                    "UnexpectedEndOfFile",image->filename);
884
0
                  break;
885
0
                }
886
0
              q=GetAuthenticPixels(canvas_image,0,0,canvas_image->columns,1,
887
0
                exception);
888
0
              if (q == (Quantum *) NULL)
889
0
                break;
890
0
              length=ImportQuantumPixels(canvas_image,(CacheView *) NULL,
891
0
                quantum_info,BlueQuantum,(unsigned char *) stream,exception);
892
0
              if (SyncAuthenticPixels(canvas_image,exception) == MagickFalse)
893
0
                break;
894
0
              if (((y-image->extract_info.y) >= 0) &&
895
0
                  ((y-image->extract_info.y) < (ssize_t) image->rows))
896
0
                {
897
0
                  p=GetVirtualPixels(canvas_image,canvas_image->extract_info.x,
898
0
                    0,canvas_image->columns,1,exception);
899
0
                  q=GetAuthenticPixels(image,0,y-image->extract_info.y,
900
0
                    image->columns,1,exception);
901
0
                  if ((p == (const Quantum *) NULL) || (q == (Quantum *) NULL))
902
0
                    break;
903
0
                  for (x=0; x < (ssize_t) image->columns; x++)
904
0
                  {
905
0
                    SetPixelAlpha(image,GetPixelAlpha(canvas_image,p),q);
906
0
                    p+=(ptrdiff_t) GetPixelChannels(canvas_image);
907
0
                    q+=(ptrdiff_t) GetPixelChannels(image);
908
0
                  }
909
0
                  if (SyncAuthenticPixels(image,exception) == MagickFalse)
910
0
                    break;
911
0
               }
912
0
              stream=ReadBlobStream(image,length,pixels,&count);
913
0
            }
914
0
            if (image->previous == (Image *) NULL)
915
0
              {
916
0
                status=SetImageProgress(image,LoadImageTag,4,5);
917
0
                if (status == MagickFalse)
918
0
                  break;
919
0
              }
920
0
          }
921
0
        if (image->previous == (Image *) NULL)
922
0
          {
923
0
            status=SetImageProgress(image,LoadImageTag,5,5);
924
0
            if (status == MagickFalse)
925
0
              break;
926
0
          }
927
0
        break;
928
0
      }
929
0
    }
930
0
    if (status == MagickFalse)
931
0
      break;
932
0
    SetQuantumImageType(image,quantum_type);
933
    /*
934
      Proceed to next image.
935
    */
936
0
    if (image_info->number_scenes != 0)
937
0
      if (image->scene >= (image_info->scene+image_info->number_scenes-1))
938
0
        break;
939
0
    if (count == (ssize_t) length)
940
0
      {
941
        /*
942
          Allocate next image structure.
943
        */
944
0
        AcquireNextImage(image_info,image,exception);
945
0
        if (GetNextImageInList(image) == (Image *) NULL)
946
0
          {
947
0
            status=MagickFalse;
948
0
            break;
949
0
          }
950
0
        image=SyncNextImageInList(image);
951
0
        status=SetImageProgress(image,LoadImagesTag,TellBlob(image),
952
0
          GetBlobSize(image));
953
0
        if (status == MagickFalse)
954
0
          break;
955
0
      }
956
0
    scene++;
957
0
  } while (count == (ssize_t) length);
958
0
  quantum_info=DestroyQuantumInfo(quantum_info);
959
0
  canvas_image=DestroyImage(canvas_image);
960
0
  if (CloseBlob(image) == MagickFalse)
961
0
    status=MagickFalse;
962
0
  if (status == MagickFalse)
963
0
    return(DestroyImageList(image));
964
0
  return(GetFirstImageInList(image));
965
0
}
966

967
/*
968
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
969
%                                                                             %
970
%                                                                             %
971
%                                                                             %
972
%   R e g i s t e r Y C b C r I m a g e                                       %
973
%                                                                             %
974
%                                                                             %
975
%                                                                             %
976
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
977
%
978
%  RegisterYCBCRImage() adds attributes for the YCbCr or YCbCrA image format to
979
%  the list of supported formats.  The attributes include the image format
980
%  tag, a method to read and/or write the format, whether the format
981
%  supports the saving of more than one frame to the same file or blob,
982
%  whether the format supports native in-memory I/O, and a brief
983
%  description of the format.
984
%
985
%  The format of the RegisterYCBCRImage method is:
986
%
987
%      size_t RegisterYCBCRImage(void)
988
%
989
*/
990
ModuleExport size_t RegisterYCBCRImage(void)
991
8
{
992
8
  MagickInfo
993
8
    *entry;
994
995
8
  entry=AcquireMagickInfo("YCBCR","YCBCR","Raw Y, Cb, and Cr samples");
996
8
  entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
997
8
  entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
998
8
  entry->flags|=CoderRawSupportFlag;
999
8
  entry->flags|=CoderEndianSupportFlag;
1000
8
  (void) RegisterMagickInfo(entry);
1001
8
  entry=AcquireMagickInfo("YCBCR","YCBCRA","Raw Y, Cb, Cr, and alpha samples");
1002
8
  entry->decoder=(DecodeImageHandler *) ReadYCBCRImage;
1003
8
  entry->encoder=(EncodeImageHandler *) WriteYCBCRImage;
1004
8
  entry->flags|=CoderRawSupportFlag;
1005
8
  entry->flags|=CoderEndianSupportFlag;
1006
8
  (void) RegisterMagickInfo(entry);
1007
8
  return(MagickImageCoderSignature);
1008
8
}
1009

1010
/*
1011
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1012
%                                                                             %
1013
%                                                                             %
1014
%                                                                             %
1015
%   U n r e g i s t e r Y C b C r I m a g e                                   %
1016
%                                                                             %
1017
%                                                                             %
1018
%                                                                             %
1019
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1020
%
1021
%  UnregisterYCBCRImage() removes format registrations made by the
1022
%  YCbCr module from the list of supported formats.
1023
%
1024
%  The format of the UnregisterYCBCRImage method is:
1025
%
1026
%      UnregisterYCBCRImage(void)
1027
%
1028
*/
1029
ModuleExport void UnregisterYCBCRImage(void)
1030
0
{
1031
0
  (void) UnregisterMagickInfo("YCbCr");
1032
0
  (void) UnregisterMagickInfo("YCbCrA");
1033
0
}
1034

1035
/*
1036
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037
%                                                                             %
1038
%                                                                             %
1039
%                                                                             %
1040
%   W r i t e Y C b C r I m a g e                                             %
1041
%                                                                             %
1042
%                                                                             %
1043
%                                                                             %
1044
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1045
%
1046
%  WriteYCBCRImage() writes an image to a file in the YCbCr or YCbCrA
1047
%  rasterfile format.
1048
%
1049
%  The format of the WriteYCBCRImage method is:
1050
%
1051
%      MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1052
%        Image *image,ExceptionInfo *exception)
1053
%
1054
%  A description of each parameter follows.
1055
%
1056
%    o image_info: the image info.
1057
%
1058
%    o image:  The image.
1059
%
1060
%    o exception: return any errors or warnings in this structure.
1061
%
1062
*/
1063
static MagickBooleanType WriteYCBCRImage(const ImageInfo *image_info,
1064
  Image *image,ExceptionInfo *exception)
1065
0
{
1066
0
  const Quantum
1067
0
    *p;
1068
1069
0
  MagickBooleanType
1070
0
    status = MagickTrue;
1071
1072
0
  MagickOffsetType
1073
0
    scene;
1074
1075
0
  QuantumInfo
1076
0
    *quantum_info;
1077
1078
0
  QuantumType
1079
0
    quantum_type;
1080
1081
0
  size_t
1082
0
    length,
1083
0
    number_scenes;
1084
1085
0
  ssize_t
1086
0
    count,
1087
0
    y;
1088
1089
0
  unsigned char
1090
0
    *pixels;
1091
1092
  /*
1093
    Allocate memory for pixels.
1094
  */
1095
0
  assert(image_info != (const ImageInfo *) NULL);
1096
0
  assert(image_info->signature == MagickCoreSignature);
1097
0
  assert(image != (Image *) NULL);
1098
0
  assert(image->signature == MagickCoreSignature);
1099
0
  if (IsEventLogging() != MagickFalse)
1100
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1101
0
  if (image_info->interlace != PartitionInterlace)
1102
0
    {
1103
      /*
1104
        Open output image file.
1105
      */
1106
0
      assert(exception != (ExceptionInfo *) NULL);
1107
0
      assert(exception->signature == MagickCoreSignature);
1108
0
      status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1109
0
      if (status == MagickFalse)
1110
0
        return(status);
1111
0
    }
1112
0
  quantum_type=RGBQuantum;
1113
0
  if (LocaleCompare(image_info->magick,"YCbCrA") == 0)
1114
0
    quantum_type=RGBAQuantum;
1115
0
  scene=0;
1116
0
  number_scenes=GetImageListLength(image);
1117
0
  do
1118
0
  {
1119
    /*
1120
      Convert MIFF to YCbCr raster pixels.
1121
    */
1122
0
    if (image->colorspace != YCbCrColorspace)
1123
0
      (void) TransformImageColorspace(image,YCbCrColorspace,exception);
1124
0
    if ((LocaleCompare(image_info->magick,"YCbCrA") == 0) &&
1125
0
        ((image->alpha_trait & BlendPixelTrait) == 0))
1126
0
      (void) SetImageAlphaChannel(image,OpaqueAlphaChannel,exception);
1127
0
    quantum_info=AcquireQuantumInfo(image_info,image);
1128
0
    if (quantum_info == (QuantumInfo *) NULL)
1129
0
      ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1130
0
    pixels=(unsigned char *) GetQuantumPixels(quantum_info);
1131
0
    switch (image_info->interlace)
1132
0
    {
1133
0
      case NoInterlace:
1134
0
      default:
1135
0
      {
1136
        /*
1137
          No interlacing:  YCbCrYCbCrYCbCrYCbCrYCbCrYCbCr...
1138
        */
1139
0
        for (y=0; y < (ssize_t) image->rows; y++)
1140
0
        {
1141
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1142
0
          if (p == (const Quantum *) NULL)
1143
0
            break;
1144
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1145
0
            quantum_type,pixels,exception);
1146
0
          count=WriteBlob(image,length,pixels);
1147
0
          if (count != (ssize_t) length)
1148
0
            break;
1149
0
          if (image->previous == (Image *) NULL)
1150
0
            {
1151
0
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1152
0
                image->rows);
1153
0
              if (status == MagickFalse)
1154
0
                break;
1155
0
            }
1156
0
        }
1157
0
        break;
1158
0
      }
1159
0
      case LineInterlace:
1160
0
      {
1161
        /*
1162
          Line interlacing:  YYY...CbCbCb...CrCrCr...YYY...CbCbCb...CrCrCr...
1163
        */
1164
0
        for (y=0; y < (ssize_t) image->rows; y++)
1165
0
        {
1166
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1167
0
          if (p == (const Quantum *) NULL)
1168
0
            break;
1169
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1170
0
            RedQuantum,pixels,exception);
1171
0
          count=WriteBlob(image,length,pixels);
1172
0
          if (count != (ssize_t) length)
1173
0
            break;
1174
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1175
0
            GreenQuantum,pixels,exception);
1176
0
          count=WriteBlob(image,length,pixels);
1177
0
          if (count != (ssize_t) length)
1178
0
            break;
1179
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1180
0
            BlueQuantum,pixels,exception);
1181
0
          count=WriteBlob(image,length,pixels);
1182
0
          if (count != (ssize_t) length)
1183
0
            break;
1184
0
          if (quantum_type == RGBAQuantum)
1185
0
            {
1186
0
              length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1187
0
                AlphaQuantum,pixels,exception);
1188
0
              count=WriteBlob(image,length,pixels);
1189
0
              if (count != (ssize_t) length)
1190
0
                break;
1191
0
            }
1192
0
          if (image->previous == (Image *) NULL)
1193
0
            {
1194
0
              status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
1195
0
                image->rows);
1196
0
              if (status == MagickFalse)
1197
0
                break;
1198
0
            }
1199
0
        }
1200
0
        break;
1201
0
      }
1202
0
      case PlaneInterlace:
1203
0
      {
1204
        /*
1205
          Plane interlacing:  YYYYYY...CbCbCbCbCbCb...CrCrCrCrCrCr...
1206
        */
1207
0
        for (y=0; y < (ssize_t) image->rows; y++)
1208
0
        {
1209
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1210
0
          if (p == (const Quantum *) NULL)
1211
0
            break;
1212
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1213
0
            RedQuantum,pixels,exception);
1214
0
          count=WriteBlob(image,length,pixels);
1215
0
          if (count != (ssize_t) length)
1216
0
            break;
1217
0
        }
1218
0
        if (image->previous == (Image *) NULL)
1219
0
          {
1220
0
            status=SetImageProgress(image,SaveImageTag,1,5);
1221
0
            if (status == MagickFalse)
1222
0
              break;
1223
0
          }
1224
0
        for (y=0; y < (ssize_t) image->rows; y++)
1225
0
        {
1226
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1227
0
          if (p == (const Quantum *) NULL)
1228
0
            break;
1229
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1230
0
            GreenQuantum,pixels,exception);
1231
0
          count=WriteBlob(image,length,pixels);
1232
0
          if (count != (ssize_t) length)
1233
0
            break;
1234
0
        }
1235
0
        if (image->previous == (Image *) NULL)
1236
0
          {
1237
0
            status=SetImageProgress(image,SaveImageTag,2,5);
1238
0
            if (status == MagickFalse)
1239
0
              break;
1240
0
          }
1241
0
        for (y=0; y < (ssize_t) image->rows; y++)
1242
0
        {
1243
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1244
0
          if (p == (const Quantum *) NULL)
1245
0
            break;
1246
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1247
0
            BlueQuantum,pixels,exception);
1248
0
          count=WriteBlob(image,length,pixels);
1249
0
          if (count != (ssize_t) length)
1250
0
            break;
1251
0
        }
1252
0
        if (image->previous == (Image *) NULL)
1253
0
          {
1254
0
            status=SetImageProgress(image,SaveImageTag,3,5);
1255
0
            if (status == MagickFalse)
1256
0
              break;
1257
0
          }
1258
0
        if (quantum_type == RGBAQuantum)
1259
0
          {
1260
0
            for (y=0; y < (ssize_t) image->rows; y++)
1261
0
            {
1262
0
              p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1263
0
              if (p == (const Quantum *) NULL)
1264
0
                break;
1265
0
              length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1266
0
                AlphaQuantum,pixels,exception);
1267
0
              count=WriteBlob(image,length,pixels);
1268
0
              if (count != (ssize_t) length)
1269
0
              break;
1270
0
            }
1271
0
          }
1272
0
        if (image_info->interlace == PartitionInterlace)
1273
0
          (void) CopyMagickString(image->filename,image_info->filename,
1274
0
            MagickPathExtent);
1275
0
        if (image->previous == (Image *) NULL)
1276
0
          {
1277
0
            status=SetImageProgress(image,SaveImageTag,5,5);
1278
0
            if (status == MagickFalse)
1279
0
              break;
1280
0
          }
1281
0
        break;
1282
0
      }
1283
0
      case PartitionInterlace:
1284
0
      {
1285
        /*
1286
          Partition interlacing:  YYYYYY..., CbCbCbCbCbCb..., CrCrCrCrCrCr...
1287
        */
1288
0
        AppendImageFormat("Y",image->filename);
1289
0
        status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1290
0
          AppendBinaryBlobMode,exception);
1291
0
        if (status == MagickFalse)
1292
0
          return(status);
1293
0
        for (y=0; y < (ssize_t) image->rows; y++)
1294
0
        {
1295
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1296
0
          if (p == (const Quantum *) NULL)
1297
0
            break;
1298
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1299
0
            RedQuantum,pixels,exception);
1300
0
          count=WriteBlob(image,length,pixels);
1301
0
          if (count != (ssize_t) length)
1302
0
            break;
1303
0
        }
1304
0
        if (image->previous == (Image *) NULL)
1305
0
          {
1306
0
            status=SetImageProgress(image,SaveImageTag,1,5);
1307
0
            if (status == MagickFalse)
1308
0
              break;
1309
0
          }
1310
0
        if (CloseBlob(image) == MagickFalse)
1311
0
          break;
1312
0
        AppendImageFormat("Cb",image->filename);
1313
0
        status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1314
0
          AppendBinaryBlobMode,exception);
1315
0
        if (status == MagickFalse)
1316
0
          return(status);
1317
0
        for (y=0; y < (ssize_t) image->rows; y++)
1318
0
        {
1319
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1320
0
          if (p == (const Quantum *) NULL)
1321
0
            break;
1322
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1323
0
            GreenQuantum,pixels,exception);
1324
0
          count=WriteBlob(image,length,pixels);
1325
0
          if (count != (ssize_t) length)
1326
0
            break;
1327
0
        }
1328
0
        if (image->previous == (Image *) NULL)
1329
0
          {
1330
0
            status=SetImageProgress(image,SaveImageTag,2,5);
1331
0
            if (status == MagickFalse)
1332
0
              break;
1333
0
          }
1334
0
        if (CloseBlob(image) == MagickFalse)
1335
0
          break;
1336
0
        AppendImageFormat("Cr",image->filename);
1337
0
        status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1338
0
          AppendBinaryBlobMode,exception);
1339
0
        if (status == MagickFalse)
1340
0
          return(status);
1341
0
        for (y=0; y < (ssize_t) image->rows; y++)
1342
0
        {
1343
0
          p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1344
0
          if (p == (const Quantum *) NULL)
1345
0
            break;
1346
0
          length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1347
0
            BlueQuantum,pixels,exception);
1348
0
          count=WriteBlob(image,length,pixels);
1349
0
          if (count != (ssize_t) length)
1350
0
            break;
1351
0
        }
1352
0
        if (image->previous == (Image *) NULL)
1353
0
          {
1354
0
            status=SetImageProgress(image,SaveImageTag,3,5);
1355
0
            if (status == MagickFalse)
1356
0
              break;
1357
0
          }
1358
0
        if (quantum_type == RGBAQuantum)
1359
0
          {
1360
0
            if (CloseBlob(image) == MagickFalse)
1361
0
              break;
1362
0
            AppendImageFormat("A",image->filename);
1363
0
            status=OpenBlob(image_info,image,scene == 0 ? WriteBinaryBlobMode :
1364
0
              AppendBinaryBlobMode,exception);
1365
0
            if (status == MagickFalse)
1366
0
              return(status);
1367
0
            for (y=0; y < (ssize_t) image->rows; y++)
1368
0
            {
1369
0
              p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1370
0
              if (p == (const Quantum *) NULL)
1371
0
                break;
1372
0
              length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
1373
0
                AlphaQuantum,pixels,exception);
1374
0
              count=WriteBlob(image,length,pixels);
1375
0
              if (count != (ssize_t) length)
1376
0
                break;
1377
0
            }
1378
0
            if (image->previous == (Image *) NULL)
1379
0
              {
1380
0
                status=SetImageProgress(image,SaveImageTag,4,5);
1381
0
                if (status == MagickFalse)
1382
0
                  break;
1383
0
              }
1384
0
          }
1385
0
        (void) CloseBlob(image);
1386
0
        (void) CopyMagickString(image->filename,image_info->filename,
1387
0
          MagickPathExtent);
1388
0
        if (image->previous == (Image *) NULL)
1389
0
          {
1390
0
            status=SetImageProgress(image,SaveImageTag,5,5);
1391
0
            if (status == MagickFalse)
1392
0
              break;
1393
0
          }
1394
0
        break;
1395
0
      }
1396
0
    }
1397
0
    quantum_info=DestroyQuantumInfo(quantum_info);
1398
0
    if (GetNextImageInList(image) == (Image *) NULL)
1399
0
      break;
1400
0
    image=SyncNextImageInList(image);
1401
0
    status=SetImageProgress(image,SaveImagesTag,scene++,number_scenes);
1402
0
    if (status == MagickFalse)
1403
0
      break;
1404
0
  } while (image_info->adjoin != MagickFalse);
1405
0
  if (CloseBlob(image) == MagickFalse)
1406
0
    status=MagickFalse;
1407
0
  return(status);
1408
0
}