braille.c revision 79f189952032391bb2623c5efe0202152d9f0986
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-2009 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%    http://www.imagemagick.org/script/license.php                            %
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 "magick/studio.h"
41#include "magick/blob.h"
42#include "magick/blob-private.h"
43#include "magick/cache.h"
44#include "magick/color-private.h"
45#include "magick/colorspace.h"
46#include "magick/constitute.h"
47#include "magick/exception.h"
48#include "magick/exception-private.h"
49#include "magick/image.h"
50#include "magick/image-private.h"
51#include "magick/list.h"
52#include "magick/magick.h"
53#include "magick/memory_.h"
54#include "magick/module.h"
55#include "magick/monitor.h"
56#include "magick/monitor-private.h"
57#include "magick/property.h"
58#include "magick/quantize.h"
59#include "magick/static.h"
60#include "magick/string_.h"
61#include "magick/utility.h"
62
63/*
64  Forward declarations.
65*/
66static MagickBooleanType
67  WriteBRAILLEImage(const ImageInfo *,Image *);
68
69/*
70%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
71%                                                                             %
72%                                                                             %
73%                                                                             %
74%   R e g i s t e r B R A I L L E I m a g e                                   %
75%                                                                             %
76%                                                                             %
77%                                                                             %
78%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
79%
80%  RegisterBRAILLEImage() adds values for the Braille format to
81%  the list of supported formats.  The values include the image format
82%  tag, a method to read and/or write the format, whether the format
83%  supports the saving of more than one frame to the same file or blob,
84%  whether the format supports native in-memory I/O, and a brief
85%  description of the format.
86%
87%  The format of the RegisterBRAILLEImage method is:
88%
89%      unsigned long RegisterBRAILLEImage(void)
90%
91*/
92ModuleExport unsigned long RegisterBRAILLEImage(void)
93{
94  MagickInfo
95    *entry;
96
97  entry=SetMagickInfo("BRF");
98  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
99  entry->adjoin=MagickFalse;
100  entry->description=AcquireString("BRF ASCII Braille format");
101  entry->module=AcquireString("BRAILLE");
102  (void) RegisterMagickInfo(entry);
103  entry=SetMagickInfo("UBRL");
104  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
105  entry->adjoin=MagickFalse;
106  entry->description=AcquireString("Unicode Text format");
107  entry->module=AcquireString("BRAILLE");
108  (void) RegisterMagickInfo(entry);
109  entry=SetMagickInfo("ISOBRL");
110  entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage;
111  entry->adjoin=MagickFalse;
112  entry->description=AcquireString("ISO/TR 11548-1 format");
113  entry->module=AcquireString("BRAILLE");
114  (void) RegisterMagickInfo(entry);
115  return(MagickImageCoderSignature);
116}
117
118/*
119%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120%                                                                             %
121%                                                                             %
122%                                                                             %
123%   U n r e g i s t e r B R A I L L E I m a g e                               %
124%                                                                             %
125%                                                                             %
126%                                                                             %
127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
128%
129%  UnregisterBRAILLEImage() removes format registrations made by the
130%  BRAILLE module from the list of supported formats.
131%
132%  The format of the UnregisterBRAILLEImage method is:
133%
134%      UnregisterBRAILLEImage(void)
135%
136*/
137ModuleExport void UnregisterBRAILLEImage(void)
138{
139  (void) UnregisterMagickInfo("BRF");
140  (void) UnregisterMagickInfo("UBRL");
141  (void) UnregisterMagickInfo("ISOBRL");
142}
143
144/*
145%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
146%                                                                             %
147%                                                                             %
148%                                                                             %
149%   W r i t e B R A I L L E I m a g e                                         %
150%                                                                             %
151%                                                                             %
152%                                                                             %
153%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
154%
155%  WriteBRAILLEImage() writes an image to a file in the Braille format.
156%
157%  The format of the WriteBRAILLEImage method is:
158%
159%      MagickBooleanType WriteBRAILLEImage(const ImageInfo *image_info,
160%        Image *image)
161%
162%  A description of each parameter follows.
163%
164%    o image_info: The image info.
165%
166%    o image:  The image.
167%
168*/
169static MagickBooleanType WriteBRAILLEImage(const ImageInfo *image_info,
170  Image *image)
171{
172  char
173    buffer[MaxTextExtent];
174
175  const char
176    *value;
177
178  int
179    unicode = 0,
180    iso_11548_1 = 0;
181
182  long
183    y;
184
185  MagickBooleanType
186    status;
187
188  register const IndexPacket
189    *indexes;
190
191  register const PixelPacket
192    *p;
193
194  IndexPacket
195    polarity;
196
197  register long
198    x;
199
200  unsigned long
201    cell_height = 4;
202
203  /*
204    Open output image file.
205  */
206  assert(image_info != (const ImageInfo *) NULL);
207  assert(image_info->signature == MagickSignature);
208  assert(image != (Image *) NULL);
209  assert(image->signature == MagickSignature);
210  if (LocaleCompare(image_info->magick, "UBRL") == 0)
211    unicode=1;
212  else
213    if (LocaleCompare(image_info->magick, "ISOBRL") == 0)
214      iso_11548_1=1;
215    else
216      cell_height=3;
217  if (image->debug != MagickFalse)
218    (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
219  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
220  if (status == MagickFalse)
221    return(status);
222  if (!iso_11548_1)
223    {
224      value=GetImageProperty(image,"Label");
225      if (value != (const char *) NULL) {
226        (void) FormatMagickString(buffer,MaxTextExtent,"Title: %s\n", value);
227        (void) WriteBlobString(image,buffer);
228      }
229      if (image->page.x)
230      {
231        (void) FormatMagickString(buffer,MaxTextExtent,"X: %ld\n",
232          image->page.x);
233        (void) WriteBlobString(image,buffer);
234      }
235      if (image->page.y)
236      {
237        (void) FormatMagickString(buffer,MaxTextExtent,"Y: %ld\n",
238          image->page.y);
239        (void) WriteBlobString(image,buffer);
240      }
241      (void) FormatMagickString(buffer,MaxTextExtent,"Width: %lu\n",
242        image->columns+(image->columns % 2));
243      (void) WriteBlobString(image,buffer);
244      (void) FormatMagickString(buffer,MaxTextExtent,"Height: %lu\n",
245        image->rows);
246      (void) WriteBlobString(image,buffer);
247      (void) WriteBlobString(image,"\n");
248    }
249  (void) SetImageType(image,BilevelType);
250  polarity = 0;
251  if (image->storage_class == PseudoClass) {
252    polarity=(IndexPacket) (PixelIntensityToQuantum(&image->colormap[0]) >=
253      (Quantum) (QuantumRange/2));
254    if (image->colors == 2)
255      polarity=(IndexPacket)
256        (PixelIntensityToQuantum(&image->colormap[0]) >=
257         PixelIntensityToQuantum(&image->colormap[1]));
258  }
259  for (y=0; y < (long) image->rows; y+=cell_height)
260  {
261    if ((y+cell_height) > image->rows)
262      cell_height = (unsigned long) (image->rows-y);
263
264    p=GetVirtualPixels(image,0,y,image->columns,cell_height,&image->exception);
265    if (p == (const PixelPacket *) NULL)
266      break;
267    indexes=GetVirtualIndexQueue(image);
268    for (x=0; x < (long) image->columns; x+=2)
269    {
270      unsigned char cell = 0;
271      int two_columns = x+1 < (long) image->columns;
272
273      do
274      {
275#define do_cell(dx,dy,bit) do { \
276        if (image->storage_class == PseudoClass) \
277          cell |= (indexes[x+dx+dy*image->columns] == polarity) << bit; \
278        else \
279          cell |= (p[x+dx+dy*image->columns].green == 0) << bit; \
280} while (0)
281
282        do_cell(0,0,0);
283        if (two_columns)
284          do_cell(1,0,3);
285        if (cell_height < 2)
286          break;
287
288        do_cell(0,1,1);
289        if (two_columns)
290          do_cell(1,1,4);
291        if (cell_height < 3)
292          break;
293
294        do_cell(0,2,2);
295        if (two_columns)
296          do_cell(1,2,5);
297        if (cell_height < 4)
298          break;
299
300        do_cell(0,3,6);
301        if (two_columns)
302          do_cell(1,3,7);
303      } while(0);
304
305      if (unicode)
306        {
307          unsigned char utf8[3];
308          /* Unicode text */
309          utf8[0] = (unsigned char) (0xe0|((0x28>>4)&0x0f));
310          utf8[1] = 0x80|((0x28<<2)&0x3f)|(cell>>6);
311          utf8[2] = 0x80|(cell&0x3f);
312          (void) WriteBlob(image,3,utf8);
313        }
314      else if (iso_11548_1)
315        {
316          /* ISO/TR 11548-1 binary */
317          (void) WriteBlobByte(image,cell);
318        }
319      else
320        {
321          /* BRF */
322          static const unsigned char iso_to_brf[64] = {
323            ' ', 'A', '1', 'B', '\'', 'K', '2', 'L',
324            '@', 'C', 'I', 'F', '/', 'M', 'S', 'P',
325            '"', 'E', '3', 'H', '9', 'O', '6', 'R',
326            '^', 'D', 'J', 'G', '>', 'N', 'T', 'Q',
327            ',', '*', '5', '<', '-', 'U', '8', 'V',
328            '.', '%', '[', '$', '+', 'X', '!', '&',
329            ';', ':', '4', '\\', '0', 'Z', '7', '(',
330            '_', '?', 'W', ']', '#', 'Y', ')', '='
331          };
332          (void) WriteBlobByte(image,iso_to_brf[cell]);
333        }
334    }
335    if (!iso_11548_1)
336      (void) WriteBlobByte(image,'\n');
337    status=SetImageProgress(image,SaveImageTag,y,image->rows);
338    if (status == MagickFalse)
339      break;
340  }
341  (void) CloseBlob(image);
342  return(MagickTrue);
343}
344