Coverage Report

Created: 2025-11-16 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/otb.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2020 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
%
5
% This program is covered by multiple licenses, which are described in
6
% Copyright.txt. You should have received a copy of Copyright.txt with this
7
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
8
%
9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
10
%                                                                             %
11
%                                                                             %
12
%                                                                             %
13
%                              OOO   TTTTT  BBBB                              %
14
%                             O   O    T    B   B                             %
15
%                             O   O    T    BBBB                              %
16
%                             O   O    T    B   B                             %
17
%                              OOO     T    BBBB                              %
18
%                                                                             %
19
%                                                                             %
20
%                     Read/Write On-The-Air Image Format.                     %
21
%                                                                             %
22
%                                                                             %
23
%                              Software Design                                %
24
%                                John Cristy                                  %
25
%                               January 2000                                  %
26
%                                                                             %
27
%                                                                             %
28
%                                                                             %
29
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
30
%
31
%
32
*/
33
/*
34
  Include declarations.
35
*/
36
#include "magick/studio.h"
37
#include "magick/blob.h"
38
#include "magick/colormap.h"
39
#include "magick/magick.h"
40
#include "magick/monitor.h"
41
#include "magick/pixel_cache.h"
42
#include "magick/utility.h"
43

44
/*
45
  Forward declarations.
46
*/
47
static unsigned int
48
  WriteOTBImage(const ImageInfo *,Image *);
49

50
/*
51
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
52
%                                                                             %
53
%                                                                             %
54
%                                                                             %
55
%   R e a d O T B I m a g e                                                   %
56
%                                                                             %
57
%                                                                             %
58
%                                                                             %
59
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60
%
61
%  Method ReadOTBImage reads a on-the-air (level 0) bitmap and returns it.  It
62
%  allocates the memory necessary for the new Image structure and returns a
63
%  pointer to the new image.
64
%
65
%  The format of the ReadOTBImage method is:
66
%
67
%      Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception)
68
%
69
%  A description of each parameter follows:
70
%
71
%    o image:  Method ReadOTBImage returns a pointer to the image after
72
%      reading.  A null image is returned if there is a memory shortage or
73
%      if the image cannot be read.
74
%
75
%    o image_info: Specifies a pointer to a ImageInfo structure.
76
%
77
%    o exception: return any errors or warnings in this structure.
78
%
79
%
80
*/
81
static Image *ReadOTBImage(const ImageInfo *image_info,ExceptionInfo *exception)
82
446
{
83
446
#define GetBit(a,i) (((a) >> (i)) & 1L)
84
85
446
  Image
86
446
    *image;
87
88
446
  int
89
446
    byte;
90
91
446
  long
92
446
    y;
93
94
446
  register IndexPacket
95
446
    *indexes;
96
97
446
  register long
98
446
    x;
99
100
446
  register PixelPacket
101
446
    *q;
102
103
446
  unsigned char
104
446
    bit,
105
446
    info,
106
446
    depth;
107
108
446
  unsigned int
109
446
    status;
110
111
  /*
112
    Open image file.
113
  */
114
446
  assert(image_info != (const ImageInfo *) NULL);
115
446
  assert(image_info->signature == MagickSignature);
116
446
  assert(exception != (ExceptionInfo *) NULL);
117
446
  assert(exception->signature == MagickSignature);
118
446
  image=AllocateImage(image_info);
119
446
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
120
446
  if (status == False)
121
446
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
122
  /*
123
    Initialize image structure.
124
  */
125
446
  info=ReadBlobByte(image);
126
446
  if (GetBit(info,4) == 0)
127
217
    {
128
217
      image->columns=ReadBlobByte(image);
129
217
      image->rows=ReadBlobByte(image);
130
217
    }
131
229
  else
132
229
    {
133
229
      image->columns=ReadBlobMSBShort(image);
134
229
      image->rows=ReadBlobMSBShort(image);
135
229
    }
136
446
  if ((image->columns == 0) || (image->rows == 0))
137
433
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
138
433
  depth=ReadBlobByte(image);
139
433
  if (depth != 1)
140
389
    ThrowReaderException(CoderError,OnlyLevelZerofilesSupported,image);
141
389
  if (!AllocateImageColormap(image,2))
142
389
    ThrowReaderException(ResourceLimitError,MemoryAllocationFailed,image);
143
389
  if (image_info->ping)
144
0
    {
145
0
      CloseBlob(image);
146
0
      StopTimer(&image->timer);
147
0
      return(image);
148
0
    }
149
150
389
  if (CheckImagePixelLimits(image, exception) != MagickPass)
151
363
    ThrowReaderException(ResourceLimitError,ImagePixelLimitExceeded,image);
152
153
  /*
154
    Convert bi-level image to pixel packets.
155
  */
156
122k
  for (y=0; y < (long) image->rows; y++)
157
122k
  {
158
122k
    q=SetImagePixelsEx(image,0,y,image->columns,1,exception);
159
122k
    if (q == (PixelPacket *) NULL)
160
0
      break;
161
122k
    indexes=AccessMutableIndexes(image);
162
122k
    bit=0;
163
122k
    byte=0;
164
72.0M
    for (x=0; x < (long) image->columns; x++)
165
71.9M
    {
166
71.9M
      if (bit == 0)
167
9.03M
        {
168
9.03M
          byte=ReadBlobByte(image);
169
9.03M
          if (byte == EOF)
170
9.03M
            ThrowReaderException(CorruptImageError,CorruptImage,image);
171
9.03M
        }
172
71.9M
      indexes[x]=(byte & (0x01 << (7-bit))) ? 0x01 : 0x00;
173
71.9M
      bit++;
174
71.9M
      if (bit == 8)
175
8.95M
        bit=0;
176
71.9M
    }
177
122k
    if (!SyncImagePixelsEx(image,exception))
178
0
      break;
179
122k
    if (QuantumTick(y,image->rows))
180
18.4k
      if (!MagickMonitorFormatted(y,image->rows,exception,LoadImageText,
181
18.4k
                                  image->filename,
182
18.4k
                                  image->columns,image->rows))
183
0
        break;
184
122k
  }
185
204
  (void) SyncImage(image);
186
204
  if (EOFBlob(image))
187
0
    ThrowException(exception,CorruptImageError,UnexpectedEndOfFile,
188
204
      image->filename);
189
204
  CloseBlob(image);
190
204
  StopTimer(&image->timer);
191
204
  return(image);
192
363
}
193

194
/*
195
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196
%                                                                             %
197
%                                                                             %
198
%                                                                             %
199
%   R e g i s t e r O T B I m a g e                                           %
200
%                                                                             %
201
%                                                                             %
202
%                                                                             %
203
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204
%
205
%  Method RegisterOTBImage adds attributes for the OTB image format to
206
%  the list of supported formats.  The attributes include the image format
207
%  tag, a method to read and/or write the format, whether the format
208
%  supports the saving of more than one frame to the same file or blob,
209
%  whether the format supports native in-memory I/O, and a brief
210
%  description of the format.
211
%
212
%  The format of the RegisterOTBImage method is:
213
%
214
%      RegisterOTBImage(void)
215
%
216
*/
217
ModuleExport void RegisterOTBImage(void)
218
1
{
219
1
  MagickInfo
220
1
    *entry;
221
222
1
  entry=SetMagickInfo("OTB");
223
1
  entry->decoder=(DecoderHandler) ReadOTBImage;
224
1
  entry->encoder=(EncoderHandler) WriteOTBImage;
225
1
  entry->adjoin=False;
226
1
  entry->description="On-the-air bitmap";
227
1
  entry->module="OTB";
228
1
  (void) RegisterMagickInfo(entry);
229
1
}
230

231
/*
232
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233
%                                                                             %
234
%                                                                             %
235
%                                                                             %
236
%   U n r e g i s t e r O T B I m a g e                                       %
237
%                                                                             %
238
%                                                                             %
239
%                                                                             %
240
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241
%
242
%  Method UnregisterOTBImage removes format registrations made by the
243
%  OTB module from the list of supported formats.
244
%
245
%  The format of the UnregisterOTBImage method is:
246
%
247
%      UnregisterOTBImage(void)
248
%
249
*/
250
ModuleExport void UnregisterOTBImage(void)
251
0
{
252
0
  (void) UnregisterMagickInfo("OTB");
253
0
}
254

255
/*
256
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257
%                                                                             %
258
%                                                                             %
259
%                                                                             %
260
%   W r i t e O T B I m a g e                                                 %
261
%                                                                             %
262
%                                                                             %
263
%                                                                             %
264
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265
%
266
%  Method WriteOTBImage writes an image to a file in the On-the-air Bitmap
267
%  (level 0) image format.
268
%
269
%  The format of the WriteOTBImage method is:
270
%
271
%      unsigned int WriteOTBImage(const ImageInfo *image_info,Image *image)
272
%
273
%  A description of each parameter follows.
274
%
275
%    o status: Method WriteOTBImage return True if the image is written.
276
%      False is returned is there is a memory shortage or if the image file
277
%      fails to write.
278
%
279
%    o image_info: Specifies a pointer to a ImageInfo structure.
280
%
281
%    o image:  A pointer to an Image structure.
282
%
283
%
284
*/
285
static unsigned int WriteOTBImage(const ImageInfo *image_info,Image *image)
286
204
{
287
204
#define SetBit(a,i,set) \
288
282
  a=(unsigned char) ((set) ? (a) | (1L << (i)) : (a) & ~(1L << (i)))
289
290
204
  long
291
204
    y;
292
293
204
  register const PixelPacket
294
204
    *p;
295
296
204
  register const IndexPacket
297
204
    *indexes;
298
299
204
  register long
300
204
    x;
301
302
204
  unsigned char
303
204
    bit,
304
204
    byte,
305
204
    info,
306
204
    polarity;
307
308
204
  unsigned int
309
204
    status;
310
311
  /*
312
    Open output image file.
313
  */
314
204
  assert(image_info != (const ImageInfo *) NULL);
315
204
  assert(image_info->signature == MagickSignature);
316
204
  assert(image != (Image *) NULL);
317
204
  assert(image->signature == MagickSignature);
318
204
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
319
204
  if (status == False)
320
204
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
321
204
  (void) TransformColorspace(image,RGBColorspace);
322
  /*
323
    Convert image to a bi-level image.
324
  */
325
204
  (void) SetImageType(image,BilevelType);
326
204
  polarity=PixelIntensityToQuantum(&image->colormap[0]) < (MaxRGB/2);
327
204
  if (image->colors == 2)
328
204
    polarity=PixelIntensityToQuantum(&image->colormap[0]) <
329
204
      PixelIntensityToQuantum(&image->colormap[1]);
330
204
  info=0;
331
204
  if ((image->columns >= 256) || (image->rows >= 256))
332
78
    SetBit(info,4,1);
333
204
  (void) WriteBlobByte(image,info);
334
204
  if ((image->columns >= 256) || (image->rows >= 256))
335
78
    {
336
78
      (void) WriteBlobMSBShort(image,image->columns);
337
78
      (void) WriteBlobMSBShort(image,image->rows);
338
78
    }
339
126
  else
340
126
    {
341
126
      (void) WriteBlobByte(image,(long) image->columns);
342
126
      (void) WriteBlobByte(image,(long) image->rows);
343
126
    }
344
204
  (void) WriteBlobByte(image,1);  /* depth */
345
89.9k
  for (y=0; y < (long) image->rows; y++)
346
89.7k
  {
347
89.7k
    p=AcquireImagePixels(image,0,y,image->columns,1,&image->exception);
348
89.7k
    if (p == (const PixelPacket *) NULL)
349
0
      break;
350
89.7k
    indexes=AccessImmutableIndexes(image);
351
89.7k
    bit=0;
352
89.7k
    byte=0;
353
32.7M
    for (x=0; x < (long) image->columns; x++)
354
32.6M
    {
355
32.6M
      if (indexes[x] == polarity)
356
14.2M
        byte|=0x1 << (7-bit);
357
32.6M
      bit++;
358
32.6M
      if (bit == 8)
359
4.05M
        {
360
4.05M
          (void) WriteBlobByte(image,byte);
361
4.05M
          bit=0;
362
4.05M
          byte=0;
363
4.05M
        }
364
32.6M
    }
365
89.7k
    if (bit != 0)
366
67.9k
      (void) WriteBlobByte(image,byte);
367
89.7k
    if (QuantumTick(y,image->rows))
368
15.2k
      if (!MagickMonitorFormatted(y,image->rows,&image->exception,
369
15.2k
                                  SaveImageText,image->filename,
370
15.2k
                                  image->columns,image->rows))
371
0
        break;
372
89.7k
  }
373
204
  status &= CloseBlob(image);
374
204
  return(status);
375
204
}