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/* 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*/ 68static 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*/ 94ModuleExport size_t RegisterBRAILLEImage(void) 95{ 96 MagickInfo 97 *entry; 98 99 entry=AcquireMagickInfo("BRAILLE","BRF","BRF ASCII Braille format"); 100 entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage; 101 entry->flags^=CoderAdjoinFlag; 102 (void) RegisterMagickInfo(entry); 103 entry=AcquireMagickInfo("BRAILLE","UBRL","Unicode Text format"); 104 entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage; 105 entry->flags^=CoderAdjoinFlag; 106 (void) RegisterMagickInfo(entry); 107 entry=AcquireMagickInfo("BRAILLE","UBRL6","Unicode Text format 6dot"); 108 entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage; 109 entry->flags^=CoderAdjoinFlag; 110 (void) RegisterMagickInfo(entry); 111 entry=AcquireMagickInfo("BRAILLE","ISOBRL","ISO/TR 11548-1 format"); 112 entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage; 113 entry->flags^=CoderAdjoinFlag; 114 (void) RegisterMagickInfo(entry); 115 entry=AcquireMagickInfo("BRAILLE","ISOBRL6","ISO/TR 11548-1 format 6dot"); 116 entry->encoder=(EncodeImageHandler *) WriteBRAILLEImage; 117 entry->flags^=CoderAdjoinFlag; 118 (void) RegisterMagickInfo(entry); 119 return(MagickImageCoderSignature); 120} 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*/ 141ModuleExport void UnregisterBRAILLEImage(void) 142{ 143 (void) UnregisterMagickInfo("BRF"); 144 (void) UnregisterMagickInfo("UBRL"); 145 (void) UnregisterMagickInfo("UBRL6"); 146 (void) UnregisterMagickInfo("ISOBRL"); 147 (void) UnregisterMagickInfo("ISOBRL6"); 148} 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*/ 177static MagickBooleanType WriteBRAILLEImage(const ImageInfo *image_info, 178 Image *image,ExceptionInfo *exception) 179{ 180 char 181 buffer[MagickPathExtent]; 182 183 const char 184 *value; 185 186 int 187 unicode = 0, 188 iso_11548_1 = 0; 189 190 MagickBooleanType 191 status; 192 193 Quantum 194 polarity; 195 196 register const Quantum 197 *p; 198 199 register ssize_t 200 x; 201 202 size_t 203 cell_height = 4; 204 205 ssize_t 206 y; 207 208 /* 209 Open output image file. 210 */ 211 assert(image_info != (const ImageInfo *) NULL); 212 assert(image_info->signature == MagickCoreSignature); 213 assert(image != (Image *) NULL); 214 assert(image->signature == MagickCoreSignature); 215 if (LocaleCompare(image_info->magick, "UBRL") == 0) 216 unicode=1; 217 else if (LocaleCompare(image_info->magick, "UBRL6") == 0) 218 { 219 unicode=1; 220 cell_height=3; 221 } 222 else if (LocaleCompare(image_info->magick, "ISOBRL") == 0) 223 iso_11548_1=1; 224 else if (LocaleCompare(image_info->magick, "ISOBRL6") == 0) 225 { 226 iso_11548_1=1; 227 cell_height=3; 228 } 229 else 230 cell_height=3; 231 if (image->debug != MagickFalse) 232 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 233 assert(exception != (ExceptionInfo *) NULL); 234 assert(exception->signature == MagickCoreSignature); 235 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 236 if (status == MagickFalse) 237 return(status); 238 if (!iso_11548_1) 239 { 240 value=GetImageProperty(image,"label",exception); 241 if (value != (const char *) NULL) 242 { 243 (void) FormatLocaleString(buffer,MagickPathExtent,"Title: %s\n", value); 244 (void) WriteBlobString(image,buffer); 245 } 246 if (image->page.x != 0) 247 { 248 (void) FormatLocaleString(buffer,MagickPathExtent,"X: %.20g\n",(double) 249 image->page.x); 250 (void) WriteBlobString(image,buffer); 251 } 252 if (image->page.y != 0) 253 { 254 (void) FormatLocaleString(buffer,MagickPathExtent,"Y: %.20g\n",(double) 255 image->page.y); 256 (void) WriteBlobString(image,buffer); 257 } 258 (void) FormatLocaleString(buffer,MagickPathExtent,"Width: %.20g\n",(double) 259 (image->columns+(image->columns % 2))); 260 (void) WriteBlobString(image,buffer); 261 (void) FormatLocaleString(buffer,MagickPathExtent,"Height: %.20g\n",(double) 262 image->rows); 263 (void) WriteBlobString(image,buffer); 264 (void) WriteBlobString(image,"\n"); 265 } 266 (void) SetImageType(image,BilevelType,exception); 267 polarity = 0; 268 if (image->storage_class == PseudoClass) { 269 polarity=(Quantum) (GetPixelInfoIntensity(image,&image->colormap[0]) >= 270 (QuantumRange/2.0)); 271 if (image->colors == 2) 272 polarity=(Quantum) (GetPixelInfoIntensity(image,&image->colormap[0]) >= 273 GetPixelInfoIntensity(image,&image->colormap[1])); 274 } 275 for (y=0; y < (ssize_t) image->rows; y+=(ssize_t) cell_height) 276 { 277 if ((y+cell_height) > image->rows) 278 cell_height = (size_t) (image->rows-y); 279 280 p=GetVirtualPixels(image,0,y,image->columns,cell_height,exception); 281 if (p == (const Quantum *) NULL) 282 break; 283 for (x=0; x < (ssize_t) image->columns; x+=2) 284 { 285 unsigned char cell = 0; 286 int two_columns = x+1 < (ssize_t) image->columns; 287 288 do 289 { 290#define do_cell(dx,dy,bit) do { \ 291 if (image->storage_class == PseudoClass) \ 292 cell |= (GetPixelIndex(image,p+x+dx+dy*image->columns) == polarity) << bit; \ 293 else \ 294 cell |= (GetPixelGreen(image,p+x+dx+dy*image->columns) == 0) << bit; \ 295DisableMSCWarning(4127) \ 296} while (0) \ 297RestoreMSCWarning 298 299 do_cell(0,0,0); 300 if (two_columns) 301 do_cell(1,0,3); 302 if (cell_height < 2) 303 break; 304 305 do_cell(0,1,1); 306 if (two_columns) 307 do_cell(1,1,4); 308 if (cell_height < 3) 309 break; 310 311 do_cell(0,2,2); 312 if (two_columns) 313 do_cell(1,2,5); 314 if (cell_height < 4) 315 break; 316 317 do_cell(0,3,6); 318 if (two_columns) 319 do_cell(1,3,7); 320DisableMSCWarning(4127) 321 } while(0); 322RestoreMSCWarning 323 324 if (unicode) 325 { 326 unsigned char utf8[3]; 327 /* Unicode text */ 328 utf8[0] = (unsigned char) (0xe0|((0x28>>4)&0x0f)); 329 utf8[1] = 0x80|((0x28<<2)&0x3f)|(cell>>6); 330 utf8[2] = 0x80|(cell&0x3f); 331 (void) WriteBlob(image,3,utf8); 332 } 333 else if (iso_11548_1) 334 { 335 /* ISO/TR 11548-1 binary */ 336 (void) WriteBlobByte(image,cell); 337 } 338 else 339 { 340 /* BRF */ 341 static const unsigned char iso_to_brf[64] = { 342 ' ', 'A', '1', 'B', '\'', 'K', '2', 'L', 343 '@', 'C', 'I', 'F', '/', 'M', 'S', 'P', 344 '"', 'E', '3', 'H', '9', 'O', '6', 'R', 345 '^', 'D', 'J', 'G', '>', 'N', 'T', 'Q', 346 ',', '*', '5', '<', '-', 'U', '8', 'V', 347 '.', '%', '[', '$', '+', 'X', '!', '&', 348 ';', ':', '4', '\\', '0', 'Z', '7', '(', 349 '_', '?', 'W', ']', '#', 'Y', ')', '=' 350 }; 351 (void) WriteBlobByte(image,iso_to_brf[cell]); 352 } 353 } 354 if (iso_11548_1 == 0) 355 (void) WriteBlobByte(image,'\n'); 356 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 357 image->rows); 358 if (status == MagickFalse) 359 break; 360 } 361 (void) CloseBlob(image); 362 return(MagickTrue); 363} 364