Coverage Report

Created: 2026-02-14 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/imagemagick/coders/braille.c
Line
Count
Source
1
/*
2
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3
%                                                                             %
4
%                                                                             %
5
%               BBBB   RRRR    AAA   IIIII  L      L      EEEEE               %
6
%               B   B  R   R  A   A    I    L      L      E                   %
7
%               BBBB   RRRR   AAAAA    I    L      L      EEE                 %
8
%               B   B  R R    A   A    I    L      L      E                   %
9
%               BBBB   R  R   A   A  IIIII  LLLLL  LLLLL  EEEEE               %
10
%                                                                             %
11
%                                                                             %
12
%                          Read/Write Braille Format                          %
13
%                                                                             %
14
%                               Samuel Thibault                               %
15
%                                February 2008                                %
16
%                                                                             %
17
%                                                                             %
18
%  Copyright @ 1999 ImageMagick Studio LLC, a non-profit organization         %
19
%  dedicated to making software imaging solutions freely available.           %
20
%                                                                             %
21
%  You may not use this file except in compliance with the License.  You may  %
22
%  obtain a copy of the License at                                            %
23
%                                                                             %
24
%    https://imagemagick.org/license/                                         %
25
%                                                                             %
26
%  Unless required by applicable law or agreed to in writing, software        %
27
%  distributed under the License is distributed on an "AS IS" BASIS,          %
28
%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
29
%  See the License for the specific language governing permissions and        %
30
%  limitations under the License.                                             %
31
%                                                                             %
32
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
33
%
34
%
35
*/
36

37
/*
38
  Include declarations.
39
*/
40
#include "MagickCore/studio.h"
41
#include "MagickCore/attribute.h"
42
#include "MagickCore/blob.h"
43
#include "MagickCore/blob-private.h"
44
#include "MagickCore/cache.h"
45
#include "MagickCore/color-private.h"
46
#include "MagickCore/colorspace.h"
47
#include "MagickCore/constitute.h"
48
#include "MagickCore/exception.h"
49
#include "MagickCore/exception-private.h"
50
#include "MagickCore/image.h"
51
#include "MagickCore/image-private.h"
52
#include "MagickCore/list.h"
53
#include "MagickCore/magick.h"
54
#include "MagickCore/memory_.h"
55
#include "MagickCore/module.h"
56
#include "MagickCore/monitor.h"
57
#include "MagickCore/monitor-private.h"
58
#include "MagickCore/pixel-accessor.h"
59
#include "MagickCore/property.h"
60
#include "MagickCore/quantize.h"
61
#include "MagickCore/static.h"
62
#include "MagickCore/string_.h"
63
#include "MagickCore/utility.h"
64

65
/*
66
  Forward declarations.
67
*/
68
static MagickBooleanType
69
  WriteBRAILLEImage(const ImageInfo *,Image *,ExceptionInfo *);
70

71
/*
72
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73
%                                                                             %
74
%                                                                             %
75
%                                                                             %
76
%   R e g i s t e r B R A I L L E I m a g e                                   %
77
%                                                                             %
78
%                                                                             %
79
%                                                                             %
80
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
81
%
82
%  RegisterBRAILLEImage() adds values for the Braille format to
83
%  the list of supported formats.  The values include the image format
84
%  tag, a method to read and/or write the format, whether the format
85
%  supports the saving of more than one frame to the same file or blob,
86
%  whether the format supports native in-memory I/O, and a brief
87
%  description of the format.
88
%
89
%  The format of the RegisterBRAILLEImage method is:
90
%
91
%      size_t RegisterBRAILLEImage(void)
92
%
93
*/
94
ModuleExport size_t RegisterBRAILLEImage(void)
95
7
{
96
7
  MagickInfo
97
7
    *entry;
98
99
7
  entry=AcquireMagickInfo("BRAILLE","BRF","BRF ASCII Braille format");
100
7
  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
101
7
  entry->flags^=CoderAdjoinFlag;
102
7
  (void) RegisterMagickInfo(entry);
103
7
  entry=AcquireMagickInfo("BRAILLE","UBRL","Unicode Text format");
104
7
  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
105
7
  entry->flags^=CoderAdjoinFlag;
106
7
  (void) RegisterMagickInfo(entry);
107
7
  entry=AcquireMagickInfo("BRAILLE","UBRL6","Unicode Text format 6dot");
108
7
  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
109
7
  entry->flags^=CoderAdjoinFlag;
110
7
  (void) RegisterMagickInfo(entry);
111
7
  entry=AcquireMagickInfo("BRAILLE","ISOBRL","ISO/TR 11548-1 format");
112
7
  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
113
7
  entry->flags^=CoderAdjoinFlag;
114
7
  (void) RegisterMagickInfo(entry);
115
7
  entry=AcquireMagickInfo("BRAILLE","ISOBRL6","ISO/TR 11548-1 format 6dot");
116
7
  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
117
7
  entry->flags^=CoderAdjoinFlag;
118
7
  (void) RegisterMagickInfo(entry);
119
7
  return(MagickImageCoderSignature);
120
7
}
121

122
/*
123
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
124
%                                                                             %
125
%                                                                             %
126
%                                                                             %
127
%   U n r e g i s t e r B R A I L L E I m a g e                               %
128
%                                                                             %
129
%                                                                             %
130
%                                                                             %
131
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
132
%
133
%  UnregisterBRAILLEImage() removes format registrations made by the
134
%  BRAILLE module from the list of supported formats.
135
%
136
%  The format of the UnregisterBRAILLEImage method is:
137
%
138
%      UnregisterBRAILLEImage(void)
139
%
140
*/
141
ModuleExport void UnregisterBRAILLEImage(void)
142
0
{
143
0
  (void) UnregisterMagickInfo("BRF");
144
0
  (void) UnregisterMagickInfo("UBRL");
145
0
  (void) UnregisterMagickInfo("UBRL6");
146
0
  (void) UnregisterMagickInfo("ISOBRL");
147
0
  (void) UnregisterMagickInfo("ISOBRL6");
148
0
}
149

150
/*
151
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
152
%                                                                             %
153
%                                                                             %
154
%                                                                             %
155
%   W r i t e B R A I L L E I m a g e                                         %
156
%                                                                             %
157
%                                                                             %
158
%                                                                             %
159
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
160
%
161
%  WriteBRAILLEImage() writes an image to a file in the Braille format.
162
%
163
%  The format of the WriteBRAILLEImage method is:
164
%
165
%      MagickBooleanType WriteBRAILLEImage(const ImageInfo *image_info,
166
%        Image *image,ExceptionInfo *exception)
167
%
168
%  A description of each parameter follows.
169
%
170
%    o image_info: The image info.
171
%
172
%    o image:  The image.
173
%
174
%    o exception: return any errors or warnings in this structure.
175
%
176
*/
177
static MagickBooleanType WriteBRAILLEImage(const ImageInfo *image_info,
178
  Image *image,ExceptionInfo *exception)
179
0
{
180
0
#define do_cell(dx,dy,bit) \
181
0
{ \
182
0
  if (image->storage_class == PseudoClass) \
183
0
    cell|=(GetPixelIndex(image,p+(x+(ssize_t) (dx))*(ssize_t) \
184
0
      GetImageChannels(image)+(dy)*(ssize_t) (image->columns* \
185
0
      GetImageChannels(image))) == polarity) << bit; \
186
0
  else \
187
0
    cell|=(GetPixelGreen(image,p+(x+(ssize_t) (dx))*(ssize_t) \
188
0
      GetImageChannels(image)+(dy)*((ssize_t) image->columns*(ssize_t) \
189
0
      GetImageChannels(image))) == 0) << bit; \
190
0
}
191
192
0
  char
193
0
    buffer[MagickPathExtent];
194
195
0
  const char
196
0
    *value;
197
198
0
  const Quantum
199
0
    *p;
200
201
0
  int
202
0
    unicode = 0,
203
0
    iso_11548_1 = 0;
204
205
0
  MagickBooleanType
206
0
    status;
207
208
0
  Quantum
209
0
    polarity;
210
211
0
  size_t
212
0
    cell_height = 4;
213
214
0
  ssize_t
215
0
    x,
216
0
    y;
217
218
  /*
219
    Open output image file.
220
  */
221
0
  assert(image_info != (const ImageInfo *) NULL);
222
0
  assert(image_info->signature == MagickCoreSignature);
223
0
  assert(image != (Image *) NULL);
224
0
  assert(image->signature == MagickCoreSignature);
225
0
  assert(exception != (ExceptionInfo *) NULL);
226
0
  assert(exception->signature == MagickCoreSignature);
227
0
  if (IsEventLogging() != MagickFalse)
228
0
    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
229
0
  if (LocaleCompare(image_info->magick,"UBRL") == 0)
230
0
    unicode=1;
231
0
  else
232
0
    if (LocaleCompare(image_info->magick,"UBRL6") == 0)
233
0
      {
234
0
        unicode=1;
235
0
        cell_height=3;
236
0
      }
237
0
    else
238
0
      if (LocaleCompare(image_info->magick,"ISOBRL") == 0)
239
0
        iso_11548_1=1;
240
0
      else
241
0
        if (LocaleCompare(image_info->magick,"ISOBRL6") == 0)
242
0
          {
243
0
            iso_11548_1=1;
244
0
            cell_height=3;
245
0
          }
246
0
        else
247
0
          cell_height=3;
248
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
249
0
  if (status == MagickFalse)
250
0
    return(status);
251
0
  if (iso_11548_1 == 0)
252
0
    {
253
0
      value=GetImageProperty(image,"label",exception);
254
0
      if (value != (const char *) NULL)
255
0
        {
256
0
          (void) FormatLocaleString(buffer,MagickPathExtent,"Title: %s\n",
257
0
            value);
258
0
          (void) WriteBlobString(image,buffer);
259
0
        }
260
0
      if (image->page.x != 0)
261
0
        {
262
0
          (void) FormatLocaleString(buffer,MagickPathExtent,"X: %.20g\n",
263
0
            (double) image->page.x);
264
0
          (void) WriteBlobString(image,buffer);
265
0
        }
266
0
      if (image->page.y != 0)
267
0
        {
268
0
          (void) FormatLocaleString(buffer,MagickPathExtent,"Y: %.20g\n",
269
0
            (double) image->page.y);
270
0
          (void) WriteBlobString(image,buffer);
271
0
        }
272
0
      (void) FormatLocaleString(buffer,MagickPathExtent,"Width: %.20g\n",
273
0
        (double) (image->columns+(image->columns % 2)));
274
0
      (void) WriteBlobString(image,buffer);
275
0
      (void) FormatLocaleString(buffer,MagickPathExtent,"Height: %.20g\n",
276
0
        (double) image->rows);
277
0
      (void) WriteBlobString(image,buffer);
278
0
      (void) WriteBlobString(image,"\n");
279
0
    }
280
0
  (void) SetImageType(image,BilevelType,exception);
281
0
  polarity=0;
282
0
  if (image->storage_class == PseudoClass)
283
0
    {
284
0
      polarity=(Quantum) (GetPixelInfoIntensity(image,&image->colormap[0]) >=
285
0
        ((double) QuantumRange/2.0));
286
0
      if (image->colors == 2)
287
0
        polarity=(Quantum) (GetPixelInfoIntensity(image,&image->colormap[0]) >=
288
0
          GetPixelInfoIntensity(image,&image->colormap[1]));
289
0
    }
290
0
  for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) cell_height)
291
0
  {
292
0
    if ((size_t) (y+(ssize_t) cell_height) > image->rows)
293
0
      cell_height=(size_t) ((ssize_t) image->rows-y);
294
0
    p=GetVirtualPixels(image,0,y,image->columns,cell_height,exception);
295
0
    if (p == (const Quantum *) NULL)
296
0
      break;
297
0
    for (x=0; x < (ssize_t) image->columns; x+=2)
298
0
    {
299
0
      MagickBooleanType
300
0
        two_columns;
301
302
0
      unsigned char
303
0
        cell = 0;
304
305
0
      two_columns=(x+1) < (ssize_t) image->columns ? MagickTrue : MagickFalse;
306
0
      do_cell(0,0,0)
307
0
      if (two_columns != MagickFalse)
308
0
        do_cell(1,0,3)
309
0
      if (cell_height > 1)
310
0
        {
311
0
          do_cell(0,1,1)
312
0
          if (two_columns != MagickFalse)
313
0
            do_cell(1,1,4)
314
0
          if (cell_height > 2)
315
0
            {
316
0
              do_cell(0,2,2)
317
0
              if (two_columns != MagickFalse)
318
0
                do_cell(1,2,5)
319
0
              if (cell_height > 3)
320
0
                {
321
0
                  do_cell(0,3,6)
322
0
                  if (two_columns != MagickFalse)
323
0
                    do_cell(1,3,7)
324
0
                }
325
0
            }
326
0
        }
327
0
      if (unicode != 0)
328
0
        {
329
0
          unsigned char
330
0
            utf8[3];
331
332
          /*
333
            Unicode text.
334
          */
335
0
          utf8[0]=(unsigned char) (0xe0 | ((0x28 >> 4) & 0x0f));
336
0
          utf8[1]=0x80| ((0x28 << 2) & 0x3f) | (cell >> 6);
337
0
          utf8[2]=0x80| (cell & 0x3f);
338
0
          (void) WriteBlob(image,3,utf8);
339
0
        }
340
0
      else
341
0
        if (iso_11548_1 != 0)
342
0
          {
343
            /*
344
              ISO/TR 11548-1 binary.
345
            */
346
0
            (void) WriteBlobByte(image,cell);
347
0
          }
348
0
        else
349
0
          {
350
0
            static const unsigned char
351
0
              iso_to_brf[64] =
352
0
              {
353
0
                ' ', 'A', '1', 'B', '\'', 'K', '2', 'L',
354
0
                '@', 'C', 'I', 'F', '/', 'M', 'S', 'P',
355
0
                '"', 'E', '3', 'H', '9', 'O', '6', 'R',
356
0
                '^', 'D', 'J', 'G', '>', 'N', 'T', 'Q',
357
0
                ',', '*', '5', '<', '-', 'U', '8', 'V',
358
0
                '.', '%', '[', '$', '+', 'X', '!', '&',
359
0
                ';', ':', '4', '\\', '0', 'Z', '7', '(',
360
0
                '_', '?', 'W', ']', '#', 'Y', ')', '='
361
0
              };
362
363
            /*
364
              BRF.
365
            */
366
0
            (void) WriteBlobByte(image,iso_to_brf[cell]);
367
0
          }
368
0
    }
369
0
    if (iso_11548_1 == 0)
370
0
      (void) WriteBlobByte(image,'\n');
371
0
    status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
372
0
      image->rows);
373
0
    if (status == MagickFalse)
374
0
      break;
375
0
  }
376
0
  if (CloseBlob(image) == MagickFalse)
377
0
    status=MagickFalse;
378
0
  return(status);
379
0
}