Coverage Report

Created: 2025-10-12 07:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/rgf.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%                                                                             %
6
%                            RRRR    GGG   FFFFF                              %
7
%                            R   R  G      F                                  %
8
%                            RRRR   G  GG  FFF                                %
9
%                            R  R   G   G  F                                  %
10
%                            R   R   GGG   F                                  %
11
%                                                                             %
12
%                                                                             %
13
%                  Read/Write LEGO Mindstorms EV3 Robot Graphics File         %
14
%                                                                             %
15
%                              Software Design                                %
16
%                               Brian Wheeler                                 %
17
%                               August 2013                                   %
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/attribute.h"
44
#include "MagickCore/blob.h"
45
#include "MagickCore/blob-private.h"
46
#include "MagickCore/cache.h"
47
#include "MagickCore/color-private.h"
48
#include "MagickCore/colormap.h"
49
#include "MagickCore/colorspace.h"
50
#include "MagickCore/colorspace-private.h"
51
#include "MagickCore/exception.h"
52
#include "MagickCore/exception-private.h"
53
#include "MagickCore/image.h"
54
#include "MagickCore/image-private.h"
55
#include "MagickCore/list.h"
56
#include "MagickCore/magick.h"
57
#include "MagickCore/memory_.h"
58
#include "MagickCore/monitor.h"
59
#include "MagickCore/monitor-private.h"
60
#include "MagickCore/pixel-accessor.h"
61
#include "MagickCore/quantum-private.h"
62
#include "MagickCore/static.h"
63
#include "MagickCore/string_.h"
64
#include "MagickCore/module.h"
65
#include "MagickCore/utility.h"
66

67
/*
68
  Forward declarations.
69
*/
70
static MagickBooleanType
71
  WriteRGFImage(const ImageInfo *,Image *,ExceptionInfo *);
72

73
/*
74
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
75
%                                                                             %
76
%                                                                             %
77
%                                                                             %
78
%   R e a d X B M I m a g e                                                   %
79
%                                                                             %
80
%                                                                             %
81
%                                                                             %
82
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
83
%
84
%  ReadRGFImage() reads an RGF bitmap image file and returns it.  It
85
%  allocates the memory necessary for the new Image structure and returns a
86
%  pointer to the new image.
87
%
88
%  The format of the ReadRGFImage method is:
89
%
90
%      Image *ReadRGFImage(const ImageInfo *image_info,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 *ReadRGFImage(const ImageInfo *image_info,ExceptionInfo *exception)
100
693
{
101
693
  Image
102
693
    *image;
103
104
693
  int
105
693
    bit;
106
107
693
  MagickBooleanType
108
693
    status;
109
110
693
  ssize_t
111
693
    i,
112
693
    x;
113
114
693
  Quantum
115
693
    *q;
116
117
693
  unsigned char
118
693
    *p;
119
120
693
  ssize_t
121
693
    y;
122
123
693
  unsigned char
124
693
    byte,
125
693
    *data;
126
127
  /*
128
    Open image file.
129
  */
130
693
  assert(image_info != (const ImageInfo *) NULL);
131
693
  assert(image_info->signature == MagickCoreSignature);
132
693
  assert(exception != (ExceptionInfo *) NULL);
133
693
  assert(exception->signature == MagickCoreSignature);
134
693
  if (IsEventLogging() != MagickFalse)
135
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
136
0
      image_info->filename);
137
693
  image=AcquireImage(image_info,exception);
138
693
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
139
693
  if (status == MagickFalse)
140
326
    {
141
326
      image=DestroyImageList(image);
142
326
      return((Image *) NULL);
143
326
    }
144
  /*
145
    Read RGF header.
146
  */
147
367
  image->columns = (unsigned long) ReadBlobByte(image);
148
367
  image->rows = (unsigned long) ReadBlobByte(image);
149
367
  image->depth=8;
150
367
  image->storage_class=PseudoClass;
151
367
  image->colors=2;
152
  /*
153
    Initialize image structure.
154
  */
155
367
  if (AcquireImageColormap(image,image->colors,exception) == MagickFalse)
156
367
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
157
  /*
158
    Initialize colormap.
159
  */
160
367
  image->colormap[0].red=QuantumRange;
161
367
  image->colormap[0].green=QuantumRange;
162
367
  image->colormap[0].blue=QuantumRange;
163
367
  image->colormap[1].red=(Quantum) 0;
164
367
  image->colormap[1].green=(Quantum) 0;
165
367
  image->colormap[1].blue=(Quantum) 0;
166
367
  if (image_info->ping != MagickFalse)
167
0
    {
168
0
      (void) CloseBlob(image);
169
0
      return(GetFirstImageInList(image));
170
0
    }
171
367
  status=SetImageExtent(image,image->columns,image->rows,exception);
172
367
  if (status == MagickFalse)
173
210
    return(DestroyImageList(image));
174
  /*
175
    Read hex image data.
176
  */
177
157
  data=(unsigned char *) AcquireQuantumMemory(image->rows,image->columns*
178
157
    sizeof(*data));
179
157
  if (data == (unsigned char *) NULL)
180
157
    ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
181
157
  p=data;
182
2.85M
  for (i=0; i < (ssize_t) (image->columns * image->rows); i++) 
183
2.85M
    {
184
2.85M
      *p++=(char) ReadBlobByte(image);
185
2.85M
    }
186
187
  /*
188
    Convert RGF image to pixel packets.
189
  */
190
157
  p=data;
191
17.7k
  for (y=0; y < (ssize_t) image->rows; y++)
192
17.6k
  {
193
17.6k
    q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
194
17.6k
    if (q == (Quantum *) NULL)
195
0
      break;
196
17.6k
    bit=0;
197
17.6k
    byte=0;
198
2.87M
    for (x=0; x < (ssize_t) image->columns; x++)
199
2.85M
    {
200
2.85M
      if (bit == 0)
201
363k
        byte=(size_t) (*p++);
202
2.85M
      SetPixelIndex(image,(Quantum) ((byte & 0x01) != 0 ? 0x01 : 0x00),q);
203
2.85M
      bit++;
204
2.85M
      byte>>=1;
205
2.85M
      if (bit == 8)
206
348k
        bit=0;
207
2.85M
      q+=(ptrdiff_t) GetPixelChannels(image);
208
2.85M
    }
209
17.6k
    if (SyncAuthenticPixels(image,exception) == MagickFalse)
210
0
      break;
211
17.6k
    status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
212
17.6k
      image->rows);
213
17.6k
    if (status == MagickFalse)
214
0
      break;
215
17.6k
  }
216
157
  data=(unsigned char *) RelinquishMagickMemory(data);
217
157
  (void) SyncImage(image,exception);
218
157
  if (CloseBlob(image) == MagickFalse)
219
0
    status=MagickFalse;
220
157
  if (status == MagickFalse)
221
0
    return(DestroyImageList(image));
222
157
  return(GetFirstImageInList(image));
223
157
}
224

225
/*
226
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
227
%                                                                             %
228
%                                                                             %
229
%                                                                             %
230
%   R e g i s t e r R G F I m a g e                                           %
231
%                                                                             %
232
%                                                                             %
233
%                                                                             %
234
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235
%
236
%  RegisterRGFImage() adds attributes for the RGF image format to
237
%  the list of supported formats.  The attributes include the image format
238
%  tag, a method to read and/or write the format, whether the format
239
%  supports the saving of more than one frame to the same file or blob,
240
%  whether the format supports native in-memory I/O, and a brief
241
%  description of the format.
242
%
243
%  The format of the RegisterRGFImage method is:
244
%
245
%      size_t RegisterRGFImage(void)
246
%
247
*/
248
ModuleExport size_t RegisterRGFImage(void)
249
9
{
250
9
  MagickInfo
251
9
    *entry;
252
253
9
  entry=AcquireMagickInfo("RGF","RGF",
254
9
    "LEGO Mindstorms EV3 Robot Graphic Format (black and white)");
255
9
  entry->decoder=(DecodeImageHandler *) ReadRGFImage;
256
9
  entry->encoder=(EncodeImageHandler *) WriteRGFImage;
257
9
  entry->flags^=CoderAdjoinFlag;
258
9
  (void) RegisterMagickInfo(entry);
259
9
  return(MagickImageCoderSignature);
260
9
}
261

262
/*
263
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
264
%                                                                             %
265
%                                                                             %
266
%                                                                             %
267
%   U n r e g i s t e r R G F I m a g e                                       %
268
%                                                                             %
269
%                                                                             %
270
%                                                                             %
271
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
%
273
%  UnregisterRGFImage() removes format registrations made by the
274
%  RGF module from the list of supported formats.
275
%
276
%  The format of the UnregisterRGFImage method is:
277
%
278
%      UnregisterRGFImage(void)
279
%
280
*/
281
ModuleExport void UnregisterRGFImage(void)
282
0
{
283
0
  (void) UnregisterMagickInfo("RGF");
284
0
}
285

286
/*
287
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288
%                                                                             %
289
%                                                                             %
290
%                                                                             %
291
%   W r i t e R G F I m a g e                                                 %
292
%                                                                             %
293
%                                                                             %
294
%                                                                             %
295
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
296
%
297
%  WriteRGFImage() writes an image to a file in the X bitmap format.
298
%
299
%  The format of the WriteRGFImage method is:
300
%
301
%      MagickBooleanType WriteRGFImage(const ImageInfo *image_info,
302
%        Image *image,ExceptionInfo *exception)
303
%
304
%  A description of each parameter follows.
305
%
306
%    o image_info: the image info.
307
%
308
%    o image:  The image.
309
%
310
%    o exception: return any errors or warnings in this structure.
311
%
312
*/
313
static MagickBooleanType WriteRGFImage(const ImageInfo *image_info,Image *image,
314
  ExceptionInfo *exception)
315
157
{
316
157
  MagickBooleanType
317
157
    status;
318
319
157
  const Quantum
320
157
    *p;
321
322
157
  ssize_t
323
157
    x;
324
325
157
  size_t
326
157
    bit,
327
157
    byte;
328
329
157
  ssize_t
330
157
    y;
331
332
  /*
333
    Open output image file.
334
  */
335
157
  assert(image_info != (const ImageInfo *) NULL);
336
157
  assert(image_info->signature == MagickCoreSignature);
337
157
  assert(image != (Image *) NULL);
338
157
  assert(image->signature == MagickCoreSignature);
339
157
  assert(exception != (ExceptionInfo *) NULL);
340
157
  assert(exception->signature == MagickCoreSignature);
341
157
  if (IsEventLogging() != MagickFalse)
342
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
343
157
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
344
157
  if (status == MagickFalse)
345
0
  return(status);
346
157
  if (IssRGBCompatibleColorspace(image->colorspace) == MagickFalse)
347
0
    (void) TransformImageColorspace(image,sRGBColorspace,exception);
348
157
  if ((image->columns > 255L) || (image->rows > 255L))
349
157
    ThrowWriterException(ImageError,"Dimensions must be less than 255x255");
350
  /*
351
    Write header (just the image dimensions)
352
   */
353
157
  (void) WriteBlobByte(image,image->columns & 0xff);
354
157
  (void) WriteBlobByte(image,image->rows & 0xff);
355
  /*
356
    Convert MIFF to bit pixels.
357
  */
358
157
  if (IsImageMonochrome(image) == MagickFalse)
359
157
    (void) SetImageType(image,BilevelType,exception);
360
157
  x=0;
361
157
  y=0;
362
17.7k
  for (y=0; y < (ssize_t) image->rows; y++)
363
17.6k
  {
364
17.6k
    p=GetVirtualPixels(image,0,y,image->columns,1,exception);
365
17.6k
    if (p == (const Quantum *) NULL)
366
0
      break;
367
17.6k
    bit=0;
368
17.6k
    byte=0;
369
2.87M
    for (x=0; x < (ssize_t) image->columns; x++)
370
2.85M
    {
371
2.85M
      byte>>=1;
372
2.85M
      if (GetPixelLuma(image,p) < ((double) QuantumRange/2.0))
373
2.75M
        byte|=0x80;
374
2.85M
      bit++;
375
2.85M
      if (bit == 8)
376
348k
        {
377
          /*
378
            Write a bitmap byte to the image file.
379
          */
380
348k
          (void) WriteBlobByte(image,(unsigned char) byte);
381
348k
          bit=0;
382
348k
          byte=0;
383
348k
        }
384
2.85M
      p+=(ptrdiff_t) GetPixelChannels(image);
385
2.85M
    }
386
17.6k
    if (bit != 0)
387
15.2k
    {
388
15.2k
      byte >>= 8 - bit;
389
15.2k
      (void) WriteBlobByte(image,(unsigned char) byte);
390
15.2k
    }
391
17.6k
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
392
17.6k
      image->rows);
393
17.6k
    if (status == MagickFalse)
394
0
      break;
395
17.6k
  }
396
157
  if (CloseBlob(image) == MagickFalse)
397
0
    status=MagickFalse;
398
157
  return(status);
399
157
}