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