reference/ocr-simple/BitMap.cc
changeset 0 6b8091ca909a
equal deleted inserted replaced
-1:000000000000 0:6b8091ca909a
       
     1  /* *****************************************************************
       
     2   * BitMap.cc - Member functions for a BitMap                      *
       
     3   *  because of the complexity of the many Bit functions, they are  *
       
     4   *  not all in this file.  In this file are only the following     *
       
     5   *  functions:
       
     6   *         
       
     7   *	BitMap() - Constructor
       
     8   *     ~BitMap() - Destructor
       
     9   *
       
    10   *	int imageLength();
       
    11   *	int imageWidth();
       
    12   *	MapStatus & status;
       
    13   *   	MapStatus readMap(char * filename) ;
       
    14   *	MapStatus writeMap(char * filename);
       
    15   *
       
    16   *	// Data Access and low level manipulation functions  
       
    17   *      uchar * row(int i) - Returns a pointer to row i    
       
    18   *	 MapStatus setBit(Point point, Color clr);
       
    19   *	 Color readBit(Point point);
       
    20   *
       
    21   *
       
    22    ***************************************************************/
       
    23 
       
    24 #include "BitMap.h"
       
    25 #include <iostream.h>
       
    26 #include <stdio.h>
       
    27 #include "status_message.h"
       
    28 
       
    29 inline int set_pixel_value(uchar** new_data, int y, int x, int new_val)
       
    30 {
       
    31   new_data[y][x/8] |= (uchar)(new_val << (7-(x%8)));
       
    32 }
       
    33 
       
    34 inline int get_pixel_value(uchar** data, int y, int x)
       
    35 {
       
    36   if((data[y][x/8]) & (1 << (7 - (x%8))))
       
    37     return 1;
       
    38   else
       
    39     return 0;
       
    40 }
       
    41 
       
    42 
       
    43 BitMap::BitMap()
       
    44 :fImageWidth(0), fImageLength(0), fStatus(EMPTY), fMapData(NULL)
       
    45 /*--------------------------------------------------------------
       
    46 Primary Function: Constructor
       
    47 Return Value: pointer to new BitMap
       
    48 Effects: Initialize status to empty other values to zero
       
    49 Rev: 10/6/95  KM
       
    50 ---------------------------------------------------------------*/
       
    51 { };
       
    52 
       
    53 
       
    54 
       
    55  BitMap::~BitMap()
       
    56 /*--------------------------------------------------------------
       
    57 Primary Purpose: destructor
       
    58 Effects: Deletes each row of BitPairs then the array of rows
       
    59 Rev: 10/6/95   KM
       
    60 ---------------------------------------------------------------*/
       
    61 {
       
    62   if (fMapData != NULL)
       
    63     {
       
    64       int i;
       
    65 
       
    66       // delete each row
       
    67       for (i=0; i< fImageLength; i++)
       
    68 	delete fMapData[i];
       
    69 
       
    70       // delete array of rows
       
    71         delete fMapData;   
       
    72     }
       
    73 };
       
    74 
       
    75 
       
    76 
       
    77 uchar * BitMap::row(int i)
       
    78 /*--------------------------------------------------------------
       
    79 Primary Purpose:  Access a row of the BitMap
       
    80 Arguments: i is the row to access
       
    81 Constraints:  i < fImageLength
       
    82 Rev:  KM 10/15
       
    83 ---------------------------------------------------------------*/
       
    84 {
       
    85   return fMapData[i];
       
    86 
       
    87 };
       
    88 
       
    89 
       
    90 
       
    91 MapStatus BitMap::readMap(char * filename)
       
    92 /*--------------------------------------------------------------
       
    93 Primary Purpose: Read an BitMap from a TIFF file
       
    94 Arguments: filename of TIFF file
       
    95 Return Value: A MapStatus, either VALID or READERROR
       
    96 Effects:
       
    97   *  BitMap::readMap(filename) will read a two level TIFF file
       
    98   *  and place it in an BitMap.  The private fields of the BitMap
       
    99   *  set are:
       
   100          fImageWidth - the pixel width of the image
       
   101 	 fImageLength - the vertical pixel length of the image
       
   102 	 fstat - the status after the Read VALID, OTHERERROR,READERROR
       
   103          fMapData - an array of pointers to uchar arrays/
       
   104 Constraints: filename must be a two level TIFF file
       
   105 Rev: 10/15/95  KM Portions Borrowed from Assignment 1
       
   106 ---------------------------------------------------------------*/
       
   107 {
       
   108   TIFF *tif;
       
   109   short photometric;
       
   110 
       
   111   // Open File - Read length and width
       
   112 
       
   113   tif = TIFFOpen (filename, "r");
       
   114   if(tif == NULL)
       
   115     { fStatus= OPENERROR;
       
   116       return OPENERROR;
       
   117     }
       
   118 
       
   119   TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &fImageLength);
       
   120   TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &fImageWidth);
       
   121   TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric);
       
   122   
       
   123   fMapData = new (uchar *)[fImageLength];
       
   124 
       
   125   printf("open succeeded on file %s.  length = %d. width = %d\n",
       
   126 	 filename, fImageLength, fImageWidth);
       
   127   /*  if(photometric == PHOTOMETRIC_MINISWHITE)
       
   128        printf("min-is-white format\n");
       
   129   else if(photometric == PHOTOMETRIC_MINISBLACK )
       
   130     printf("min-is-black format\n"); */
       
   131 
       
   132   if((photometric != PHOTOMETRIC_MINISWHITE) && 
       
   133      (photometric != PHOTOMETRIC_MINISBLACK))
       
   134     printf("with an unknown(!) photometric: %d\n", photometric);
       
   135   
       
   136   // Calculate number of chars in a row
       
   137   int numChars = (fImageWidth / 8 ) +1 ;
       
   138   if(ENABLE_USER_INTERFACE)
       
   139     set_status("Reading %s...", filename);
       
   140   last_status = 0.0;
       
   141 
       
   142   for (int row = 0; row < fImageLength; ++row)
       
   143     {
       
   144       if(ENABLE_USER_INTERFACE)
       
   145 	set_read_status(row, fImageLength);
       
   146       fMapData[row] = new uchar[numChars];        
       
   147       fMapData[row][numChars - 1] = 0;
       
   148       TIFFReadScanline(tif,fMapData[row],row,0);
       
   149       if(photometric != PHOTOMETRIC_MINISWHITE)
       
   150 	invertBitsInBuffer(fMapData[row], numChars);
       
   151 
       
   152     }
       
   153   last_status = 0.0;
       
   154   if(ENABLE_USER_INTERFACE)
       
   155     set_status("Done reading %s", filename);
       
   156   TIFFClose(tif);
       
   157   fStatus = VALID; 
       
   158   return VALID;
       
   159 
       
   160 };
       
   161 
       
   162 
       
   163 MapStatus BitMap::writeTclMap(char * filename, 
       
   164 			      Point & ul, Point & lr, int scaledown)
       
   165 {
       
   166   FILE *  outfile;
       
   167   int numChars= fImageWidth /8 + 1;
       
   168   outfile = fopen(filename, "w");
       
   169 
       
   170   if(!outfile)
       
   171     cout << " Could not open " << filename << endl;
       
   172    
       
   173   fprintf(outfile, "%s_width %d\n",filename,fImageWidth);
       
   174   fprintf(outfile, "%s_height %d\n",filename,fImageLength);
       
   175   fprintf(outfile, "static char %s_bits[] {\n",filename);
       
   176 
       
   177   
       
   178   for (int r = 0; r < fImageLength; r++)
       
   179       {
       
   180 	for(int col=0; col < numChars; col++)
       
   181 	    {
       
   182 	      fprintf(outfile, "%4#x,", fMapData[r][col]);
       
   183 
       
   184 	      if (!(r == fImageLength-1 && col == numChars-1))
       
   185 		fprintf(outfile, " ,");
       
   186 
       
   187 	      if (((r*numChars + col) % 15)==0)
       
   188 		fprintf(outfile,"\n");
       
   189 	    }
       
   190 
       
   191       }
       
   192   fprintf(outfile,"}\n");
       
   193 
       
   194   fclose(outfile);
       
   195 
       
   196 }
       
   197 
       
   198 
       
   199 
       
   200 short int BitMap::grayScale(Point & ul, Point & lr)
       
   201 // Dummy function for now
       
   202 {
       
   203    int numPixels = pixelsInRegion( ul, lr);
       
   204    int area = (lr.x() - ul.x()+1) * (lr.y() - ul.y()+1);
       
   205    if (area < numPixels) {
       
   206      printf("Uh oh! Area = %d and pixels = %d\n", area, numPixels);
       
   207      assert(area >= numPixels);
       
   208    }
       
   209    short int gscale =(short int)(((float)numPixels/area) * 255);
       
   210    
       
   211    return gscale;
       
   212  };
       
   213 
       
   214 
       
   215 
       
   216 int BitMap::pixelsInRegion( Point  ul,  Point lr)
       
   217 {
       
   218   assert (ul >= Point(0,0));  /* did someone overload these? */
       
   219   if (!(lr <= Point(fImageWidth, fImageLength))) 
       
   220        printf("problem\n");
       
   221   assert (lr <= Point(fImageWidth, fImageLength));
       
   222 
       
   223   if(ul > lr)return 0;
       
   224 
       
   225   int ulx = ul.x(); int uly = ul.y();
       
   226   int lrx = lr.x(); int lry = lr.y();
       
   227   uchar * curRow;
       
   228   int pixCount = 0;
       
   229   
       
   230 
       
   231   for(int r = uly; r <= lry; r++)
       
   232     {
       
   233       curRow = row(r);
       
   234       // Count middle (whole) characters
       
   235       pixCount += pixelsBetween(curRow, ulx, lrx);
       
   236 //      cout << pixelsBetween(curRow,ulx,lrx) <<" ";
       
   237 //      cout << pixCount << endl;
       
   238 
       
   239     }
       
   240   return pixCount;
       
   241 };
       
   242 
       
   243 
       
   244 void testBitMap(char * filename)
       
   245 // Reads in BitMap and prints on screen
       
   246 {
       
   247     BitMap * m = new BitMap;
       
   248     
       
   249     m->readMap(filename);
       
   250     int numChars = (m->imageWidth() / 8 )+ 1;
       
   251 
       
   252     for (int r = 0; r < m->imageLength(); r++){
       
   253       for (int c =0; c < numChars; c++) byteprint(m->row(r)[c]);
       
   254     printf( "\n");
       
   255   }
       
   256 
       
   257 };
       
   258 
       
   259 
       
   260 void byteprint(char d) // print bits in a byte, high bit on left
       
   261 {
       
   262   for (int i= 7; i>=0; --i) {
       
   263     if ((d>>i)&1) printf("X");
       
   264     else printf(" ");
       
   265   } 
       
   266 };
       
   267 
       
   268 void bitprint(char d, int x)
       
   269 {
       
   270   if ((d>>(7-x))&1) cout << "X";
       
   271   else cout << " ";
       
   272 };
       
   273 
       
   274 
       
   275 class Page;
       
   276 
       
   277 void testPixelsInRegion(BitMap * bmap, RLEMap * rmap)
       
   278 // Reads in file and compares pixelsInRegion to RLEVersion
       
   279 {
       
   280 
       
   281   int bmapcnt, rmapcnt;
       
   282 
       
   283   cout << "Testing pixelsInRegion " << endl;
       
   284   
       
   285    bmapcnt = bmap->pixelsInRegion(Point(0,0), 
       
   286 		Point(bmap->imageWidth()-1, bmap->imageLength()-1));
       
   287 
       
   288    rmapcnt = rmap->pixelsInRegion(Point(0,0), 
       
   289 	 Point(rmap->imageWidth()-1, rmap->imageLength()-1));				     
       
   290 				     
       
   291   cout << "For whole page:";
       
   292   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   293 
       
   294   cout << "Start on char edge end on edge (8,8) (16,21) ";  
       
   295    bmapcnt = bmap->pixelsInRegion(Point(8,8), Point(16,21));
       
   296    rmapcnt = rmap->pixelsInRegion(Point(8,8), Point(16,21));
       
   297   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   298 
       
   299   cout << "Start on char edge, end mid char (0,8) (50,21)";
       
   300    bmapcnt = bmap->pixelsInRegion(Point(0,8), Point(50,21));
       
   301    rmapcnt = rmap->pixelsInRegion(Point(0,8), Point(50,21));
       
   302   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   303 
       
   304   cout << "Start mid char, end on edge (2,8) (7,21)";
       
   305    bmapcnt = bmap->pixelsInRegion(Point(2,8), Point(7,21));
       
   306    rmapcnt = rmap->pixelsInRegion(Point(2,8), Point(7,21));
       
   307   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   308 
       
   309   cout << "Start mid char, end mid char (2,8) (9,21)";
       
   310    bmapcnt = bmap->pixelsInRegion(Point(2,8), Point(9,21));
       
   311    rmapcnt = rmap->pixelsInRegion(Point(2,8), Point(9,21));
       
   312   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   313 
       
   314   cout << "Start and, end same char (2,8) (4,21)";
       
   315    bmapcnt = bmap->pixelsInRegion(Point(2,4), Point(4,21));
       
   316    rmapcnt = rmap->pixelsInRegion(Point(2,4), Point(4,21));
       
   317   cout <<" Bitmap-" << bmapcnt << " RLEMap-" << rmapcnt << endl;
       
   318 
       
   319 };
       
   320 
       
   321 MapStatus BitMap::rotateMap(Angle angle) 
       
   322 /* 
       
   323    Thanks to Clint Staley and S. Jacques @calpoly 
       
   324    for this bitmap rotation alg.
       
   325 
       
   326    copied and slightly modified since it wass a pain getting
       
   327    the RLE rotate to work and I think this might be decently
       
   328    fast -AR
       
   329 */
       
   330 {
       
   331   int nx,ny,newheight,newwidth,oldheight,oldwidth,i,j,halfnewheight,halfnewwidth;
       
   332   int halfoldheight,halfoldwidth;
       
   333   double radians; 
       
   334   double cosval,sinval;
       
   335   uchar** newMapData;
       
   336   
       
   337   fprintf(stderr,"Rotating Image %lf Degrees\n",angle);
       
   338   radians =  -(angle) / ((180 / 3.142));
       
   339   cosval = cos(radians);
       
   340   sinval = sin(radians);
       
   341 
       
   342   oldheight = fImageLength;
       
   343   oldwidth = fImageWidth;
       
   344   
       
   345   newwidth = (int)abs((int)(oldwidth*cosval)) + (int)abs((int)(oldheight*sinval));
       
   346   newheight = (int)abs((int)(-oldwidth*sinval)) + (int)abs((int)(oldheight*cosval));
       
   347 
       
   348   halfnewheight = newheight / 2;
       
   349   halfnewwidth = newwidth / 2;
       
   350   halfoldwidth = oldwidth /2;
       
   351   halfoldheight = oldheight /2 ;
       
   352   
       
   353   newMapData = new (uchar*) [newheight];
       
   354 
       
   355   int num_chars = (newwidth / 8) + 1;
       
   356   
       
   357   for (int row = 0; row < newheight; ++row)
       
   358       {
       
   359 	newMapData[row] = new uchar[num_chars];        
       
   360 	for (int k = 0; k < num_chars; k++)
       
   361 	  newMapData[row][k] = '\0';
       
   362       }
       
   363 
       
   364   last_status = 0.0;
       
   365   for(i=0;i < newheight;i++)
       
   366       {
       
   367 	if(ENABLE_USER_INTERFACE)
       
   368 	  set_rotation_status((int)i, (int)newheight);
       
   369 	for(j=0;j < newwidth;j++)
       
   370 	    {
       
   371 	     
       
   372 /*	      set_pixel_value(newMapData, i, j, 0); 
       
   373 	      break;  */
       
   374 
       
   375 	      nx =(int)( (j - halfnewwidth)*cosval + (i-halfnewheight)*sinval);
       
   376 	      ny =(int)( -((j - halfnewwidth)*sinval) + (i - halfnewheight)*cosval);
       
   377 	      nx = nx + halfoldwidth;
       
   378 	      ny = ny + halfoldheight;
       
   379 	      if ((nx < oldwidth) && (ny < oldheight) && (nx > 0) && (ny > 0))
       
   380 		{
       
   381 		  if(get_pixel_value(fMapData, ny, nx))
       
   382 		    set_pixel_value(newMapData, i, j, 1);
       
   383 		  else
       
   384 		    set_pixel_value(newMapData, i, j, 0);
       
   385 		}
       
   386 	      else
       
   387 		  {
       
   388 		    set_pixel_value(newMapData, i, j, 0);		
       
   389 		  }
       
   390 	    }
       
   391       }
       
   392   if(ENABLE_USER_INTERFACE)
       
   393     set_status("Rotating Image: Done");
       
   394   last_status = 0.0;
       
   395 
       
   396 /* free up the old storage */  
       
   397   for(i = 0; i < fImageLength; i++)
       
   398       {
       
   399 	free(fMapData[i]);
       
   400       }
       
   401   free(fMapData);
       
   402 
       
   403 /* assign pointer, etc to the new stuff */
       
   404   fMapData = newMapData;
       
   405   fImageLength = newheight;
       
   406   fImageWidth = newwidth;
       
   407 }
       
   408 
       
   409 /*
       
   410 				
       
   411 int set_pixel_value(uchar** new_data, int y, int x, int new_val)
       
   412 {
       
   413   new_data[y][x/8] |= (uchar)(new_val << (7-(x%8)));
       
   414 }
       
   415 
       
   416 int get_pixel_value(uchar** data, int y, int x)
       
   417 {
       
   418   if((data[y][x/8]) & (1 << (7 - (x%8))))
       
   419     return 1;
       
   420   else
       
   421     return 0;
       
   422 }
       
   423 
       
   424 */  
       
   425 
       
   426 
       
   427 
       
   428 
       
   429 
       
   430 
       
   431 
       
   432 
       
   433