| /* -*-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); |
| } |