📄 mfoutline.cpp
字号:
** NoiseSegmentLength maximum length of a "noise" segment ** Globals: none ** Operation: Filter out noise from the specified outline. This is ** done by changing the direction of short segments of the ** outline to the same direction as the preceding outline ** segment. ** Return: none ** Exceptions: none ** History: Fri May 4 10:23:45 1990, DSJ, Created. */ MFOUTLINE Current; MFOUTLINE Last; MFOUTLINE First; FLOAT32 Length; int NumFound = 0; DIRECTION DirectionOfFirst = north; if (DegenerateOutline (Outline)) return; /* find 2 segments of different orientation which are long enough to not be filtered. If two cannot be found, leave the outline unchanged. */ First = NextDirectionChange (Outline); Last = First; do { Current = NextDirectionChange (Last); Length = DistanceBetween (PositionOf (PointAt (Current)), PositionOf (PointAt (Last))); if (Length >= NoiseSegmentLength) { if (NumFound == 0) { NumFound = 1; DirectionOfFirst = DirectionOf (PointAt (Last)); } else if (DirectionOfFirst != DirectionOf (PointAt (Last))) break; } Last = Current; } while (Last != First); if (Current == Last) return; /* find each segment and filter it out if it is too short. Note that the above code guarantees that the initial direction change will not be removed, therefore the loop will terminate. */ First = Last; do { Current = NextDirectionChange (Last); Length = DistanceBetween (PositionOf (PointAt (Current)), PositionOf (PointAt (Last))); if (Length < NoiseSegmentLength) ChangeDirection (Last, Current, PreviousDirectionOf (PointAt (Last))); Last = Current; } while (Last != First);} /* FilterEdgeNoise *//*---------------------------------------------------------------------------*/void FindDirectionChanges(MFOUTLINE Outline, FLOAT32 MinSlope, FLOAT32 MaxSlope) {/* ** Parameters: ** Outline micro-feature outline to analyze ** MinSlope controls "snapping" of segments to horizontal ** MaxSlope controls "snapping" of segments to vertical ** Globals: none ** Operation: ** This routine searches thru the specified outline, computes ** a slope for each vector in the outline, and marks each ** vector as having one of the following directions: ** N, S, E, W, NE, NW, SE, SW ** This information is then stored in the outline and the ** outline is returned. ** Return: none ** Exceptions: none ** History: 7/21/89, DSJ, Created. */ MFEDGEPT *Current; MFEDGEPT *Last; MFOUTLINE EdgePoint; if (DegenerateOutline (Outline)) return; Last = PointAt (Outline); Outline = NextPointAfter (Outline); EdgePoint = Outline; do { Current = PointAt (EdgePoint); ComputeDirection(Last, Current, MinSlope, MaxSlope); Last = Current; EdgePoint = NextPointAfter (EdgePoint); } while (EdgePoint != Outline);} /* FindDirectionChanges *//*---------------------------------------------------------------------------*/void FreeMFOutline(void *arg) { //MFOUTLINE Outline)/* ** Parameters: ** Outline micro-feature outline to be freed ** Globals: none ** Operation: ** This routine deallocates all of the memory consumed by ** a micro-feature outline. ** Return: none ** Exceptions: none ** History: 7/27/89, DSJ, Created. */ MFOUTLINE Start; MFOUTLINE Outline = (MFOUTLINE) arg; /* break the circular outline so we can use std. techniques to deallocate */ Start = rest (Outline); set_rest(Outline, NIL); while (Start != NULL) { c_free_struct (first (Start), sizeof (MFEDGEPT), "MFEDGEPT"); Start = pop (Start); }} /* FreeMFOutline *//*---------------------------------------------------------------------------*/void FreeOutlines(LIST Outlines) { /* ** Parameters: ** Outlines list of mf-outlines to be freed ** Globals: none ** Operation: Release all memory consumed by the specified list ** of outlines. ** Return: none ** Exceptions: none ** History: Thu Dec 13 16:14:50 1990, DSJ, Created. */ destroy_nodes(Outlines, FreeMFOutline); } /* FreeOutlines *//*---------------------------------------------------------------------------*/void InitMFOutlineVars() { /* ** Parameters: none ** Globals: none ** Operation: This routine initializes the global control knobs for ** all routines in this file. ** Return: none ** Exceptions: none ** History: Fri Dec 14 10:50:12 1990, DSJ, Created. */ MakeNormMethod(); MakeCharNormRange(); MakeMinNormScaleX(); MakeMaxNormScaleX(); MakeMinNormScaleY(); MakeMaxNormScaleY(); } /* InitMFOutlineVars *//*---------------------------------------------------------------------------*/void MarkDirectionChanges(MFOUTLINE Outline) { /* ** Parameters: ** Outline micro-feature outline to analyze ** Globals: none ** Operation: ** This routine searches thru the specified outline and finds ** the points at which the outline changes direction. These ** points are then marked as "extremities". This routine is ** used as an alternative to FindExtremities(). It forces the ** endpoints of the microfeatures to be at the direction ** changes rather than at the midpoint between direction ** changes. ** Return: none ** Exceptions: none ** History: 6/29/90, DSJ, Created. */ MFOUTLINE Current; MFOUTLINE Last; MFOUTLINE First; if (DegenerateOutline (Outline)) return; First = NextDirectionChange (Outline); Last = First; do { Current = NextDirectionChange (Last); MarkPoint (PointAt (Current)); Last = Current; } while (Last != First);} /* MarkDirectionChanges *//*---------------------------------------------------------------------------*/MFEDGEPT *NewEdgePoint() { /* ** Parameters: none ** Globals: none ** Operation: ** This routine allocates and returns a new edge point for ** a micro-feature outline. ** Return: New edge point. ** Exceptions: none ** History: 7/21/89, DSJ, Created. */ return ((MFEDGEPT *) c_alloc_struct (sizeof (MFEDGEPT), "MFEDGEPT"));} /* NewEdgePoint *//*---------------------------------------------------------------------------*/MFOUTLINE NextExtremity(MFOUTLINE EdgePoint) { /* ** Parameters: ** EdgePoint start search from this point ** Globals: none ** Operation: ** This routine returns the next point in the micro-feature ** outline that is an extremity. The search starts after ** EdgePoint. The routine assumes that the outline being ** searched is not a degenerate outline (i.e. it must have ** 2 or more edge points). ** Return: Next extremity in the outline after EdgePoint. ** Exceptions: none ** History: 7/26/89, DSJ, Created. */ EdgePoint = NextPointAfter (EdgePoint); while (NotExtremity (PointAt (EdgePoint))) EdgePoint = NextPointAfter (EdgePoint); return (EdgePoint);} /* NextExtremity *//*---------------------------------------------------------------------------*/void NormalizeOutline(MFOUTLINE Outline, LINE_STATS *LineStats, FLOAT32 XOrigin) {/* ** Parameters: ** Outline outline to be normalized ** LineStats statistics for text line normalization ** XOrigin x-origin of text ** Globals: none ** Operation: ** This routine normalizes the coordinates of the specified ** outline so that the outline is deskewed down to the ** baseline, translated so that x=0 is at XOrigin, and scaled ** so that the height of a character cell from descender to ** ascender is 1. Of this height, 0.25 is for the descender, ** 0.25 for the ascender, and 0.5 for the x-height. The ** y coordinate of the baseline is 0. ** Return: none ** Exceptions: none ** History: 8/2/89, DSJ, Created. ** 10/23/89, DSJ, Added ascender/descender stretching. ** 11/89, DSJ, Removed ascender/descender stretching. */ MFEDGEPT *Current; MFOUTLINE EdgePoint; FLOAT32 ScaleFactor; FLOAT32 AscStretch; FLOAT32 DescStretch; if (Outline != NIL) { ScaleFactor = ComputeScaleFactor (LineStats); AscStretch = 1.0; DescStretch = 1.0; EdgePoint = Outline; do { Current = PointAt (EdgePoint); YPositionOf (Current) = ScaleFactor * (YPositionOf (Current) - BaselineAt (LineStats, XPositionOf (Current))); if (YPositionOf (Current) > NORMAL_X_HEIGHT) YPositionOf (Current) = NORMAL_X_HEIGHT + (YPositionOf (Current) - NORMAL_X_HEIGHT) / AscStretch; else if (YPositionOf (Current) < NORMAL_BASELINE) YPositionOf (Current) = NORMAL_BASELINE + (YPositionOf (Current) - NORMAL_BASELINE) / DescStretch; XPositionOf (Current) = ScaleFactor * (XPositionOf (Current) - XOrigin); EdgePoint = NextPointAfter (EdgePoint); } while (EdgePoint != Outline); }} /* NormalizeOutline *//*---------------------------------------------------------------------------*/void NormalizeOutlines(LIST Outlines, LINE_STATS *LineStats, FLOAT32 *XScale, FLOAT32 *YScale) {/* ** Parameters: ** Outlines list of outlines to be normalized ** LineStats statistics for text line normalization ** XScale x-direction scale factor used by routine ** YScale y-direction scale factor used by routine ** Globals: ** NormMethod method being used for normalization ** CharNormRange map radius of gyration to this value ** Operation: This routine normalizes every outline in Outlines ** according to the currently selected normalization method. ** It also returns the scale factors that it used to do this ** scaling. The scale factors returned represent the x and ** y sizes in the normalized coordinate system that correspond ** to 1 pixel in the original coordinate system. ** Return: none (Outlines are changed and XScale and YScale are updated) ** Exceptions: none ** History: Fri Dec 14 08:14:55 1990, DSJ, Created. */ MFOUTLINE Outline; OUTLINE_STATS OutlineStats; FLOAT32 BaselineScale; switch (NormMethod) { case character: ComputeOutlineStats(Outlines, &OutlineStats); /* limit scale factor to avoid overscaling small blobs (.,`'), thin blobs (l1ift), and merged blobs */ *XScale = *YScale = BaselineScale = ComputeScaleFactor (LineStats); *XScale *= OutlineStats.Ry; *YScale *= OutlineStats.Rx; if (*XScale < MinNormScaleX) *XScale = MinNormScaleX; if (*YScale < MinNormScaleY) *YScale = MinNormScaleY; if (*XScale > MaxNormScaleX && *YScale <= MaxNormScaleY) *XScale = MaxNormScaleX; *XScale = CharNormRange * BaselineScale / *XScale; *YScale = CharNormRange * BaselineScale / *YScale; iterate(Outlines) { Outline = (MFOUTLINE) first (Outlines); CharNormalizeOutline (Outline, OutlineStats.x, OutlineStats.y, *XScale, *YScale); } break; case baseline: iterate(Outlines) { Outline = (MFOUTLINE) first (Outlines);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -