Coverage Report

Created: 2026-04-01 07:49

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