// Threshold the given grey or color image into the tesseract global // image ready for recognition. Requires thresholds and hi_value // produced by OtsuThreshold above. void TessBaseAPI::ThresholdRect(const unsigned char* imagedata, int bytes_per_pixel, int bytes_per_line, int left, int top, int width, int height, const int* thresholds, const int* hi_values) { IMAGELINE line; page_image.create(width, height, 1); line.init(width); // For each line in the image, fill the IMAGELINE class and put it into the // Tesseract global page_image. Note that Tesseract stores images with the // bottom at y=0 and 0 is black, so we need 2 kinds of inversion. const unsigned char* data = imagedata + top*bytes_per_line + left*bytes_per_pixel; for (int y = height - 1 ; y >= 0; --y) { const unsigned char* pix = data; for (int x = 0; x < width; ++x, pix += bytes_per_pixel) { line.pixels[x] = 1; for (int ch = 0; ch < bytes_per_pixel; ++ch) { if (hi_values[ch] >= 0 && (pix[ch] > thresholds[ch]) == (hi_values[ch] == 0)) { line.pixels[x] = 0; break; } } } page_image.put_line(0, y, width, &line, 0); data += bytes_per_line; } }
void read_tiff_image(TIFF* tif, IMAGE* image) { tdata_t buf; uint32 image_width, image_height; uint16 photometric; inT16 bpp; inT16 samples_per_pixel = 0; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &image_width); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &image_height); TIFFGetField(tif, TIFFTAG_BITSPERSAMPLE, &bpp); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &samples_per_pixel); TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photometric); if (samples_per_pixel > 1) bpp *= samples_per_pixel; // Tesseract's internal representation is 0-is-black, // so if the photometric is 1 (min is black) then high-valued pixels // are 1 (white), otherwise they are 0 (black). uinT8 high_value = photometric == 1; image->create(image_width, image_height, bpp); IMAGELINE line; line.init(image_width); buf = _TIFFmalloc(TIFFScanlineSize(tif)); int bytes_per_line = (image_width*bpp + 7)/8; uinT8* dest_buf = image->get_buffer(); // This will go badly wrong with one of the more exotic tiff formats, // but the majority will work OK. for (int y = 0; y < image_height; ++y) { TIFFReadScanline(tif, buf, y); memcpy(dest_buf, buf, bytes_per_line); dest_buf += bytes_per_line; } if (high_value == 0) invert_image(image); _TIFFfree(buf); }
// Dump the internal binary image to a PGM file. void TessBaseAPI::DumpPGM(const char* filename) { IMAGELINE line; line.init(page_image.get_xsize()); FILE *fp = fopen(filename, "w"); fprintf(fp, "P5 " INT32FORMAT " " INT32FORMAT " 255\n", page_image.get_xsize(), page_image.get_ysize()); for (int j = page_image.get_ysize()-1; j >= 0 ; --j) { page_image.get_line(0, j, page_image.get_xsize(), &line, 0); for (int i = 0; i < page_image.get_xsize(); ++i) { uinT8 b = line.pixels[i] ? 255 : 0; fwrite(&b, 1, 1, fp); } } fclose(fp); }
DLLSYM void block_edges( //get edges in a block IMAGE *t_image, //threshold image PDBLK *block, //block in image ICOORD page_tr //corner of page ) { uinT8 margin; //margin colour inT16 x; //line coords inT16 y; //current line ICOORD bleft; //bounding box ICOORD tright; ICOORD block_bleft; //bounding box ICOORD block_tright; int xindex; //index to pixel BLOCK_LINE_IT line_it = block; //line iterator IMAGELINE bwline; //thresholded line //lines in progress CRACKEDGE **ptrline = new CRACKEDGE*[t_image->get_xsize()+1]; block->bounding_box (bleft, tright); // block box block_bleft = bleft; block_tright = tright; for (x = tright.x () - bleft.x (); x >= 0; x--) ptrline[x] = NULL; //no lines in progress bwline.init (t_image->get_xsize()); margin = WHITE_PIX; for (y = tright.y () - 1; y >= bleft.y () - 1; y--) { if (y >= block_bleft.y () && y < block_tright.y ()) { t_image->get_line (bleft.x (), y, tright.x () - bleft.x (), &bwline, 0); make_margins (block, &line_it, bwline.pixels, margin, bleft.x (), tright.x (), y); } else { x = tright.x () - bleft.x (); for (xindex = 0; xindex < x; xindex++) bwline.pixels[xindex] = margin; } line_edges (bleft.x (), y, tright.x () - bleft.x (), margin, bwline.pixels, ptrline); } free_crackedges(free_cracks); //really free them free_cracks = NULL; delete [] ptrline; }
////////////DEBAYAN//Deskew begins////////////////////// void deskew(float angle,int srcheight, int srcwidth) { //angle=4; //45° for example IMAGE tempimage; IMAGELINE line; //Convert degrees to radians float radians=(2*3.1416*angle)/360; float cosine=(float)cos(radians); float sine=(float)sin(radians); float Point1x=(srcheight*sine); float Point1y=(srcheight*cosine); float Point2x=(srcwidth*cosine-srcheight*sine); float Point2y=(srcheight*cosine+srcwidth*sine); float Point3x=(srcwidth*cosine); float Point3y=(srcwidth*sine); float minx=min(0,min(Point1x,min(Point2x,Point3x))); float miny=min(0,min(Point1y,min(Point2y,Point3y))); float maxx=max(Point1x,max(Point2x,Point3x)); float maxy=max(Point1y,max(Point2y,Point3y)); int DestWidth=(int)ceil(fabs(maxx)-minx); int DestHeight=(int)ceil(fabs(maxy)-miny); tempimage.create(DestWidth,DestHeight,1); line.init(DestWidth); for(int i=0;i<DestWidth;i++){ //A white line of length=DestWidth line.pixels[i]=1; } for(int y=0;y<DestHeight;y++){ //Fill the Destination image with white, else clipmatra wont work tempimage.put_line(0,y,DestWidth,&line,0); } line.init(DestWidth); for(int y=0;y<DestHeight;y++) //Start filling the destination image pixels with corresponding source image pixels { for(int x=0;x<DestWidth;x++) { int Srcx=(int)((x+minx)*cosine+(y+miny)*sine); int Srcy=(int)((y+miny)*cosine-(x+minx)*sine); if(Srcx>=0&&Srcx<srcwidth&&Srcy>=0&& Srcy<srcheight) { line.pixels[x]= page_image.pixel(Srcx,Srcy); } } tempimage.put_line(0,y,DestWidth,&line,0); } //tempimage.write("tempimage.tif"); page_image=tempimage;//Copy deskewed image to global page image, so it can be worked on further tempimage.destroy(); //page_image.write("page_image.tif"); }