Page.cc
author viric <viriketo@gmail.com>
Sun, 24 Apr 2011 18:25:11 +0200
changeset 1 a573dab6cb46
parent 0 6b8091ca909a
permissions -rw-r--r--
Afegeixo el Makefile.am que falta.

#include "Page.h" // Inclou pam.h
#include "Bitmap.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "Errors.h"

Page::Page(const char *filename)
{
	map = NULL;
	hist = NULL;
	text = NULL;
	readMap(filename);
}

Page::~Page()
{
	delete map;
}

void Page::readMap(const char *filename)
{
	FILE *fp;
	int i,j;
	char *image; // FIXME: Good type
	tuple *tuplerow;

	if (!strcmp(filename, "-"))
		fp = stdin;
	else
		// FIXME: exception
		
		if(!(fp = fopen(filename,"r")))
			Errors::Fatal("Cannot open filename.");

	// Si existia un mapa, el borrem.
	if(map != NULL)
		delete map;

	pnm_readpaminit(fp, &pamImage, sizeof(pamImage));
	// FIXME: Read ok

	width = pamImage.width;
	height = pamImage.height;

	map = new Bitmap(width,height);
	tuplerow = pnm_allocpamrow(&pamImage);


	for (i=0; i<height; i++)
	{
		pnm_readpamrow(&pamImage, tuplerow);
		for (j=0; j<width; j++)
		{
			// We only read the first sample (changing 0 and 1)
			map->pixels[i][j] = tuplerow[j][0]?0:1;
		}
	}
	pnm_freepamrow(tuplerow);

	fclose(fp);
}

void Page::writeMap(const char *filename) const
{
	pam outpam;
	FILE *fp;
	tuple *tuplerow;
	int i,j;

	outpam = pamImage;
	outpam.width = width;
	outpam.height = height;
	
	fprintf(stderr,"Writting %s: w:%i,h:%i\n", filename, width, height);

	if (!strcmp(filename, "-"))
		fp = stdout;
	else
		// FIXME: exception
		
		if(!(fp = fopen(filename,"w")))
			Errors::Fatal("Cannot open filename.");

	outpam.file = fp;

	pnm_writepaminit(&outpam);

	tuplerow = pnm_allocpamrow(&outpam);

	for (i=0; i<height; i++)
	{
		for (j=0; j<width; j++)
		{
			// We only write the first sample (changing 0 and 1)
			tuplerow[j][0] = map->pixels[i][j]?0:1;
		}
		pnm_writepamrow(&outpam, tuplerow);
	}
	pnm_freepamrow(tuplerow);
	
	fclose(fp);
}

/*
static void Page::Initialize()
{
	pnm_init(NULL,NULL);
}
*/

float Page::ratioBlackWhite() const
{
	int i,j;
	float white=0, black=0;

	for(i=0; i<height; i++)
		for (j=0; j<width; j++)
			if (map->pixels[i][j] == 0)
				white++;
			else
				black++;
	return black/white;
}

void Page::calcHistogram()
{
	if (hist!=NULL)
		delete hist;

	map->calcHistogram(hist);
}

void Page::rotateMap(float angle)
{
	Bitmap *newmap;
	rotateMap(angle, newmap);

	// Interchange maps: New -> Page's
	delete map;
	map = newmap;

	height = map->get_height();
	width = map->get_width();
}

void Page::rotateMap(float angle, Bitmap* &mapNew)
{
	// Code taken from OCRchie
  int nx,ny,newheight,newwidth,oldheight,oldwidth,i,j,halfnewheight,halfnewwidth;
  int halfoldheight,halfoldwidth;
  double radians;
  double cosval,sinval;

  radians =  -(angle) / ((180 / 3.142));
  cosval = cos(radians);
  sinval = sin(radians);

  oldheight = height;
  oldwidth = width;
  
  newwidth = (int)abs((int)(oldwidth*cosval)) + (int)abs((int)(oldheight*sinval));
  newheight = (int)abs((int)(-oldwidth*sinval)) + (int)abs((int)(oldheight*cosval));

  halfnewheight = newheight / 2;
  halfnewwidth = newwidth / 2;
  halfoldwidth = oldwidth /2;
  halfoldheight = oldheight /2 ;

  int num_chars = (newwidth / 8) + 1;

  mapNew = new Bitmap(newwidth,newheight);
  mapNew->setToZero();

  for(i=0;i < newheight;i++)
      {
        for(j=0;j < newwidth;j++)
            {
              nx =(int)( (j - halfnewwidth)*cosval + (i-halfnewheight)*sinval);
              ny =(int)( -((j - halfnewwidth)*sinval) + (i - halfnewheight)*cosval);
              nx = nx + halfoldwidth;
              ny = ny + halfoldheight;
              if ((nx < oldwidth) && (ny < oldheight) && (nx > 0) && (ny > 0))
                {
		    mapNew->pixels[i][j] = map->pixels[ny][nx];
                }
              else
                  {
		    mapNew->pixels[i][j] = 0;
                  }
            }
      }


}

void Page::tryAngles(float min, float max, float step)
{
	float i;
	float std_dev;


	for(i=min; i<=max; i+=step)
	{
		std_dev = std_dev_lines_angle(i);
		fprintf(stderr, "Angle: %f, Dev: %f\n", i,
			std_dev);
	}
}

float Page::std_dev_lines_angle(float angle)
{
	float retval;

	Bitmap *tmpmap;
	Histogram *tmphist;


	if (angle == 0)
	{
		map->calcHistogram(tmphist);
	}
	else
	{
		rotateMap(angle,tmpmap);
		tmpmap->calcHistogram(tmphist);
		delete tmpmap;
	}

	retval = tmphist->get_std_dev();

	delete tmphist;

	return retval;
}

float Page::getSkew(int depth, float margin)
{
	float x1,x2,x3;
	float y1,y2,y3;
	float newx, newy;
	int i;

	x1 = -margin;
	x2 = 0;
	x3 = margin;

	/* Bret's Method */
	/*
	for (i=0; i<depth; i++)
	{
		y1 = std_dev_lines_angle(x1);
		y2 = std_dev_lines_angle(x2);
		y3 = std_dev_lines_angle(x3);
		fprintf(stderr, "New stddevs: %f, %f, %f\n", y1, y2, y3);

		newx = x2 - 0.5 * ((x2-x1)*(x2-x1) * (y2-y3) -
			(x2-x3)*(x2-x3) * (y2-y1)) /
			((x2-x1) * (y2-y3) - (x2-x3) * (y2-y1));

		// Comprovacions

		// Resultat
		if (newx > x1 && newx < x2)
		{
			x3 = x2;
			x2 = newx;
		}
		else if (newx > x2 && newx < x3)
		{
			x1 = x2;
			x2 = newx;
		}
		else
			Errors::Fatal("No convergence!");
		fprintf(stderr, "Nous punts: %f, %f, %f\n", x1,x2,x3);
	}
	*/

	/* Golden Slice */
	y1 = std_dev_lines_angle(x1);
	y2 = std_dev_lines_angle(x2);
	y3 = std_dev_lines_angle(x3);

	for (i=0; i<depth; i++)
	{

		// Flanc esquerra
		newx = (x2+x1)/2;
		newy = std_dev_lines_angle(newx);

		// Resultat
		if (newy < y2 )
		{
			x1 = newx;
			y1 = newy;
		}
		else // newy < y2
		{
			x3 = x2;
			y3 = y2;
			x2 = newx;
			y2 = newy;
		}

		// Flanc dret
		newx = (x3+x2)/2;
		newy = std_dev_lines_angle(newx);

		// Resultat
		if (newy < y2 )
		{
			x3 = newx;
			y3 = newy;
		}
		else // newy < y2
		{
			x1 = x2;
			y1 = y2;
			x2 = newx;
			y2 = newy;
		}
		fprintf(stderr, "Nous punts: %f, %f, %f\n", x1,x2,x3);
	}
	return x2;
}

void Page::getText()
{
	if (text == NULL)
		text = new Text();

	text->getLines(map);
}