Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/uyvy.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
% SPDX-License-Identifier: MIT
6
%
7
% This program is covered by multiple licenses, which are described in
8
% Copyright.txt. You should have received a copy of Copyright.txt with this
9
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
10
%
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
%                                                                             %
13
%                                                                             %
14
%                                                                             %
15
%                        U   U  Y   Y  V   V  Y   Y                           %
16
%                        U   U   Y Y   V   V   Y Y                            %
17
%                        U   U    Y    V   V    Y                             %
18
%                        U   U    Y     V V     Y                             %
19
%                         UUU     Y      V      Y                             %
20
%                                                                             %
21
%                                                                             %
22
%           Read/Write 16bit/pixel Interleaved YUV Image Format.              %
23
%                                                                             %
24
%                                                                             %
25
%                              Software Design                                %
26
%                                John Cristy                                  %
27
%                                 July 1992                                   %
28
%                                                                             %
29
%                                                                             %
30
%                                                                             %
31
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32
%
33
%
34
*/
35

36
/*
37
  Include declarations.
38
*/
39
#include "magick/studio.h"
40
#include "magick/blob.h"
41
#include "magick/pixel_cache.h"
42
#include "magick/magick.h"
43
#include "magick/monitor.h"
44
#include "magick/utility.h"
45
#include "magick/static.h"
46

47
/*
48
  Forward declarations.
49
*/
50
static unsigned int
51
  WriteUYVYImage(const ImageInfo *,Image *);
52

53
/*
54
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55
%                                                                             %
56
%                                                                             %
57
%                                                                             %
58
%   R e a d U Y V Y I m a g e                                                 %
59
%                                                                             %
60
%                                                                             %
61
%                                                                             %
62
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
63
%
64
%  Method ReadUYVYImage reads an image in the UYVY format and returns it.  It
65
%  allocates the memory necessary for the new Image structure and returns a
66
%  pointer to the new image.
67
%
68
%  The format of the ReadUYVYImage method is:
69
%
70
%      Image *ReadUYVYImage(const ImageInfo *image_info,
71
%        ExceptionInfo *exception)
72
%
73
%  A description of each parameter follows:
74
%
75
%    o image:  Method ReadUYVYImage returns a pointer to the image after
76
%      reading.  A null image is returned if there is a memory shortage or
77
%      if the image cannot be read.
78
%
79
%    o image_info: Specifies a pointer to a ImageInfo structure.
80
%
81
%    o exception: return any errors or warnings in this structure.
82
%
83
%
84
*/
85
static Image *ReadUYVYImage(const ImageInfo *image_info,
86
  ExceptionInfo *exception)
87
49
{
88
49
  Image
89
49
    *image;
90
91
49
  long
92
49
    y;
93
94
49
  register long
95
49
    x;
96
97
49
  register PixelPacket
98
49
    *q;
99
100
49
  register long
101
49
    i;
102
103
49
  unsigned char
104
49
    u,
105
49
    v,
106
49
    y1,
107
49
    y2;
108
109
49
  unsigned int
110
49
    status;
111
112
  /*
113
    Open image file.
114
  */
115
49
  assert(image_info != (const ImageInfo *) NULL);
116
49
  assert(image_info->signature == MagickSignature);
117
49
  assert(exception != (ExceptionInfo *) NULL);
118
49
  assert(exception->signature == MagickSignature);
119
49
  image=AllocateImage(image_info);
120
49
  if ((image->columns == 0) || (image->rows == 0))
121
49
    ThrowReaderException(OptionError,MustSpecifyImageSize,image);
122
0
  (void) strlcpy(image->filename,image_info->filename,MaxTextExtent);
123
0
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
124
0
  if (status == False)
125
0
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
126
  /*
127
    When subsampling, image width must be evenly divisible by two.
128
  */
129
0
  if (image->columns %2)
130
0
    ThrowReaderException(CorruptImageError,SubsamplingRequiresEvenWidth,image);
131
0
  for (i=0; i < image->offset; i++)
132
0
    {
133
0
      if (EOF == ReadBlobByte(image))
134
0
        ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
135
0
                       image->filename);
136
0
    }
137
0
  image->depth=8;
138
0
  if (image_info->ping)
139
0
    {
140
0
      CloseBlob(image);
141
0
      StopTimer(&image->timer);
142
0
      return(image);
143
0
    }
144
  /*
145
    Accumulate UYVY, then unpack into two pixels.
146
  */
147
0
  for (y=0; y < (long) image->rows; y++)
148
0
  {
149
0
    q=SetImagePixels(image,0,y,image->columns,1);
150
0
    if (q == (PixelPacket *) NULL)
151
0
      break;
152
0
    for (x=0; x < (long) (image->columns >> 1); x++)
153
0
    {
154
0
      u=ReadBlobByte(image);
155
0
      y1=ReadBlobByte(image);
156
0
      v=ReadBlobByte(image);
157
0
      y2=ReadBlobByte(image);
158
0
      q->red=ScaleCharToQuantum(y1);
159
0
      q->green=ScaleCharToQuantum(u);
160
0
      q->blue=ScaleCharToQuantum(v);
161
0
      q++;
162
0
      q->red=ScaleCharToQuantum(y2);
163
0
      q->green=ScaleCharToQuantum(u);
164
0
      q->blue=ScaleCharToQuantum(v);
165
0
      q++;
166
0
    }
167
0
    if (!SyncImagePixels(image))
168
0
      break;
169
0
    if (QuantumTick(y,image->rows))
170
0
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
171
0
                                  image->filename,
172
0
                                  image->columns,image->rows))
173
0
        break;
174
0
  }
175
0
  image->colorspace=YCbCrColorspace;
176
0
  if (TransformColorspace(image,RGBColorspace) == MagickFail)
177
0
    ThrowException(exception,CoderError,UnableToTransformColorspace,
178
0
                   image->filename);
179
0
  if (EOFBlob(image))
180
0
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
181
0
      image->filename);
182
0
  CloseBlob(image);
183
0
  StopTimer(&image->timer);
184
0
  return(image);
185
0
}
186

187
/*
188
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
189
%                                                                             %
190
%                                                                             %
191
%                                                                             %
192
%   R e g i s t e r U Y V Y I m a g e                                         %
193
%                                                                             %
194
%                                                                             %
195
%                                                                             %
196
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
197
%
198
%  Method RegisterUYVYImage adds attributes for the UYVY image format to
199
%  the list of supported formats.  The attributes include the image format
200
%  tag, a method to read and/or write the format, whether the format
201
%  supports the saving of more than one frame to the same file or blob,
202
%  whether the format supports native in-memory I/O, and a brief
203
%  description of the format.
204
%
205
%  The format of the RegisterUYVYImage method is:
206
%
207
%      RegisterUYVYImage(void)
208
%
209
*/
210
ModuleExport void RegisterUYVYImage(void)
211
2
{
212
2
  MagickInfo
213
2
    *entry;
214
215
2
  entry=SetMagickInfo("PAL");
216
2
  entry->decoder=(DecoderHandler) ReadUYVYImage;
217
2
  entry->encoder=(EncoderHandler) WriteUYVYImage;
218
2
  entry->adjoin=False;
219
2
  entry->raw=True;
220
2
  entry->description="16bit/pixel interleaved YUV";
221
2
  entry->module="UYVY";
222
2
  (void) RegisterMagickInfo(entry);
223
224
2
  entry=SetMagickInfo("UYVY");
225
2
  entry->decoder=(DecoderHandler) ReadUYVYImage;
226
2
  entry->encoder=(EncoderHandler) WriteUYVYImage;
227
2
  entry->adjoin=False;
228
2
  entry->raw=True;
229
2
  entry->description="16bit/pixel interleaved YUV";
230
2
  entry->module="UYVY";
231
2
  (void) RegisterMagickInfo(entry);
232
2
}
233

234
/*
235
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236
%                                                                             %
237
%                                                                             %
238
%                                                                             %
239
%   U n r e g i s t e r U Y V Y I m a g e                                     %
240
%                                                                             %
241
%                                                                             %
242
%                                                                             %
243
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244
%
245
%  Method UnregisterUYVYImage removes format registrations made by the
246
%  UYVY module from the list of supported formats.
247
%
248
%  The format of the UnregisterUYVYImage method is:
249
%
250
%      UnregisterUYVYImage(void)
251
%
252
*/
253
ModuleExport void UnregisterUYVYImage(void)
254
0
{
255
0
  (void) UnregisterMagickInfo("PAL");
256
0
  (void) UnregisterMagickInfo("UYVY");
257
0
}
258

259
/*
260
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261
%                                                                             %
262
%                                                                             %
263
%                                                                             %
264
%   W r i t e U Y V Y I m a g e                                               %
265
%                                                                             %
266
%                                                                             %
267
%                                                                             %
268
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
269
%
270
%  Method WriteUYVYImage writes an image to a file in the digital UYVY
271
%  format.  This format, used by AccomWSD, is not dramatically higher quality
272
%  than the 12bit/pixel YUV format, but has better locality.
273
%
274
%  The format of the WriteUYVYImage method is:
275
%
276
%      unsigned int WriteUYVYImage(const ImageInfo *image_info,Image *image)
277
%
278
%  A description of each parameter follows.
279
%
280
%    o status: Method WriteUYVYImage return True if the image is written.
281
%      False is returned is there is a memory shortage or if the image file
282
%      fails to write.
283
%
284
%    o image_info: Specifies a pointer to a ImageInfo structure.
285
%
286
%    o image:  A pointer to an Image structure.
287
%      Implicit assumption: number of columns is even.
288
%
289
*/
290
static unsigned int WriteUYVYImage(const ImageInfo *image_info,Image *image)
291
0
{
292
0
  DoublePixelPacket
293
0
    pixel;
294
295
0
  long
296
0
    y;
297
298
0
  register const PixelPacket
299
0
    *p;
300
301
0
  register long
302
0
    x;
303
304
0
  unsigned int
305
0
    full,
306
0
    status;
307
308
0
  ColorspaceType
309
0
    original_colorspace;
310
311
  /*
312
    Open output image file.
313
  */
314
0
  assert(image_info != (const ImageInfo *) NULL);
315
0
  assert(image_info->signature == MagickSignature);
316
0
  assert(image != (Image *) NULL);
317
0
  assert(image->signature == MagickSignature);
318
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
319
0
  if (status == False)
320
0
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
321
322
  /*
323
    When subsampling, image width must be evenly divisible by two.
324
  */
325
0
  if (image->columns %2)
326
0
    ThrowWriterException(CoderError,SubsamplingRequiresEvenWidth,image);
327
328
  /*
329
    Convert to YUV, at full resolution.
330
  */
331
0
  original_colorspace=image->colorspace;
332
0
  if (TransformColorspace(image,YCbCrColorspace) == MagickFail)
333
0
    ThrowWriterException(CoderError,UnableToTransformColorspace,image);
334
  /*
335
    Accumulate two pixels, then output.
336
  */
337
0
  full=False;
338
0
  (void) memset(&pixel,0,sizeof(DoublePixelPacket));
339
0
  for (y=0; y < (long) image->rows; y++)
340
0
  {
341
0
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
342
0
    if (p == (const PixelPacket *) NULL)
343
0
      break;
344
0
    for (x=0; x < (long) image->columns; x++)
345
0
    {
346
0
      if (full)
347
0
        {
348
0
          pixel.green=(pixel.green+p->green)/2;
349
0
          pixel.blue=(pixel.blue+p->blue)/2;
350
0
          (void) WriteBlobByte(image,ScaleQuantumToChar(pixel.green));
351
0
          (void) WriteBlobByte(image,ScaleQuantumToChar(pixel.red));
352
0
          (void) WriteBlobByte(image,ScaleQuantumToChar(pixel.blue));
353
0
          (void) WriteBlobByte(image,ScaleQuantumToChar(p->red));
354
0
        }
355
0
      pixel.red=p->red;
356
0
      pixel.green=p->green;
357
0
      pixel.blue=p->blue;
358
0
      full=!full;
359
0
      p++;
360
0
    }
361
0
    if (QuantumTick(y,image->rows))
362
0
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
363
0
                                  SaveImageText,image->filename,
364
0
                                  image->columns,image->rows))
365
0
        break;
366
0
  }
367
  /*
368
    Restore colorspace
369
  */
370
0
  if (TransformColorspace(image,original_colorspace) == MagickFail)
371
0
    ThrowWriterException(CoderError,UnableToTransformColorspace,image);
372
0
  status &= CloseBlob(image);
373
0
  return(status);
374
0
}