reference/ocr-new/RLEPair.cc
author viric@llimona
Thu, 18 May 2006 23:12:51 +0200
changeset 0 6b8091ca909a
permissions -rw-r--r--
Init from working directory of svn repository.

#include "system.h"
#include "tcl_interface.h"




/**** RLEPair.cc 
  Member functions for RLEPairs
  RLEPair functions defined in the function header
  rev 10/20 Kathey Marsden 
*/




RLEPairs::RLEPairs(int rownum)
:List()
{
  numPixels = 0;
  row = rownum;
}


RLEPairs::~RLEPairs()
{
  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
    if (ptr->item != NULL)
      delete (RLEPair *) (ptr->item);
     }

  while(!IsEmpty())
    Remove();
}

void RLEPairs::print_pairs()
{
  RLEPair* item;
  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
    item = (RLEPair *)(ptr->item);
    printf("(%d->%d)", item->start, item->end);
  }
  printf("\n");
}

void RLEPairs::draw_pairs(char * window, double scaleFactor,
			  int y_coord, char* color, double width)
{
  RLEPair* item;
  scale(y_coord,scaleFactor);
  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
    item = (RLEPair *)(ptr->item);
    int line_start = item->start;
    int line_end = item->end;
    scale(line_start,scaleFactor);
    scale(line_end, scaleFactor);
    if(width > 1)
      docommand("%s create line %d %d %d %d -fill %s -width %d", window, 
		line_start, y_coord, line_end, y_coord, color, (int)width);
    else
      docommand("%s create line %d %d %d %d -fill %s", window, line_start, 
		y_coord, line_end, y_coord, color);
  }
}

void RLEPairs::shift(int bits)
/*--------------------------------------------------------------
Primary Purpose: shift a row right by bits
Arguments: bits: the number of bits to shift by
Return Value: none
Effects: ...
Constraints:
Rev: 11/1 AR

Someone should write a macro for this for loop. . .
---------------------------------------------------------------*/
{
  RLEPair* item;
  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
	  item = (RLEPair *)(ptr->item);
	  item->start += bits;
	  item->end += bits;
	}
}

void RLEPairs::fill(unsigned char * contents, int contentsLength,
		    int contentsRow)
/*--------------------------------------------------------------
Primary Purpose:  Take the contents of a line scanned from a 
TIFF file and put it into this list of RLEPairs
Arguments: contents is the result of a TIFFReadScanline function
           contentsLength is the number of unsigned chars in contents
	   contentsRow is the Row that this interval belongs to
Effects: Scans contents and for each range of black pixels, adds
         an RLEPair to the list
Constraints:
Rev: 10/20 KM  
---------------------------------------------------------------*/
{
  if(contentsRow != row)
    printf("Warning: merging to %d what appears to belong at %d\n", row, contentsRow);

  bool inPair = FALSE;      // Flag set to TRUE when Run of black starts
  short int startCol =0;
  short int endCol = 0;
  short int curCol= 0;
  unsigned char nextChar;

// Deallocate old pairs
  for(ListElement *ptr = first; ptr != NULL; ptr = ptr->next)
    removeAt(ptr);

  for (int c = 0; c < contentsLength; c++)
    {
      nextChar = contents[c];


      if (nextChar == 255)
        {
	  endCol = c*8+7;
	  // If this is a new pair we also have to set  start col
	  if (!inPair)
	    {
	      startCol = c*8;
	      inPair = TRUE;
	    }
	}
      else if(nextChar == 0)
	{
	  if (inPair)
	    {
	      RLEPair * pair = new RLEPair(startCol,endCol, contentsRow);
	      Append(pair);
	      inPair = FALSE;
	      numPixels += endCol - startCol +1;
	    }
	}
      else {  // Start Shifting and look at each bit

	// high bit on left
	for (int i = 7; i >=0; i--)
	  {
	    curCol = 7 + c * 8 - i;
	    /*** Black Pixel handling  */
	    if ((nextChar>>i)&1)      // if this is a black pixel
	      {
		if (!inPair)   // If not in a Pair, Start of a new Pair
		  {
		    inPair = TRUE;
		    startCol = curCol;
		    endCol = curCol;
		  }
		else           // Extend current Pair
		  endCol = curCol;
	      }
	    /*** White Pixel Handling **/
	    else            // This is a white pixel
	      if (inPair)   // Close off the Pair add to the list 
		{
		  RLEPair * pair = new RLEPair(startCol,endCol, contentsRow);
		  Append(pair);
		  inPair = FALSE;
		  numPixels += endCol - startCol+1;
		}
	    // if not in pair just continue
	  }
      }
   }
}


#define DEBUG_PIXELS_BETWEEN 0
int RLEPairs::pixelsBetween(int startCol, int endCol)
/*--------------------------------------------------------------
Return Value:  Returns the number of black pixels between column 
               startCol and column endCol.
Constraints:  0 <= startCol < endCol;  endCol < imageWidth  of RLEMap
Rev: 10/20 KM
---------------------------------------------------------------*/
{
  if (DEBUG_PIXELS_BETWEEN)
      {
	printf("Call to pixels between: start = %d, finish = %d\n", startCol, endCol);
      }
/*  assert(startCol < endCol); */
  if(!(startCol < endCol))
      {
	printf("Warning, startcol %d not less then endcol %d (setting startcol = endcol)\n", startCol, endCol);
	startCol = endCol;
      }

  int count= 0;
  int pairStart;
  int pairEnd;
  RLEPair * item;

  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
	  item = (RLEPair *)(ptr->item);
      	  pairEnd = item->end;
          pairStart = item->start;
	  // Don't loop anymore if past endCol
	  if (pairStart > endCol) break; 
  
	    // range starts after this pair
	  if (pairEnd < startCol) ; // do nothing
	     // range starts and ends in this pair
	    else if (pairStart <= startCol && pairEnd >= endCol)
	      count += endCol - startCol +1;
	    // range starts in this pair but ends later
	    else if (pairStart <=  startCol && pairEnd <= endCol)
	      count += pairEnd - startCol + 1;
	    // range includes this whole pair
	    else if (pairStart >= startCol && pairEnd <= endCol)     
	      count += pairEnd - pairStart + 1;
	    // range ends in the middle of this pair
	    else 
	      count += endCol - pairStart + 1;

	  // printf(" %d , %d  - %d newcount\n", pairStart, pairEnd, count);
	  }
	    	  


  return count;

}


RLEPairs * RLEPairs::extract(int startCol, int endCol)
/*--------------------------------------------------------------
Primary Purpose: Makes a copy of a sectionn of this row
Arguments: startCol - starting column to extract
           endCol - ending column to extract
Return Value: a pointer to a new RLEPairs that has been
extracted from this.
Constraints: start <= first col of first pair 
             end <= ending col of lat pair
Rev:  KM 11/16
---------------------------------------------------------------*/
{

  int pairStart;
  int pairEnd;

  RLEPair * item;
  RLEPairs * returnPairs = new RLEPairs(row);



  for (ListElement *ptr = first; ptr != NULL; ptr = ptr->next) {
	  item = (RLEPair *)(ptr->item);
      	  pairEnd = item->end;
          pairStart = item->start;
	  row = item->row;

	  // Don't loop anymore if past endCol
	  if (pairStart > endCol) break; 
  
	    // range starts after this pair
	  if (pairEnd < startCol) ; // do nothing

	     // range starts and ends in this pair
	    else if (pairStart <= startCol && pairEnd >= endCol)
		{
          	 RLEPair * addpair = new RLEPair(startCol,endCol, row);
		 returnPairs->Append(addpair);
	       }
	    // range starts in this pair but ends later
	    else if (pairStart <=  startCol && pairEnd <= endCol)
		{
          	 RLEPair * addpair = new RLEPair(startCol,pairEnd, row);
		 returnPairs->Append(addpair);
	       }

	    // range includes this whole pair
	    else if (pairStart >= startCol && pairEnd <= endCol)     
		{
          	 RLEPair * addpair = new RLEPair(pairStart,pairEnd, row);
		 returnPairs->Append(addpair);
	       }
	    // range ends in the middle of this pair
	    else 
		{
          	 RLEPair * addpair = new RLEPair(pairStart,endCol, row);
		 returnPairs->Append(addpair);
	       }	    

	  }
/*  printf("Extract returning: ");
    returnPairs->print_pairs();  */
  return returnPairs;
}



void RLEPairs::merge(RLEPairs * pairs)
/*--------------------------------------------------------------
Primary Purpose: Inserts  the black regions of pairs into this.
Arguments: pairs - RLEPair list to be combined with this one.
Return Value: A new list that represtents merged data
Effects: Modifies this to add pairs. deallocates pairs.
Constraints:
Rev: 11/16/95
---------------------------------------------------------------*/
{
  if((!pairs) || (pairs->length == 0))
    return;

  int pairStart;
  int pairEnd;

  RLEPair * item;
  int lastCol =  ((RLEPair *) (last->item))->end;
  int lastColpairs =  ((RLEPair *) (pairs->last->item))->end;
  if (lastCol < lastColpairs)
     lastCol = lastColpairs;


  int numChars = lastCol/8 + 1;
  uchar buffer[numChars];
  for(int i = 0; i < numChars; i++) buffer[i] = 0;
  
  for (ListElement * ptr2 = pairs->first; ptr2 != NULL; ptr2 = ptr2->next) 
      {
	item = (RLEPair *)(ptr2->item);
	setRange(buffer,  item->start, item->end);
      }
  
  
  for (ListElement * ptr=first; ptr != NULL; ptr = ptr->next) 
	{
	  item = (RLEPair *)(ptr->item);
	  setRange(buffer,  item->start, item->end);
	}

  fill(buffer, numChars, row);

/*  printf("Merged to form: ");
    print_pairs(); */

}