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