Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/braille.c
Line
Count
Source
1
/*
2
% Copyright (C) 2019-2026 GraphicsMagick Group
3
% SPDX-License-Identifier: MIT
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
%               BBBB   RRRR    AAA   IIIII  L      L      EEEEE               %
13
%               B   B  R   R  A   A    I    L      L      E                   %
14
%               BBBB   RRRR   AAAAA    I    L      L      EEE                 %
15
%               B   B  R R    A   A    I    L      L      E                   %
16
%               BBBB   R  R   A   A  IIIII  LLLLL  LLLLL  EEEEE               %
17
%                                                                             %
18
%                                                                             %
19
%                          Read/Write Braille Format                          %
20
%                                                                             %
21
%                               Samuel Thibault                               %
22
%                                February 2008                                %
23
%                                                                             %
24
%                                                                             %
25
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
26
%
27
%
28
*/
29

30
/*
31
  Include declarations.
32
*/
33
#include "magick/studio.h"
34
#include "magick/blob.h"
35
#include "magick/magick.h"
36
#include "magick/pixel_cache.h"
37
#include "magick/utility.h"
38
#include "magick/static.h"
39

40
/*
41
  Forward declarations.
42
*/
43
static unsigned int
44
  WriteBRAILLEImage(const ImageInfo *,Image *);
45
46

47
/*
48
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
49
%                                                                             %
50
%                                                                             %
51
%                                                                             %
52
%   R e g i s t e r B R A I L L E I m a g e                                   %
53
%                                                                             %
54
%                                                                             %
55
%                                                                             %
56
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
%
58
%  RegisterBRAILLEImage() adds values for the Braille format to
59
%  the list of supported formats.  The values include the image format
60
%  tag, a method to read and/or write the format, whether the format
61
%  supports the saving of more than one frame to the same file or blob,
62
%  whether the format supports native in-memory I/O, and a brief
63
%  description of the format.
64
%
65
%  The format of the RegisterBRAILLEImage method is:
66
%
67
%      size_t RegisterBRAILLEImage(void)
68
%
69
*/
70
ModuleExport void RegisterBRAILLEImage(void)
71
0
{
72
0
  MagickInfo
73
0
    *entry;
74
75
0
  entry=SetMagickInfo("BRF");
76
0
  entry->encoder=(EncoderHandler) WriteBRAILLEImage;
77
0
  entry->adjoin=False;
78
0
  entry->description="BRF ASCII Braille format";
79
0
  entry->module="BRAILLE";
80
0
  (void) RegisterMagickInfo(entry);
81
0
  entry=SetMagickInfo("UBRL");
82
0
  entry->encoder=(EncoderHandler) WriteBRAILLEImage;
83
0
  entry->adjoin=False;
84
0
  entry->description="Unicode Text format";
85
0
  entry->module="BRAILLE";
86
0
  (void) RegisterMagickInfo(entry);
87
0
  entry=SetMagickInfo("UBRL6");
88
0
  entry->encoder=(EncoderHandler) WriteBRAILLEImage;
89
0
  entry->adjoin=False;
90
0
  entry->description="Unicode Text format 6dot";
91
0
  entry->module="BRAILLE";
92
0
  (void) RegisterMagickInfo(entry);
93
0
  entry=SetMagickInfo("ISOBRL");
94
0
  entry->encoder=(EncoderHandler) WriteBRAILLEImage;
95
0
  entry->adjoin=False;
96
0
  entry->description="ISO/TR 11548-1 format";
97
0
  entry->module="BRAILLE";
98
0
  (void) RegisterMagickInfo(entry);
99
0
  entry=SetMagickInfo("ISOBRL6");
100
0
  entry->encoder=(EncoderHandler) WriteBRAILLEImage;
101
0
  entry->adjoin=False;
102
0
  entry->description="ISO/TR 11548-1 format 6dot";
103
0
  entry->module="BRAILLE";
104
0
  (void) RegisterMagickInfo(entry);
105
0
}
106

107
/*
108
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109
%                                                                             %
110
%                                                                             %
111
%                                                                             %
112
%   U n r e g i s t e r B R A I L L E I m a g e                               %
113
%                                                                             %
114
%                                                                             %
115
%                                                                             %
116
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
117
%
118
%  UnregisterBRAILLEImage() removes format registrations made by the
119
%  BRAILLE module from the list of supported formats.
120
%
121
%  The format of the UnregisterBRAILLEImage method is:
122
%
123
%      UnregisterBRAILLEImage(void)
124
%
125
*/
126
ModuleExport void UnregisterBRAILLEImage(void)
127
0
{
128
0
  (void) UnregisterMagickInfo("BRF");
129
0
  (void) UnregisterMagickInfo("UBRL");
130
0
  (void) UnregisterMagickInfo("UBRL6");
131
0
  (void) UnregisterMagickInfo("ISOBRL");
132
0
  (void) UnregisterMagickInfo("ISOBRL6");
133
0
}
134

135
/*
136
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
137
%                                                                             %
138
%                                                                             %
139
%                                                                             %
140
%   W r i t e B R A I L L E I m a g e                                         %
141
%                                                                             %
142
%                                                                             %
143
%                                                                             %
144
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145
%
146
%  WriteBRAILLEImage() writes an image to a file in the Braille format.
147
%
148
%  The format of the WriteBRAILLEImage method is:
149
%
150
%      unsigned int WriteBRAILLEImage(const ImageInfo *image_info,
151
%        Image *image)
152
%
153
%  A description of each parameter follows.
154
%
155
%    o image_info: The image info.
156
%
157
%    o image:  The image.
158
%
159
*/
160
static unsigned int WriteBRAILLEImage(const ImageInfo *image_info,
161
  Image *image)
162
0
{
163
0
  char
164
0
    buffer[MaxTextExtent];
165
166
0
  IndexPacket
167
0
    polarity;
168
169
0
  int
170
0
    unicode = 0,
171
0
    iso_11548_1 = 0;
172
173
0
  MagickPassFail
174
0
    status = MagickPass;
175
176
0
  register const IndexPacket
177
0
    *indexes;
178
179
0
  register const PixelPacket
180
0
    *p;
181
182
0
  register unsigned long
183
0
    x;
184
185
0
  unsigned long
186
0
    cell_height = 4;
187
188
0
  unsigned long
189
0
    y;
190
191
0
  assert(image_info != (const ImageInfo *) NULL);
192
0
  assert(image != (Image *) NULL);
193
194
0
  if (SetImageType(image,BilevelType) == MagickFail)
195
0
    ThrowWriterException(CoderError,UnableToSetImageType,image);
196
197
  /*
198
    Open output image file.
199
  */
200
0
  if (LocaleCompare(image_info->magick,"UBRL") == 0)
201
0
    unicode=1;
202
0
  else if (LocaleCompare(image_info->magick,"UBRL6") == 0)
203
0
    {
204
0
      unicode=1;
205
0
      cell_height=3;
206
0
    }
207
0
  else if (LocaleCompare(image_info->magick,"ISOBRL") == 0)
208
0
    iso_11548_1=1;
209
0
  else if (LocaleCompare(image_info->magick,"ISOBRL6") == 0)
210
0
    {
211
0
      iso_11548_1=1;
212
0
      cell_height=3;
213
0
    }
214
0
  else
215
0
    cell_height=3;
216
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
217
0
  if (status == False)
218
0
    return(status);
219
0
  if (!iso_11548_1)
220
0
    {
221
0
      if (image->page.x != 0)
222
0
        {
223
0
          (void) MagickFormatString(buffer,sizeof(buffer),"X: %.20g\n",(double)
224
0
            image->page.x);
225
0
          (void) WriteBlobString(image,buffer);
226
0
        }
227
0
      if (image->page.y != 0)
228
0
        {
229
0
          (void) MagickFormatString(buffer,sizeof(buffer),"Y: %.20g\n",(double)
230
0
            image->page.y);
231
0
          (void) WriteBlobString(image,buffer);
232
0
        }
233
0
      (void) MagickFormatString(buffer,sizeof(buffer),"Width: %.20g\n",(double)
234
0
        image->columns+(image->columns % 2));
235
0
      (void) WriteBlobString(image,buffer);
236
0
      (void) MagickFormatString(buffer,sizeof(buffer),"Height: %.20g\n",(double)
237
0
        image->rows);
238
0
      (void) WriteBlobString(image,buffer);
239
0
      (void) WriteBlobString(image,"\n");
240
0
    }
241
0
  polarity=PixelIntensityToQuantum(&image->colormap[0]) >= (MaxRGB/2);
242
0
  if (image->colors == 2)
243
0
    polarity=PixelIntensityToQuantum(&image->colormap[0]) >=
244
0
      PixelIntensityToQuantum(&image->colormap[1]);
245
0
  for (y=0; y < image->rows; y+=cell_height)
246
0
  {
247
0
    if ((y+cell_height) > image->rows)
248
0
      cell_height = (image->rows-y);
249
0
    p=AcquireImagePixels(image,0,y,image->columns,cell_height,&image->exception);
250
0
    if (p == (const PixelPacket *) NULL)
251
0
      break;
252
0
    indexes=AccessImmutableIndexes(image);
253
0
    for (x=0; x < image->columns; x+=2)
254
0
    {
255
0
      unsigned char cell = 0;
256
0
      unsigned long two_columns = x+1 < image->columns;
257
258
0
      do
259
0
      {
260
0
#define do_cell(dx,dy,bit) do { \
261
0
        cell |= (indexes[x+dx+dy*image->columns] == polarity) << bit; \
262
0
} while (0)
263
264
0
        do_cell(0,0,0);
265
0
        if (two_columns)
266
0
          do_cell(1,0,3);
267
0
        if (cell_height < 2)
268
0
          break;
269
270
0
        do_cell(0,1,1);
271
0
        if (two_columns)
272
0
          do_cell(1,1,4);
273
0
        if (cell_height < 3)
274
0
          break;
275
276
0
        do_cell(0,2,2);
277
0
        if (two_columns)
278
0
          do_cell(1,2,5);
279
0
        if (cell_height < 4)
280
0
          break;
281
282
0
        do_cell(0,3,6);
283
0
        if (two_columns)
284
0
          do_cell(1,3,7);
285
0
      } while(0);
286
287
0
      if (unicode)
288
0
        {
289
0
          unsigned char utf8[3];
290
          /* Unicode text */
291
0
          utf8[0] = (unsigned char) (0xe0|((0x28>>4)&0x0f));
292
0
          utf8[1] = 0x80|((0x28<<2)&0x3f)|(cell>>6);
293
0
          utf8[2] = 0x80|(cell&0x3f);
294
0
          (void) WriteBlob(image,3,utf8);
295
0
        }
296
0
      else if (iso_11548_1)
297
0
        {
298
          /* ISO/TR 11548-1 binary */
299
0
          (void) WriteBlobByte(image,cell);
300
0
        }
301
0
      else
302
0
        {
303
          /* BRF */
304
0
          static const unsigned char iso_to_brf[64] = {
305
0
            ' ', 'A', '1', 'B', '\'', 'K', '2', 'L',
306
0
            '@', 'C', 'I', 'F', '/', 'M', 'S', 'P',
307
0
            '"', 'E', '3', 'H', '9', 'O', '6', 'R',
308
0
            '^', 'D', 'J', 'G', '>', 'N', 'T', 'Q',
309
0
            ',', '*', '5', '<', '-', 'U', '8', 'V',
310
0
            '.', '%', '[', '$', '+', 'X', '!', '&',
311
0
            ';', ':', '4', '\\', '0', 'Z', '7', '(',
312
0
            '_', '?', 'W', ']', '#', 'Y', ')', '='
313
0
          };
314
0
          if (cell >= 64)
315
0
            cell = 0;
316
0
          (void) WriteBlobByte(image,iso_to_brf[cell]);
317
0
        }
318
0
    }
319
0
    if (iso_11548_1 == 0)
320
0
      (void) WriteBlobByte(image,'\n');
321
0
  }
322
0
  status &= CloseBlob(image);
323
0
  return(status);
324
0
}