reference/ocr-new/RLEMap.cc
changeset 0 6b8091ca909a
equal deleted inserted replaced
-1:000000000000 0:6b8091ca909a
       
     1 #include "system.h"
       
     2 #include "RLEMap.h"
       
     3 #include "RLEPair.h"
       
     4 #include "tcl_interface.h"
       
     5 #include "status_message.h"
       
     6 
       
     7  /* *****************************************************************
       
     8   * RLEMap.cc - Member functions for an RLEMap                      *
       
     9   *         
       
    10   *	RLEMap() - Constructor
       
    11   *     ~RLEMap() - Destructor
       
    12   *
       
    13   *	int imageLength();
       
    14   *	int imageWidth();
       
    15   *	MapStatus & status;
       
    16   *  
       
    17   * Below is an index of the other functions and the files where they 
       
    18   * appear.  
       
    19   *
       
    20   *   	MapStatus readMap(char * filename) - RLEMap_readMap.cc
       
    21   *	MapStatus WriteMap(char * filename);
       
    22   *
       
    23   *	// Data Access and low level manipulation functions  
       
    24   *     RLEPairs * row(int i) - Returns a pointer to the list of RLEPairs
       
    25   *     for row i.                       
       
    26   *     MapStatus setBit(Point point, Color clr);
       
    27   *	Color readBit(Point point);
       
    28   *
       
    29   *
       
    30    ***************************************************************/
       
    31 
       
    32 RLEMap::RLEMap()
       
    33 : fMapData(NULL), fImageLength(0), fImageWidth(0), fStatus(EMPTY)
       
    34 /*--------------------------------------------------------------
       
    35 Primary Function: Constructor
       
    36 Return Value: pointer to new RLEMap
       
    37 Effects: Initialize status to empty other values to zero
       
    38 Rev: 10/6/95  KM
       
    39 ---------------------------------------------------------------*/
       
    40 { }
       
    41 
       
    42 
       
    43 
       
    44  RLEMap::~RLEMap()
       
    45 /*--------------------------------------------------------------
       
    46 Primary Purpose: destructor
       
    47 Effects: Deletes each row of RLEPairs then the array of rows
       
    48 Rev: 10/6/95   KM
       
    49 ---------------------------------------------------------------*/
       
    50 {
       
    51   if (fMapData != NULL)
       
    52     {
       
    53       int i;
       
    54 
       
    55 
       
    56       // delete each row
       
    57       for (i=0; i< fImageLength; i++)
       
    58 	  {
       
    59 	    delete fMapData[i];
       
    60 	  }
       
    61       // delete array of rows
       
    62         delete fMapData;   
       
    63     }
       
    64 };
       
    65 
       
    66 int & RLEMap::imageLength()
       
    67 /*--------------------------------------------------------------
       
    68 Return Value: vertical length of image in pixels
       
    69 Constraints: readMap() must have been run and fStatus be VALID
       
    70 Rev: 10/6 KM
       
    71 ---------------------------------------------------------------*/
       
    72   {
       
    73   return fImageLength;
       
    74 
       
    75 };
       
    76 
       
    77 
       
    78 int & RLEMap::imageWidth()
       
    79 /*--------------------------------------------------------------
       
    80 Return Value: horizontal width of image in pixels
       
    81 Constraints: readMap() must have been run and fStatus be valid
       
    82 Rev: 10/20 KM
       
    83 ---------------------------------------------------------------*/
       
    84 {
       
    85   return fImageWidth;
       
    86 
       
    87 }
       
    88 
       
    89 
       
    90 MapStatus & RLEMap::status()
       
    91 /*--------------------------------------------------------------
       
    92 Return Value: return reference to current status EMPTY, VALID etc..
       
    93 Rev: 10/6/95 KM
       
    94 ---------------------------------------------------------------*/
       
    95 {
       
    96   return fStatus;
       
    97 
       
    98 }
       
    99 
       
   100 
       
   101 
       
   102 RLEPairs *  RLEMap::operator [](int i)
       
   103 /*--------------------------------------------------------------
       
   104 Arguments: i is the row # of the RLEPair list to be returned
       
   105 Return Value: A pointer to the list of RLEPairs in row i
       
   106 Rev:  10/20/95 KM
       
   107 ---------------------------------------------------------------*/
       
   108 {
       
   109 
       
   110   return fMapData[i];
       
   111 }
       
   112 
       
   113 
       
   114 RLEPairs * RLEMap::row(int i)
       
   115 // Same as overloaded [] function above
       
   116 {
       
   117   return fMapData[i];
       
   118 }
       
   119 
       
   120 
       
   121 
       
   122 MapStatus RLEMap::readMap(char * filename)
       
   123 /*--------------------------------------------------------------
       
   124 Primary Purpose: Read an RLEMap from a TIFF file
       
   125 Arguments: filename of TIFF file
       
   126 Return Value: A MapStatus, either VALID or READERROR
       
   127 Effects:
       
   128   *  RLEMap::readMap(filename) will read a two level TIFF file
       
   129   *  and place it in an RLEMap.  The private fields of the RLEMap
       
   130   *  set are:
       
   131          fImageWidth - the pixel width of the image
       
   132 	 fImageLength - the vertical pixel length of the image
       
   133 	 fstat - the status of the image VALID or READERROR
       
   134          fMapData - an array of pointers to lists of RLEPairs
       
   135 Constraints: filename must be a two level TIFF file
       
   136 Rev: 10/20/95  Portions Borrowed from Assignment 1
       
   137 ---------------------------------------------------------------*/
       
   138 {
       
   139   TIFF *tif;
       
   140   unsigned char * buf;
       
   141   short photometric;
       
   142 
       
   143   // Open File - Read length and width
       
   144 
       
   145   tif = TIFFOpen (filename, "r");
       
   146   if(tif == NULL)
       
   147     return READERROR;
       
   148 
       
   149   TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &fImageLength);
       
   150   TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &fImageWidth);
       
   151   TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric);
       
   152   
       
   153   printf("open succeeded on file %s.  length = %d. width = %d ",
       
   154 	 filename, fImageLength, fImageWidth);
       
   155   if(photometric == PHOTOMETRIC_MINISWHITE)
       
   156     printf("min-is-white format\n");
       
   157   else if(photometric == PHOTOMETRIC_MINISBLACK )
       
   158     printf("min-is-black format\n");
       
   159   else
       
   160     printf("with an unknown photometric: %d\n", photometric);
       
   161 
       
   162   // allocate buffer and array for data
       
   163   int numCharsInBuf = fImageWidth / 8  +1 ;
       
   164   buf = new unsigned char[numCharsInBuf];
       
   165   fMapData = new (RLEPairs*)[fImageLength+1]; 
       
   166  
       
   167  for (int row = 0; row < fImageLength; ++row)
       
   168     {
       
   169       TIFFReadScanline(tif,buf,row,0);
       
   170       if(photometric != PHOTOMETRIC_MINISWHITE)  /* invert anything except white */
       
   171 	invertBitsInBuffer(buf, numCharsInBuf);
       
   172       if(row==0 || row == fImageLength -1)
       
   173 	clearBitsInBuffer(buf,numCharsInBuf);
       
   174       // Create a list of RLEPairs for this row and fill with buffer data
       
   175       fMapData[row] = new RLEPairs(row); 
       
   176    	fMapData[row]->fill(buf, numCharsInBuf, row);
       
   177     }
       
   178 
       
   179  TIFFClose(tif);
       
   180    
       
   181   return VALID;
       
   182 }
       
   183 
       
   184 short int RLEMap::grayScale(Point ul, Point  lr)
       
   185 // Dummy function for now
       
   186 {
       
   187    int numPixels = pixelsInRegion( ul, lr);
       
   188    int area = (lr.x() - ul.x()+1) * (lr.y() - ul.y()+1);
       
   189    if (area < numPixels) {
       
   190      printf("Uh oh! Area = %d and pixels = %d\n", area, numPixels);
       
   191      assert(area >= numPixels);
       
   192    }
       
   193    short int gscale =(short int)(((float)numPixels/area) * 255);
       
   194    
       
   195    return gscale;
       
   196  }
       
   197 
       
   198 int RLEMap::pixelsInRegion(Point  ul, Point  lr)
       
   199 {
       
   200   assert (ul >= Point(0,0));
       
   201   assert (ul <= lr);
       
   202   assert (lr <= Point(fImageWidth, fImageLength));
       
   203 
       
   204   int ulx = ul.x(); int uly = ul.y();
       
   205   int lrx = lr.x(); int lry = lr.y();
       
   206   int numPixels = 0;
       
   207   RLEPairs * curRow;
       
   208 
       
   209   for (int r = uly; r <= lry; r++)
       
   210     {
       
   211       curRow = row(r);
       
   212       numPixels += curRow->pixelsBetween(ulx, lrx);
       
   213 //      cout << curRow->pixelsBetween(ulx,lrx) <<" ";
       
   214  //     cout << numPixels << endl;
       
   215     }
       
   216   
       
   217   return numPixels;
       
   218 
       
   219 }
       
   220 
       
   221 ListElement*
       
   222 RLEMap::FindNearVertDot(int startCol, int endCol, int startRow, int endRow) 
       
   223 /*--------------------------------------------------------------
       
   224 Primary Purpose: Return closest interval to startRow within bounds of
       
   225                  startCol and endRow in the direction of endRow. Finds
       
   226                  closest dot vertically from startRow.
       
   227 Arguments: startRow is row to start from, startCol and endCol are
       
   228            left and right boundaries of search. Search in the direction
       
   229 	   of endRow.
       
   230 Return Value: An RLE interval - pointer to a list element in RLEPairs 
       
   231 Effects:
       
   232 Constraints: startRow < endRow
       
   233 ---------------------------------------------------------------*/
       
   234 {
       
   235   ListElement* current;
       
   236   if (startRow < endRow) {
       
   237     for (int i = startRow+2; i <= endRow; i++) {
       
   238       current = fMapData[i]->first;
       
   239       while (current != NULL) {
       
   240 	if ((((RLEPair *) current->item)->start <= endCol)
       
   241 	    && (((RLEPair *) current->item)->end >= startCol))
       
   242 	  return current;
       
   243 	current = current->next;
       
   244       }
       
   245     }
       
   246   } else {
       
   247     for (int i = startRow-2; i >= endRow; i--) {
       
   248       current = fMapData[i]->first;
       
   249       while (current != NULL) {
       
   250 	if ((((RLEPair *) current->item)->start <= endCol)
       
   251 	    && (((RLEPair *) current->item)->end >= startCol))
       
   252 	  return current;
       
   253 	current = current->next;
       
   254       }
       
   255     }
       
   256   }
       
   257   return NULL;
       
   258 }
       
   259 
       
   260 
       
   261 
       
   262 
       
   263 
       
   264 ListElement*
       
   265 RLEMap::FindNearHorizDot(int startCol, int startRow, int endRow) 
       
   266 /*--------------------------------------------------------------
       
   267 Primary Purpose: Return closest interval to startCol within bounds of
       
   268                  startRow and endRow (startRow is lower). Finds
       
   269                  closest dot horizontally from startCol.
       
   270 Arguments: startCol is column to start from, startRow and endRow are
       
   271            upper and lower boundaries of search
       
   272 Return Value: An RLE interval - pointer to a list element in RLEPairs 
       
   273 Effects:
       
   274 Constraints: startRow < endRow
       
   275 ---------------------------------------------------------------*/
       
   276 {
       
   277   ListElement* answer = NULL;
       
   278   ListElement* current;
       
   279   int closest = fImageWidth;
       
   280 
       
   281   for (int i = startRow; i <= endRow; i++) {
       
   282     current = fMapData[i]->first;
       
   283     while ((current != NULL) && (((RLEPair *) current->item)->end 
       
   284 				 < startCol)) {
       
   285       current = current->next;
       
   286     }
       
   287     if ((current != NULL) && (((RLEPair *) current->item)->start < closest)) {
       
   288       answer = current;
       
   289       closest = ((RLEPair *) answer->item)->start;
       
   290     }
       
   291   }
       
   292   return answer;
       
   293 }
       
   294 
       
   295 
       
   296 
       
   297 
       
   298 void testRLEMap(char * filename)
       
   299 /*--------------------------------------------------------------
       
   300 Primary Purpose: Test the reading of tiff files into RLE format
       
   301 Effects:  Reads filename,  puts it into RLE format then prints
       
   302 Rev:  10/7/95 KM
       
   303 ---------------------------------------------------------------*/
       
   304 {
       
   305   RLEMap m;
       
   306 
       
   307   m.readMap(filename);
       
   308   if (m.imageLength() < 100)  printMap(&m);
       
   309   testpixelsBetween(&m);   // In RLEPairs.cc - tests pixelsBetween function
       
   310 }
       
   311 
       
   312 
       
   313 void printMap(RLEMap * map)
       
   314 {
       
   315   int startX = 0;
       
   316   int endX = 0;
       
   317   int pos;    
       
   318   RLEPair * item;
       
   319   RLEPairs * rowdata;
       
   320 
       
   321   RLEMap & m = *map;
       
   322 
       
   323   for (int r = 0; r < m.imageLength(); r++)
       
   324     {
       
   325       startX = 0;
       
   326       endX = -1;
       
   327       rowdata = m[r];
       
   328 
       
   329       for (ListElement* ptr = rowdata->first; ptr != NULL; ptr = ptr->next) 
       
   330 	{
       
   331 	  item = (RLEPair *)(ptr->item);
       
   332 	  startX = item->start;	  
       
   333 	  for ( pos = endX+1; pos< startX; pos++)
       
   334 	  cout << " ";
       
   335           endX = item->end;	  
       
   336 	  for ( pos = startX; pos <= endX; pos++)
       
   337 	    cout << "X";
       
   338 	}
       
   339       cout << "" << endl;
       
   340     }
       
   341 
       
   342 }
       
   343 
       
   344 void RLEMap::printPairs(int startRow, int endRow)
       
   345 /*--------------------------------------------------------------
       
   346 Primary Purpose: Prints RLE Pairs for this map from startRow to endRow  
       
   347 Rev:11/2 KM
       
   348 ---------------------------------------------------------------*/
       
   349 {
       
   350   int startX, endX;
       
   351   RLEPair * item;
       
   352   RLEPairs * rowdata;
       
   353 
       
   354   RLEMap & m = *this;
       
   355   cout << "printing rows " << startRow << " to " << endRow << endl;
       
   356   for (int r = startRow; r <= endRow; r++)
       
   357     {
       
   358       rowdata = m[r];
       
   359 
       
   360       cout << "row " << r << " ";
       
   361 
       
   362       for (ListElement *ptr = rowdata->first; ptr != NULL; ptr = ptr->next) 
       
   363 	{
       
   364 	  item = (RLEPair *)(ptr->item);
       
   365 	  startX = item->start;	  
       
   366 	  endX = item->end;
       
   367 	  cout << "(" << startX << "," << endX <<")";
       
   368 	}
       
   369       cout << endl;
       
   370     }
       
   371 }
       
   372 
       
   373 void testpixelsBetween(RLEMap * map)
       
   374 // tests out a row by making sure that pixels between 
       
   375 // 0 and ImageWidth - 1 == pixels in sub ranges of 29 pixels
       
   376 // Test performed on center row.
       
   377 {
       
   378   int start = 0;
       
   379   int end = 28;
       
   380 
       
   381   int pcount;
       
   382   int sum = 0;
       
   383   RLEPairs * pairs;
       
   384   int row;
       
   385 
       
   386   for (row = 0; row < map->imageLength(); row++)
       
   387     {
       
   388       pairs = (*map)[row];  
       
   389       while (start <= map->imageWidth())
       
   390 	{
       
   391 	  pcount = pairs->pixelsBetween(start, end);
       
   392 //	  printf("row %d col %d to %d - %d pixels\n",row, start,end,pcount);
       
   393 	  sum += pcount;
       
   394 	  start +=29;
       
   395 	  end +=29;
       
   396 	}
       
   397       if (sum !=0)
       
   398 	printf("row %d sum was %d , should be %d\n", row, sum, pairs->numPixels);
       
   399       assert(sum == pairs->numPixels);
       
   400       start = 0;
       
   401       end = 28;
       
   402       sum = 0;
       
   403     }
       
   404 
       
   405   delete pairs;
       
   406 }
       
   407 
       
   408 int RLEMap::deskew()
       
   409 /* going to be a (near-blind) steal from fateman */
       
   410 /*--------------------------------------------------------------
       
   411 Primary Purpose: deskewing an RLEMap
       
   412 Arguments: none 
       
   413 Return Value: 1 if the page is altered, 0 if not
       
   414 Effects: RLEMap is straightened out
       
   415 Constraints: RLE shouldn't be tilted too much (< 10deg)
       
   416 Rev: AR 11/1/95
       
   417 ---------------------------------------------------------------*/
       
   418 {
       
   419   double skew = -get_skew(this);  /* skew in rad */
       
   420   if((skew >= MINIMUM_SKEW_ANGLE)||(skew <= - MINIMUM_SKEW_ANGLE))
       
   421     {
       
   422       double h = tan(skew / (180 / M_PI));  
       
   423       if(h > 0)
       
   424 	  {
       
   425 	    tilt_and_slant(1/h, 1); /* clockwise */
       
   426 	    return 1;
       
   427 	  }
       
   428       else if (h < 0)
       
   429 	  {
       
   430 	    tilt_and_slant(-(1/h), -1); /* counter clockwise */
       
   431 	    return 1;
       
   432 	  }
       
   433       else
       
   434 	return 0;
       
   435     }
       
   436   else 
       
   437     return 0;
       
   438 }
       
   439 
       
   440 #define DEBUG_TILT_AND_SLANT 1
       
   441 void RLEMap::tilt_and_slant(double step, int direction)
       
   442 /*--------------------------------------------------------------
       
   443 Primary Purpose: do the work of shifting the RLEMap
       
   444 Arguments: step--something about how many rows to go before shifting,
       
   445            direction--counterclockwise or clockwise
       
   446 Return Value: none
       
   447 Effects: rotates the RLEMap some ammount by tilting the map slightly,
       
   448         then slanting it. (duh). Not an exact rotation
       
   449 Constraints:
       
   450 Rev: AR 11/1/95
       
   451 ---------------------------------------------------------------*/
       
   452 {
       
   453   if(DEBUG_TILT_AND_SLANT)
       
   454     printf("Call to tilt_and_slant: step = %lf, direction = %d\n ", step, direction);
       
   455   if(direction > 0)
       
   456     {
       
   457       tilt(step, direction);  
       
   458       slant(step, direction);
       
   459     }
       
   460   else
       
   461     {
       
   462       slant(step, -direction);
       
   463       tilt(step, direction); 
       
   464     }
       
   465 }     
       
   466 
       
   467 #define DEBUG_SLANT 1
       
   468 /*  "slant a picture by shifting lines horizontally 1 bit every step rows"
       
   469   ;; dir 1 means shift to right as row number increases
       
   470   ;; dir -1 means shift by left
       
   471   ;; this does not rotate the picture, since rows are each unchanged.
       
   472   ;; the effect of a positive direction, say (slantpic pic 3 3 1)
       
   473   ;; is to "italicize".
       
   474 */  
       
   475 void RLEMap::slant(double step, int direction)
       
   476 {
       
   477   if(DEBUG_SLANT)
       
   478     printf("Slant called, step = %lf, dir = %d\n", step, direction);
       
   479   fImageWidth += (int)((double)fImageLength / (double)step);
       
   480   int shift_amount = direction;
       
   481   int num_steps = 1;
       
   482   for(int i = 0; i < fImageLength; i++)
       
   483       {
       
   484 	if(i > (num_steps*(int)step))  
       
   485 /* if we have gone through step rows, increment the shift */
       
   486 	    {
       
   487 	      shift_amount += direction;
       
   488 	      num_steps++;
       
   489 	    }
       
   490 /*	printf("Shifting row %d by %d\n", i, shift_amount);  */
       
   491 	fMapData[i]->shift(shift_amount);
       
   492       }
       
   493 }
       
   494 
       
   495 
       
   496 void RLEMap::display_intervals(char* color)
       
   497 {
       
   498   display_intervals(".main_window.display.work_space", SCALE_FACTOR, color);
       
   499 }
       
   500 
       
   501 void RLEMap::display_intervals(char* window, double scaleFactor, char * color)
       
   502 {
       
   503   assert(scaleFactor > 0);
       
   504   if(!DISPLAY_IMAGE)
       
   505     return;
       
   506   double skip;
       
   507   last_status = 0.0;
       
   508   printf("scaleFactor = %lf  ", scaleFactor);
       
   509   skip = 1.0 / scaleFactor;
       
   510   printf("Skip = %lf\n", skip);
       
   511 
       
   512   /* delete any garbage hanging around */
       
   513   docommand("%s delete all", window);
       
   514 
       
   515   set_status("Displaying Image: 0%...");
       
   516     for (int i = 0, j= 0; i < fImageLength;i= int(j * skip), j++)
       
   517       {
       
   518 
       
   519 	set_display_status((int)(i*skip), fImageLength);
       
   520 	fMapData[i]->draw_pairs(window, scaleFactor,
       
   521 			      i, color, 1.0/skip);
       
   522 
       
   523 	
       
   524       }
       
   525    
       
   526   last_status = 0.0;
       
   527   update();
       
   528   set_status("Displaying Image: Done");
       
   529 }
       
   530 
       
   531 void RLEMap::tilt(double step, int direction)
       
   532 {
       
   533 /*    printf("tilt called, step = %lf, dir = %d\n", step, direction); */
       
   534   int old_height = fImageLength;
       
   535   int new_height = /* ceiling */ (int)(((double)fImageWidth) / step) + old_height;
       
   536   int delta = old_height - new_height;
       
   537   RLEPairs ** new_data = new RLEPairs*[new_height];
       
   538   for(int i = 0; i < new_height; i++)
       
   539       {
       
   540 	new_data[i] = new RLEPairs(i);
       
   541       }
       
   542   for(int j = 0; j < old_height; j++)
       
   543       {
       
   544 	tilt_row(j, delta, new_data, step, direction);
       
   545       }
       
   546   fMapData = new_data;  /* probably want to delete old data */
       
   547   fImageLength = new_height;
       
   548   display_intervals("black");
       
   549 }  
       
   550 
       
   551 
       
   552 void RLEMap::tilt_row(int old_row_index, int old_new_row_diff, RLEPairs** new_data, double step, int direction)
       
   553 {
       
   554 /*    printf("Tilt row called: old row = %d, row diff = %d, step = %lf, dir = %d\n", old_row_index, old_new_row_diff, step, direction); */
       
   555 
       
   556   double cur_x = 0;  /* I don't know what will happen with negative rows */
       
   557   double new_x;
       
   558   int cur_y = old_row_index + (old_new_row_diff * direction);
       
   559   
       
   560   while(((new_x = cur_x + step) < fImageWidth) &&
       
   561 	(cur_y >= 0) && (cur_y < fImageLength))
       
   562     {
       
   563       RLEPairs* new_pairs;
       
   564       new_pairs = (fMapData[old_row_index])->extract((int) cur_x, (int)new_x);
       
   565       new_data[cur_y]->merge(new_pairs);
       
   566       cur_x = new_x + 1;
       
   567       cur_y += direction;
       
   568     }
       
   569 }
       
   570 
       
   571 
       
   572 
       
   573 
       
   574 
       
   575 
       
   576 
       
   577 
       
   578