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