mirror of
https://github.com/tesseract-ocr/tesseract.git
synced 2024-11-27 20:59:36 +08:00
425d593ebe
git-svn-id: https://tesseract-ocr.googlecode.com/svn/trunk/trunk@2 d0cd1f9f-072b-0410-8dd7-cf729c803f20
248 lines
7.8 KiB
C++
248 lines
7.8 KiB
C++
/* -*-C-*-
|
|
********************************************************************************
|
|
*
|
|
* File: blobs.c (Formerly blobs.c)
|
|
* Description: Blob definition
|
|
* Author: Mark Seaman, OCR Technology
|
|
* Created: Fri Oct 27 15:39:52 1989
|
|
* Modified: Thu Mar 28 15:33:26 1991 (Mark Seaman) marks@hpgrlt
|
|
* Language: C
|
|
* Package: N/A
|
|
* Status: Experimental (Do Not Distribute)
|
|
*
|
|
* (c) Copyright 1989, Hewlett-Packard Company.
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*
|
|
*********************************************************************************/
|
|
|
|
/*----------------------------------------------------------------------
|
|
I n c l u d e s
|
|
----------------------------------------------------------------------*/
|
|
#include "mfcpch.h"
|
|
#include "blobs.h"
|
|
#include "cutil.h"
|
|
#include "emalloc.h"
|
|
#include "structures.h"
|
|
|
|
/*----------------------------------------------------------------------
|
|
F u n c t i o n s
|
|
----------------------------------------------------------------------*/
|
|
/**********************************************************************
|
|
* blob_origin
|
|
*
|
|
* Compute the origin of a compound blob, define to be the centre
|
|
* of the bounding box.
|
|
**********************************************************************/
|
|
void blob_origin(TBLOB *blob, /*blob to compute on */
|
|
TPOINT *origin) { /*return value */
|
|
TPOINT topleft; /*bounding box */
|
|
TPOINT botright;
|
|
|
|
/*find bounding box */
|
|
blob_bounding_box(blob, &topleft, &botright);
|
|
/*centre of box */
|
|
origin->x = (topleft.x + botright.x) / 2;
|
|
origin->y = (topleft.y + botright.y) / 2;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* blob_bounding_box
|
|
*
|
|
* Compute the bounding_box of a compound blob, define to be the
|
|
* max coordinate value of the bounding boxes of all the top-level
|
|
* outlines in the box.
|
|
**********************************************************************/
|
|
void blob_bounding_box(TBLOB *blob, /*blob to compute on */
|
|
register TPOINT *topleft, /*bounding box */
|
|
register TPOINT *botright) {
|
|
register TESSLINE *outline; /*current outline */
|
|
|
|
if (blob == NULL || blob->outlines == NULL) {
|
|
topleft->x = topleft->y = 0;
|
|
*botright = *topleft; /*default value */
|
|
}
|
|
else {
|
|
outline = blob->outlines;
|
|
*topleft = outline->topleft;
|
|
*botright = outline->botright;
|
|
for (outline = outline->next; outline != NULL; outline = outline->next) {
|
|
if (outline->topleft.x < topleft->x)
|
|
/*find extremes */
|
|
topleft->x = outline->topleft.x;
|
|
if (outline->botright.x > botright->x)
|
|
/*find extremes */
|
|
botright->x = outline->botright.x;
|
|
if (outline->topleft.y > topleft->y)
|
|
/*find extremes */
|
|
topleft->y = outline->topleft.y;
|
|
if (outline->botright.y < botright->y)
|
|
/*find extremes */
|
|
botright->y = outline->botright.y;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* blobs_bounding_box
|
|
*
|
|
* Return the smallest extreme point that contain this word.
|
|
**********************************************************************/
|
|
void blobs_bounding_box(TBLOB *blobs, TPOINT *topleft, TPOINT *botright) {
|
|
TPOINT tl;
|
|
TPOINT br;
|
|
TBLOB *blob;
|
|
/* Start with first blob */
|
|
blob_bounding_box(blobs, topleft, botright);
|
|
|
|
iterate_blobs(blob, blobs) {
|
|
blob_bounding_box(blob, &tl, &br);
|
|
|
|
if (tl.x < topleft->x)
|
|
topleft->x = tl.x;
|
|
if (tl.y > topleft->y)
|
|
topleft->y = tl.y;
|
|
if (br.x > botright->x)
|
|
botright->x = br.x;
|
|
if (br.y < botright->y)
|
|
botright->y = br.y;
|
|
}
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* blobs_origin
|
|
*
|
|
* Compute the origin of a compound blob, define to be the centre
|
|
* of the bounding box.
|
|
**********************************************************************/
|
|
void blobs_origin(TBLOB *blobs, /*blob to compute on */
|
|
TPOINT *origin) { /*return value */
|
|
TPOINT topleft; /*bounding box */
|
|
TPOINT botright;
|
|
|
|
/*find bounding box */
|
|
blobs_bounding_box(blobs, &topleft, &botright);
|
|
/*center of box */
|
|
origin->x = (topleft.x + botright.x) / 2;
|
|
origin->y = (topleft.y + botright.y) / 2;
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* blobs_widths
|
|
*
|
|
* Compute the widths of a list of blobs. Return an array of the widths
|
|
* and gaps.
|
|
**********************************************************************/
|
|
WIDTH_RECORD *blobs_widths(TBLOB *blobs) { /*blob to compute on */
|
|
WIDTH_RECORD *width_record;
|
|
TPOINT topleft; /*bounding box */
|
|
TPOINT botright;
|
|
TBLOB *blob; /*blob to compute on */
|
|
int i = 0;
|
|
int blob_end;
|
|
int num_blobs = count_blobs (blobs);
|
|
|
|
/* Get memory */
|
|
width_record = (WIDTH_RECORD *) memalloc (sizeof (int) * num_blobs * 2);
|
|
width_record->num_chars = num_blobs;
|
|
|
|
blob_bounding_box(blobs, &topleft, &botright);
|
|
width_record->widths[i++] = botright.x - topleft.x;
|
|
/* First width */
|
|
blob_end = botright.x;
|
|
|
|
iterate_blobs (blob, blobs->next) {
|
|
blob_bounding_box(blob, &topleft, &botright);
|
|
width_record->widths[i++] = topleft.x - blob_end;
|
|
width_record->widths[i++] = botright.x - topleft.x;
|
|
blob_end = botright.x;
|
|
}
|
|
return (width_record);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* count_blobs
|
|
*
|
|
* Return a count of the number of blobs attached to this one.
|
|
**********************************************************************/
|
|
int count_blobs(TBLOB *blobs) {
|
|
TBLOB *b;
|
|
int x = 0;
|
|
|
|
iterate_blobs (b, blobs) x++;
|
|
return (x);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* delete_word
|
|
*
|
|
* Reclaim the memory taken by this word structure and all of its
|
|
* lower level structures.
|
|
**********************************************************************/
|
|
void delete_word(TWERD *word) {
|
|
TBLOB *blob;
|
|
TBLOB *nextblob;
|
|
TESSLINE *outline;
|
|
TESSLINE *nextoutline;
|
|
TESSLINE *child;
|
|
TESSLINE *nextchild;
|
|
|
|
for (blob = word->blobs; blob; blob = nextblob) {
|
|
nextblob = blob->next;
|
|
|
|
for (outline = blob->outlines; outline; outline = nextoutline) {
|
|
nextoutline = outline->next;
|
|
|
|
delete_edgepts (outline->loop);
|
|
|
|
for (child = outline->child; child; child = nextchild) {
|
|
nextchild = child->next;
|
|
|
|
delete_edgepts (child->loop);
|
|
|
|
oldoutline(child);
|
|
}
|
|
oldoutline(outline);
|
|
}
|
|
oldblob(blob);
|
|
}
|
|
if (word->correct != NULL)
|
|
strfree (word->correct); /* Reclaim memory */
|
|
oldword(word);
|
|
}
|
|
|
|
|
|
/**********************************************************************
|
|
* delete_edgepts
|
|
*
|
|
* Delete a list of EDGEPT structures.
|
|
**********************************************************************/
|
|
void delete_edgepts(register EDGEPT *edgepts) {
|
|
register EDGEPT *this_edge;
|
|
register EDGEPT *next_edge;
|
|
|
|
if (edgepts == NULL)
|
|
return;
|
|
|
|
this_edge = edgepts;
|
|
do {
|
|
next_edge = this_edge->next;
|
|
oldedgept(this_edge);
|
|
this_edge = next_edge;
|
|
}
|
|
while (this_edge != edgepts);
|
|
}
|