reference/ocr-new/RLEMap.cc
changeset 0 6b8091ca909a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reference/ocr-new/RLEMap.cc	Thu May 18 23:12:51 2006 +0200
@@ -0,0 +1,578 @@
+#include "system.h"
+#include "RLEMap.h"
+#include "RLEPair.h"
+#include "tcl_interface.h"
+#include "status_message.h"
+
+ /* *****************************************************************
+  * RLEMap.cc - Member functions for an RLEMap                      *
+  *         
+  *	RLEMap() - Constructor
+  *     ~RLEMap() - Destructor
+  *
+  *	int imageLength();
+  *	int imageWidth();
+  *	MapStatus & status;
+  *  
+  * Below is an index of the other functions and the files where they 
+  * appear.  
+  *
+  *   	MapStatus readMap(char * filename) - RLEMap_readMap.cc
+  *	MapStatus WriteMap(char * filename);
+  *
+  *	// Data Access and low level manipulation functions  
+  *     RLEPairs * row(int i) - Returns a pointer to the list of RLEPairs
+  *     for row i.                       
+  *     MapStatus setBit(Point point, Color clr);
+  *	Color readBit(Point point);
+  *
+  *
+   ***************************************************************/
+
+RLEMap::RLEMap()
+: fMapData(NULL), fImageLength(0), fImageWidth(0), fStatus(EMPTY)
+/*--------------------------------------------------------------
+Primary Function: Constructor
+Return Value: pointer to new RLEMap
+Effects: Initialize status to empty other values to zero
+Rev: 10/6/95  KM
+---------------------------------------------------------------*/
+{ }
+
+
+
+ RLEMap::~RLEMap()
+/*--------------------------------------------------------------
+Primary Purpose: destructor
+Effects: Deletes each row of RLEPairs then the array of rows
+Rev: 10/6/95   KM
+---------------------------------------------------------------*/
+{
+  if (fMapData != NULL)
+    {
+      int i;
+
+
+      // delete each row
+      for (i=0; i< fImageLength; i++)
+	  {
+	    delete fMapData[i];
+	  }
+      // delete array of rows
+        delete fMapData;   
+    }
+};
+
+int & RLEMap::imageLength()
+/*--------------------------------------------------------------
+Return Value: vertical length of image in pixels
+Constraints: readMap() must have been run and fStatus be VALID
+Rev: 10/6 KM
+---------------------------------------------------------------*/
+  {
+  return fImageLength;
+
+};
+
+
+int & RLEMap::imageWidth()
+/*--------------------------------------------------------------
+Return Value: horizontal width of image in pixels
+Constraints: readMap() must have been run and fStatus be valid
+Rev: 10/20 KM
+---------------------------------------------------------------*/
+{
+  return fImageWidth;
+
+}
+
+
+MapStatus & RLEMap::status()
+/*--------------------------------------------------------------
+Return Value: return reference to current status EMPTY, VALID etc..
+Rev: 10/6/95 KM
+---------------------------------------------------------------*/
+{
+  return fStatus;
+
+}
+
+
+
+RLEPairs *  RLEMap::operator [](int i)
+/*--------------------------------------------------------------
+Arguments: i is the row # of the RLEPair list to be returned
+Return Value: A pointer to the list of RLEPairs in row i
+Rev:  10/20/95 KM
+---------------------------------------------------------------*/
+{
+
+  return fMapData[i];
+}
+
+
+RLEPairs * RLEMap::row(int i)
+// Same as overloaded [] function above
+{
+  return fMapData[i];
+}
+
+
+
+MapStatus RLEMap::readMap(char * filename)
+/*--------------------------------------------------------------
+Primary Purpose: Read an RLEMap from a TIFF file
+Arguments: filename of TIFF file
+Return Value: A MapStatus, either VALID or READERROR
+Effects:
+  *  RLEMap::readMap(filename) will read a two level TIFF file
+  *  and place it in an RLEMap.  The private fields of the RLEMap
+  *  set are:
+         fImageWidth - the pixel width of the image
+	 fImageLength - the vertical pixel length of the image
+	 fstat - the status of the image VALID or READERROR
+         fMapData - an array of pointers to lists of RLEPairs
+Constraints: filename must be a two level TIFF file
+Rev: 10/20/95  Portions Borrowed from Assignment 1
+---------------------------------------------------------------*/
+{
+  TIFF *tif;
+  unsigned char * buf;
+  short photometric;
+
+  // Open File - Read length and width
+
+  tif = TIFFOpen (filename, "r");
+  if(tif == NULL)
+    return READERROR;
+
+  TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &fImageLength);
+  TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &fImageWidth);
+  TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photometric);
+  
+  printf("open succeeded on file %s.  length = %d. width = %d ",
+	 filename, fImageLength, fImageWidth);
+  if(photometric == PHOTOMETRIC_MINISWHITE)
+    printf("min-is-white format\n");
+  else if(photometric == PHOTOMETRIC_MINISBLACK )
+    printf("min-is-black format\n");
+  else
+    printf("with an unknown photometric: %d\n", photometric);
+
+  // allocate buffer and array for data
+  int numCharsInBuf = fImageWidth / 8  +1 ;
+  buf = new unsigned char[numCharsInBuf];
+  fMapData = new (RLEPairs*)[fImageLength+1]; 
+ 
+ for (int row = 0; row < fImageLength; ++row)
+    {
+      TIFFReadScanline(tif,buf,row,0);
+      if(photometric != PHOTOMETRIC_MINISWHITE)  /* invert anything except white */
+	invertBitsInBuffer(buf, numCharsInBuf);
+      if(row==0 || row == fImageLength -1)
+	clearBitsInBuffer(buf,numCharsInBuf);
+      // Create a list of RLEPairs for this row and fill with buffer data
+      fMapData[row] = new RLEPairs(row); 
+   	fMapData[row]->fill(buf, numCharsInBuf, row);
+    }
+
+ TIFFClose(tif);
+   
+  return VALID;
+}
+
+short int RLEMap::grayScale(Point ul, Point  lr)
+// Dummy function for now
+{
+   int numPixels = pixelsInRegion( ul, lr);
+   int area = (lr.x() - ul.x()+1) * (lr.y() - ul.y()+1);
+   if (area < numPixels) {
+     printf("Uh oh! Area = %d and pixels = %d\n", area, numPixels);
+     assert(area >= numPixels);
+   }
+   short int gscale =(short int)(((float)numPixels/area) * 255);
+   
+   return gscale;
+ }
+
+int RLEMap::pixelsInRegion(Point  ul, Point  lr)
+{
+  assert (ul >= Point(0,0));
+  assert (ul <= lr);
+  assert (lr <= Point(fImageWidth, fImageLength));
+
+  int ulx = ul.x(); int uly = ul.y();
+  int lrx = lr.x(); int lry = lr.y();
+  int numPixels = 0;
+  RLEPairs * curRow;
+
+  for (int r = uly; r <= lry; r++)
+    {
+      curRow = row(r);
+      numPixels += curRow->pixelsBetween(ulx, lrx);
+//      cout << curRow->pixelsBetween(ulx,lrx) <<" ";
+ //     cout << numPixels << endl;
+    }
+  
+  return numPixels;
+
+}
+
+ListElement*
+RLEMap::FindNearVertDot(int startCol, int endCol, int startRow, int endRow) 
+/*--------------------------------------------------------------
+Primary Purpose: Return closest interval to startRow within bounds of
+                 startCol and endRow in the direction of endRow. Finds
+                 closest dot vertically from startRow.
+Arguments: startRow is row to start from, startCol and endCol are
+           left and right boundaries of search. Search in the direction
+	   of endRow.
+Return Value: An RLE interval - pointer to a list element in RLEPairs 
+Effects:
+Constraints: startRow < endRow
+---------------------------------------------------------------*/
+{
+  ListElement* current;
+  if (startRow < endRow) {
+    for (int i = startRow+2; i <= endRow; i++) {
+      current = fMapData[i]->first;
+      while (current != NULL) {
+	if ((((RLEPair *) current->item)->start <= endCol)
+	    && (((RLEPair *) current->item)->end >= startCol))
+	  return current;
+	current = current->next;
+      }
+    }
+  } else {
+    for (int i = startRow-2; i >= endRow; i--) {
+      current = fMapData[i]->first;
+      while (current != NULL) {
+	if ((((RLEPair *) current->item)->start <= endCol)
+	    && (((RLEPair *) current->item)->end >= startCol))
+	  return current;
+	current = current->next;
+      }
+    }
+  }
+  return NULL;
+}
+
+
+
+
+
+ListElement*
+RLEMap::FindNearHorizDot(int startCol, int startRow, int endRow) 
+/*--------------------------------------------------------------
+Primary Purpose: Return closest interval to startCol within bounds of
+                 startRow and endRow (startRow is lower). Finds
+                 closest dot horizontally from startCol.
+Arguments: startCol is column to start from, startRow and endRow are
+           upper and lower boundaries of search
+Return Value: An RLE interval - pointer to a list element in RLEPairs 
+Effects:
+Constraints: startRow < endRow
+---------------------------------------------------------------*/
+{
+  ListElement* answer = NULL;
+  ListElement* current;
+  int closest = fImageWidth;
+
+  for (int i = startRow; i <= endRow; i++) {
+    current = fMapData[i]->first;
+    while ((current != NULL) && (((RLEPair *) current->item)->end 
+				 < startCol)) {
+      current = current->next;
+    }
+    if ((current != NULL) && (((RLEPair *) current->item)->start < closest)) {
+      answer = current;
+      closest = ((RLEPair *) answer->item)->start;
+    }
+  }
+  return answer;
+}
+
+
+
+
+void testRLEMap(char * filename)
+/*--------------------------------------------------------------
+Primary Purpose: Test the reading of tiff files into RLE format
+Effects:  Reads filename,  puts it into RLE format then prints
+Rev:  10/7/95 KM
+---------------------------------------------------------------*/
+{
+  RLEMap m;
+
+  m.readMap(filename);
+  if (m.imageLength() < 100)  printMap(&m);
+  testpixelsBetween(&m);   // In RLEPairs.cc - tests pixelsBetween function
+}
+
+
+void printMap(RLEMap * map)
+{
+  int startX = 0;
+  int endX = 0;
+  int pos;    
+  RLEPair * item;
+  RLEPairs * rowdata;
+
+  RLEMap & m = *map;
+
+  for (int r = 0; r < m.imageLength(); r++)
+    {
+      startX = 0;
+      endX = -1;
+      rowdata = m[r];
+
+      for (ListElement* ptr = rowdata->first; ptr != NULL; ptr = ptr->next) 
+	{
+	  item = (RLEPair *)(ptr->item);
+	  startX = item->start;	  
+	  for ( pos = endX+1; pos< startX; pos++)
+	  cout << " ";
+          endX = item->end;	  
+	  for ( pos = startX; pos <= endX; pos++)
+	    cout << "X";
+	}
+      cout << "" << endl;
+    }
+
+}
+
+void RLEMap::printPairs(int startRow, int endRow)
+/*--------------------------------------------------------------
+Primary Purpose: Prints RLE Pairs for this map from startRow to endRow  
+Rev:11/2 KM
+---------------------------------------------------------------*/
+{
+  int startX, endX;
+  RLEPair * item;
+  RLEPairs * rowdata;
+
+  RLEMap & m = *this;
+  cout << "printing rows " << startRow << " to " << endRow << endl;
+  for (int r = startRow; r <= endRow; r++)
+    {
+      rowdata = m[r];
+
+      cout << "row " << r << " ";
+
+      for (ListElement *ptr = rowdata->first; ptr != NULL; ptr = ptr->next) 
+	{
+	  item = (RLEPair *)(ptr->item);
+	  startX = item->start;	  
+	  endX = item->end;
+	  cout << "(" << startX << "," << endX <<")";
+	}
+      cout << endl;
+    }
+}
+
+void testpixelsBetween(RLEMap * map)
+// tests out a row by making sure that pixels between 
+// 0 and ImageWidth - 1 == pixels in sub ranges of 29 pixels
+// Test performed on center row.
+{
+  int start = 0;
+  int end = 28;
+
+  int pcount;
+  int sum = 0;
+  RLEPairs * pairs;
+  int row;
+
+  for (row = 0; row < map->imageLength(); row++)
+    {
+      pairs = (*map)[row];  
+      while (start <= map->imageWidth())
+	{
+	  pcount = pairs->pixelsBetween(start, end);
+//	  printf("row %d col %d to %d - %d pixels\n",row, start,end,pcount);
+	  sum += pcount;
+	  start +=29;
+	  end +=29;
+	}
+      if (sum !=0)
+	printf("row %d sum was %d , should be %d\n", row, sum, pairs->numPixels);
+      assert(sum == pairs->numPixels);
+      start = 0;
+      end = 28;
+      sum = 0;
+    }
+
+  delete pairs;
+}
+
+int RLEMap::deskew()
+/* going to be a (near-blind) steal from fateman */
+/*--------------------------------------------------------------
+Primary Purpose: deskewing an RLEMap
+Arguments: none 
+Return Value: 1 if the page is altered, 0 if not
+Effects: RLEMap is straightened out
+Constraints: RLE shouldn't be tilted too much (< 10deg)
+Rev: AR 11/1/95
+---------------------------------------------------------------*/
+{
+  double skew = -get_skew(this);  /* skew in rad */
+  if((skew >= MINIMUM_SKEW_ANGLE)||(skew <= - MINIMUM_SKEW_ANGLE))
+    {
+      double h = tan(skew / (180 / M_PI));  
+      if(h > 0)
+	  {
+	    tilt_and_slant(1/h, 1); /* clockwise */
+	    return 1;
+	  }
+      else if (h < 0)
+	  {
+	    tilt_and_slant(-(1/h), -1); /* counter clockwise */
+	    return 1;
+	  }
+      else
+	return 0;
+    }
+  else 
+    return 0;
+}
+
+#define DEBUG_TILT_AND_SLANT 1
+void RLEMap::tilt_and_slant(double step, int direction)
+/*--------------------------------------------------------------
+Primary Purpose: do the work of shifting the RLEMap
+Arguments: step--something about how many rows to go before shifting,
+           direction--counterclockwise or clockwise
+Return Value: none
+Effects: rotates the RLEMap some ammount by tilting the map slightly,
+        then slanting it. (duh). Not an exact rotation
+Constraints:
+Rev: AR 11/1/95
+---------------------------------------------------------------*/
+{
+  if(DEBUG_TILT_AND_SLANT)
+    printf("Call to tilt_and_slant: step = %lf, direction = %d\n ", step, direction);
+  if(direction > 0)
+    {
+      tilt(step, direction);  
+      slant(step, direction);
+    }
+  else
+    {
+      slant(step, -direction);
+      tilt(step, direction); 
+    }
+}     
+
+#define DEBUG_SLANT 1
+/*  "slant a picture by shifting lines horizontally 1 bit every step rows"
+  ;; dir 1 means shift to right as row number increases
+  ;; dir -1 means shift by left
+  ;; this does not rotate the picture, since rows are each unchanged.
+  ;; the effect of a positive direction, say (slantpic pic 3 3 1)
+  ;; is to "italicize".
+*/  
+void RLEMap::slant(double step, int direction)
+{
+  if(DEBUG_SLANT)
+    printf("Slant called, step = %lf, dir = %d\n", step, direction);
+  fImageWidth += (int)((double)fImageLength / (double)step);
+  int shift_amount = direction;
+  int num_steps = 1;
+  for(int i = 0; i < fImageLength; i++)
+      {
+	if(i > (num_steps*(int)step))  
+/* if we have gone through step rows, increment the shift */
+	    {
+	      shift_amount += direction;
+	      num_steps++;
+	    }
+/*	printf("Shifting row %d by %d\n", i, shift_amount);  */
+	fMapData[i]->shift(shift_amount);
+      }
+}
+
+
+void RLEMap::display_intervals(char* color)
+{
+  display_intervals(".main_window.display.work_space", SCALE_FACTOR, color);
+}
+
+void RLEMap::display_intervals(char* window, double scaleFactor, char * color)
+{
+  assert(scaleFactor > 0);
+  if(!DISPLAY_IMAGE)
+    return;
+  double skip;
+  last_status = 0.0;
+  printf("scaleFactor = %lf  ", scaleFactor);
+  skip = 1.0 / scaleFactor;
+  printf("Skip = %lf\n", skip);
+
+  /* delete any garbage hanging around */
+  docommand("%s delete all", window);
+
+  set_status("Displaying Image: 0%...");
+    for (int i = 0, j= 0; i < fImageLength;i= int(j * skip), j++)
+      {
+
+	set_display_status((int)(i*skip), fImageLength);
+	fMapData[i]->draw_pairs(window, scaleFactor,
+			      i, color, 1.0/skip);
+
+	
+      }
+   
+  last_status = 0.0;
+  update();
+  set_status("Displaying Image: Done");
+}
+
+void RLEMap::tilt(double step, int direction)
+{
+/*    printf("tilt called, step = %lf, dir = %d\n", step, direction); */
+  int old_height = fImageLength;
+  int new_height = /* ceiling */ (int)(((double)fImageWidth) / step) + old_height;
+  int delta = old_height - new_height;
+  RLEPairs ** new_data = new RLEPairs*[new_height];
+  for(int i = 0; i < new_height; i++)
+      {
+	new_data[i] = new RLEPairs(i);
+      }
+  for(int j = 0; j < old_height; j++)
+      {
+	tilt_row(j, delta, new_data, step, direction);
+      }
+  fMapData = new_data;  /* probably want to delete old data */
+  fImageLength = new_height;
+  display_intervals("black");
+}  
+
+
+void RLEMap::tilt_row(int old_row_index, int old_new_row_diff, RLEPairs** new_data, double step, int direction)
+{
+/*    printf("Tilt row called: old row = %d, row diff = %d, step = %lf, dir = %d\n", old_row_index, old_new_row_diff, step, direction); */
+
+  double cur_x = 0;  /* I don't know what will happen with negative rows */
+  double new_x;
+  int cur_y = old_row_index + (old_new_row_diff * direction);
+  
+  while(((new_x = cur_x + step) < fImageWidth) &&
+	(cur_y >= 0) && (cur_y < fImageLength))
+    {
+      RLEPairs* new_pairs;
+      new_pairs = (fMapData[old_row_index])->extract((int) cur_x, (int)new_x);
+      new_data[cur_y]->merge(new_pairs);
+      cur_x = new_x + 1;
+      cur_y += direction;
+    }
+}
+
+
+
+
+
+
+
+
+