Coverage Report

Created: 2026-06-16 07:20

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