Home | History | Annotate | Download | only in coders
      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