Coverage Report

Created: 2026-01-20 07:37

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