CA2077969C - Method of deriving wordshapes for subsequent comparison - Google Patents

Method of deriving wordshapes for subsequent comparison

Info

Publication number
CA2077969C
CA2077969C CA002077969A CA2077969A CA2077969C CA 2077969 C CA2077969 C CA 2077969C CA 002077969 A CA002077969 A CA 002077969A CA 2077969 A CA2077969 A CA 2077969A CA 2077969 C CA2077969 C CA 2077969C
Authority
CA
Canada
Prior art keywords
symbol string
image
int
float
pict
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Expired - Fee Related
Application number
CA002077969A
Other languages
French (fr)
Other versions
CA2077969A1 (en
Inventor
Daniel P. Huttenlocher
Michael J. Hopcroft
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Xerox Corp
Original Assignee
Xerox Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Xerox Corp filed Critical Xerox Corp
Publication of CA2077969A1 publication Critical patent/CA2077969A1/en
Application granted granted Critical
Publication of CA2077969C publication Critical patent/CA2077969C/en
Anticipated expiration legal-status Critical
Expired - Fee Related legal-status Critical Current

Links

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06VIMAGE OR VIDEO RECOGNITION OR UNDERSTANDING
    • G06V30/00Character recognition; Recognising digital ink; Document-oriented image-based pattern recognition
    • G06V30/10Character recognition
    • G06V30/18Extraction of features or characteristics of the image
    • G06V30/182Extraction of features or characteristics of the image by coding the contour of the pattern
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06VIMAGE OR VIDEO RECOGNITION OR UNDERSTANDING
    • G06V30/00Character recognition; Recognising digital ink; Document-oriented image-based pattern recognition
    • G06V30/10Character recognition
    • G06V30/18Extraction of features or characteristics of the image
    • G06V30/184Extraction of features or characteristics of the image by analysing segments intersecting the pattern
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06VIMAGE OR VIDEO RECOGNITION OR UNDERSTANDING
    • G06V30/00Character recognition; Recognising digital ink; Document-oriented image-based pattern recognition
    • G06V30/10Character recognition

Landscapes

  • Engineering & Computer Science (AREA)
  • Computer Vision & Pattern Recognition (AREA)
  • Physics & Mathematics (AREA)
  • General Physics & Mathematics (AREA)
  • Multimedia (AREA)
  • Theoretical Computer Science (AREA)
  • Character Input (AREA)
  • Character Discrimination (AREA)
  • Image Processing (AREA)

Abstract

A method for reducing an image of a character or word string to one or more one dimensional signals, including the steps of determining page orientation, isolating character strings from adjacent character strings, establishing a set of references with respect to which measurements about the character string may be made, and deriving a plurality of measurements with respect to the references in terms of a single variable signal, from which information about the symbol string may be derived.

Description

2077~69 -A METHOD OF DFFllvlN~i WQRnSHAPES FOR
SUESEQUENT COMPARISON ..
This invention relates to a method of recognizing text or character strings ~e,u,~s~"lt:d in an array of image data by shape, without a requirement for individually detecting and/or identifying the character or characters making up the strings, and more particularly, to a method of deriving a description of the shape of a word as a one .li"lel~siol1al signal.
The article "Performance Tradeoffs in Dynamic Time Warping Algorithms for Isolated Word Recognition", by Myers, Rabiner, and Rosenberg, IEEE Transactions on Acoustics, Speech, and Signal Processing, Vol. ASSP-28, No. 6, December 1980, and the book, "Time Warps, String Edits, and Macromolecules: The Theory and Practice of Sequence Comparison", by Sankoff and Kruskal, Addison-Wesley Publishing Company, Inc., Reading, Massachusetts, 1983, Chapters 1 and 4, may be referred to for their background teachings. I

~077q6q COPYRIGHT NOTIFICATIQN ~ .
A portion of the disclosure of this patent document contains malerial which is subject to copyright protection. The copyright owners have no objection to the facsimile reproduction, by anyone, of the patent document or the patent disclosure, as it appears in the Patent Office patent file or records, but otherwise reserves all copyright rights whatsoever.
APPENDIX
An Appendix comprising 207 pages and an index is included as part of this application.
BACKGROUND OF THE INVENTION
Textin electronlcallyencodeddocuments(electronicdocumentsl tends to be found in elther of two formats, ea~h distinct from the other. In a first format, the text may be in a bitmap format, in which text IS defined only in terms of an array of image data or pixels, essentiaily indistinguishable from adjacent images whi~h are similarly represented. In this format, text is generally in~apable of being subjected to processing by a computer based on textual content alone. In a se~ond format, hereinafter referred to as a character code format, the text is represented as a string of character codes (e.g. ASCII code). In the character code format, the image or bitmap of the text is not avallable.
Conversion from bitmap to character code format using an optical character recognition (OCR) process carries a significant cost in terms of time and processing effort. Each bitmap of a character must be distinguished from its neighbors, its appearance analyzed, and in a decision making process, identlfied as a dlstinct character in a predetermined set of characters. For example, US-~ 186~ 628 o Scott discloses a method for reading data which clrcumnavigates a character Image. Data representatlve of the periphery of the character is read to produce a set of character parameters which are then used to compare the character agalnst a set of reference r arameters and identlfv the character US-A ~ 326.~ 90 to Borland et al teaches a character feature detectlon system for reading A~: _ .
alphanumeric characters. A digitized binary image is used, characters images are traced from boundary points to boundary points, wherein the transitions are afe defined by one of eight equally divergent vectors.
~haracter features are subsequently extracted from the vector data to form a feature set. The feature set is then analyzed to form a set of secondary features which are used to identify the character. US-A 4,813,078 to Fujiwara et al. discloses a character recognition apparatus employing a similar process, where picture change points are identified and accumulated according to direction and background density, and are used to enable more accurate identification of characters which are generally erroneously ~e~c,y"i~. Fu~ ".,or~, US-A 4,833,721 to Okutomi et al.
teaches a similar system, operating on character outlines, which may be employed as a man/machine interface for an electronic apparatus.
Additional ret~,e,1~s which describe alternative methods and apparatus for identification of characters within a digitized image are: US-A 3,755,780 to Sammon et al. teaches a method for recognizing characters by the number, position and shape of alternating contour convexities as viewed from two sides of the character; US-A 3,899,771 to Saraga et al, which teaches the use of linear traverse employing shifted edge lines for character recognition; US-A 4,817,166 to Gonzales et al. which teaches the application of character recognition techniques in an apparatus for reading a license plate which includes a character alignment section and a correction section; and US-A 4,566,128 to Araki which discloses a method for compressing character image data using a divided character image to recognize and classify contours, enabling the compressed storage of the character image as a group of closed-loop line segments. In addition, US-A
4,956,869 to Miyatake et al. suggests a a more efficient method for tracing contour lines to prepare contour coordinates of a figure within an image consisting of a plurality of lines.
When the electronic document has been derived by scanning an original, however, image quality and noise in its reproduction contribute to uncertainty in the actual appearance of the bitmap. A degraded bitmap appearance may be caused by a original document of poor quality, by -2~779~9 scanning error, or by similar factors affecting the digitized ~eprese"laLion of the image. Therefore, the decision process employed in identifying a character has an inherent uncertainty about it. A particular problem in this regard is the tendency of characters in text to blur, or merge. Most character identifying processes commence with an assumption that a character is an independent set of connected pixels. When this assumption fails, due to the quality of the input image, character ider,Liri.dlion also fails. A Yariety of attempts have been made to improve character detection. US-A 4,926,49û to Mano disc~oses a method and apparatus for recognizing characters on a document wherein characters of a skewed document are recognized. A rectangle is created around each character image, oriented with the detection orientation rather than the image orientation, and position data for each rectangle is stored in a table. The rectangle is created by detecting a character's outline. US-A 4,558,461 to Schlang discloses a text line bounding system wherein skewed text is adjusted by analyzing vertical patches of a document. After the skew has been determined, each text line is bounded by determining a top, bottom, left, and right boundary of the text line. US-A 3,295,105 to Gray et al.
discloses a scan controller for normalizing a character in a character recognition apparatus wherein a character is analyzed by determining certain character characteristics including top, bottom, right and left character boundaries. US-A 4,918,740 to Ross discloses a processi.,g means for use in an optical character recognition system wherein sub-line information is used to analyze a character and identify it. US-A 4,558,461 to Schlang suggests a text line bounding system for nonmechanically adjusting for skewed text in scanned text The skew angle of the text is then established, following which the text lines are statistically bounded.
The actual text data is then rotated according to the orientation established for conventional processing. US-A 4,809,344 to Peppers et al.
teaches preprocessing of character recognition so as to obtain data necessary for character recognition. Page segmentation is performed by simultaneously extracting a plurality of features, separation between lines, separation between characters, and separation between the lines and the characters are simultaneously performed, and a calculation time for nor",-' ~g the separated individual characters can be reduced, thereby performing prtyr~.e"illg required for character recognition systematically at high speed.
OCR methods have sought to improve reliability by use of dictionary word verification methods, such as described in US-A 4,010,445 to Hoshino. However, the underlying problem of accurate character detection of each character in a character string remains. The article "F6365 Japanese Document Reader" Fujitsu Sci. Tech. J., 26, 3, pp. 224-233 (October 1990) shows a character reader using the steps of block extraction, skew adjustment, block division, adjacent character segmentation, line e.~l,d.~ions, and character recognition by pattern matching, with dictionary checking, and comparison.
It might be desirable, to identify a set of characters forming a word or character string as such, as shown, for example, in US-A 2,905,927 to Reed, in which for a text string, a set of three scans across the text, parallel to its reading orientation are employed, each scan deriving information about l~dl~,ilions from black to white across the scan. When values derived from the three scans are reviewed, the information derived from the combination of three scans forms a unique identifier for a word that may then be compared to preset values for iden~iri.alion purposes.
Two problems are noted with this method, first, that the image information or bitmap is lost in the conversion, and secondly, the process is rather gross in nature and depends heavily upon the uniform nature of the character in the image scanned. Loss of the image bitmap is a characteristic of the conversion of a bitmap containing textual information to ~t~resentalive character codes. US-A 4,155,072 to Kawa suggests a similar arrangement, operable to produce a set of values representative of the leading and trailing edges of the character. From this information a quadratic correlation function is used for comparison to standard character patterns.
In addition to an OCR system operating on printed or typed textual images, numerous references deal with recognition of handwritten 2077g6g text which has been converted into an electronic ~ .r~sel,ldLion. US-A
4,731,857 to Tappert shows pro~essing a word with the seg".er,lation and recognition steps~ombined into an overall scheme. This is accomplished by a three step procedure. First, potential or trail se9lne~lalion points are derived. Second, all combinations of the segments that could reasonably be a character are sent to a character recognizor to obtain ranked choices and ~Cr,t!,~.ol. ' .~ scores. Finally, the recognition results are sorted and combined so that the character sequences having the best cumulative scores are obtained as the best word choices. US-A 4,764,972 to Yoshida et al. suggests a recognition system for recognizing a plurality of handwritten characters. A first memory is used to store isolated characters, and a second memory is used to store information, including interstroke character information, for connecting isolated characters. Finally, US-A 4,933,977 to Ohnishi et al. discloses a method for identifying a plurality of handwritten connected figures, including identifying and prioritizing branches of the connected figures. Branches having the lowest priority within a recognition block are erased until a recognizable figure is obtained. From the recognition block extends a second block which is analyzed in the same fashion until a second figure is recognized.
The choice of entire words as the basic unit of recognition, has also been considered in signature recognition, where no attempt is made to maintain characters as having separate identities, and is suggested by US-A
3,133,266 to Frishkopf, which still relies on subsequent feature identification methods for identifying characteristics of the image of the character. Signature recognition has also used comparison techniques between samples and known signatures, as shown in US-A 4,495,644 to Parksetal~andUS-A4~701~s60toscottwhichsuggestthatfeaturesplotted on x-y coordinates during the signature process can be stored and used for signature verification.
US-A 4,499,499 to Brickman et al. suggests a method of image compression in which the bitmap representation of a word is compared to a bitmap representation dictionary through superposition of the detected word over the stored word to derive a difference value which is compared 2~77.969 to a reference value indicating a degree of certainty of a match.
Neither OCR methods which seek to encode a bitmap into characters processable as information by computer or bitmap methods for manipulation of images have proven completely satisfactory for all purposes of text manipulation or processing.
In Canadian Laid-Open Patent Application Serial No.
2,029,585 (6130/91), entitled ''Changing Characters in an Image", by Bagley et al, a method is shown for changing characters in text appearing in an image. The character to be changed is identified and if the changed version of the image includes a character not in the text prior to the change, a shape comparing process is used to identify a word containing the newly required character, copy the character, and insert it into its new position. In Canadian Laid-Open Patent Application Serial No. 2,027,253 (b/30/91), entitled "Editing Text in an Image", by Bagley et al, a method is shown for identifying and changing characters in text appearing in an image.
Alternative modes of expressing character recognition are known, such as US-A 3,755,780 to Sammon et al., which discloses a method of recognizing characters wherein a shape of the character is represented by the number, position and shape of the character's contours. The number and position of the contour allow each character to be sorted according to these values. US-A 4,903,312 to Sato discloses a character recognition system with variable subdivisions of a character region wherein a character is read to form a binary image. The binary image is then assigned a plurality of directionality codes which define a contour of the binary image.
The binary image is then divided into a number of subregions, each of which has an equal number of directionality codes. A histogram of the directionality codes is calculated for each subregion. The histogram of the binary image is then compared with a number of known character contour histograms. Also, US-A 4,949,281 to Hillenbrand et al. teaches the use of polynomials for generating and reproducing graphic objects, where the objects are predetermlned in the form of reference contours in contour coordinates. Individual characters are represented as a linear field of outside contours which may be filtered, smoothed, and corner recognlzed 2~77969 before bei:lg broken into curve segments. Subsequently, the character is stored as a series of contour segments, each segment having starting points, base poin~s and associated reference contours.
Certain signal processing techniques for comparing known signals to unknown signals are available if the word can be expressed in a relatively simple manner. US-A 4,400,828 to Pirz et al. discloses a spoken word recognizor wherein an input word is recognized from a set of reference words by generating signals representative of the correspondence of an input word and the set of reference words and selecting a closest match. The word recognizor is used with a speech analysis system. A normalization and linear time warp device is disclosed.
The input word and the set of reference words are processed electrically to determine correspondence. US-A 4,977,603 to Irie et al. teaches an arrangement for pattern recognition utilizing the multiple similarity method, capable of taking structural features of a pattern to be recognized into account, so that sufficiently accurate pattern recognition can be achieved even when the pattern may involve complicated and diverse variations. The method includes the steps of: counting a number of occurrences, within each one of localized regions which subdivides a pattern to be recognized, of local patterns indicating possible arrangements of picture elements; deriving a vector quantity indicating distribution of black picture elements which constitute the pattern, from the numbers of occurrences of the local patterns; calculating multiple similarity, defined in terms of square of inner product of the vector quantity and one of prescribed standard vectors representing standard patterns; and recognizing the pattern by identifying the pattern with one of the standard pattern whose corresponding standard vectors gives the maximum values for the multiple similarity. "An Efficiently Computable Metric for Comparing Polygon Shapes, by Arkin, Chew, Huttenlocher, Kedem and Mitchell, Proceedinqs of the First Annual ACM-SIAM
Symposium on Discrete Mathematics, ~anuary 1990 (pp. 129-137) suggests that metrics can be established for shape matching.
-~ - 2~77969 Al~ of the :t:relellces cited herein and above are incorporated by reference fortheirteachings.
-~ SUMMARY OF THE INVENTION
In accordance with the invention, there is provided a method for ~,u.~,e,,li,,g a word, character orsymbol string represented in image data, by shape, without a requirement for individually detecting and/or i~."iry;"gthecharacterorcharactersmaking upthestring.
In accordance with one aspect of the invention, a method of forming a word shape is provided, from which information about a symbol string may be derived, including the steps of a) identifying the limits of an image of a symbol string; b) identifying a reference with respect to the symbol string; c) deriving a set of one dimensional measurements about at least a portion of the shape of the symbol string with respect to the reference.
In accordance with another aspect of the invention, once orientation of a symbol string within an image is established, line spacing and word or symbol string spacing is established. Each discrete symbol string may then be surrounded by a bounding box, defining an appru~;",dLion of the limits of the image of the symbol string. A reference line may then created extending through the symbol string image. Using these references, a series of measurement may be made with respect to the references and the symbol string, which define the shape of a portions of the symbol string. Because the set of measurement derived can be expressed in terms of position along a horizontal axis, the signal can be considered a single, independent variable signal.
In an alternative mode of expressing the present invention, cc,nsiJe, i"g image data i(x,y), which in one common case could be an array of image data in the form of a bitmap, the image of a symbol string is identified, and a boundary thereabout defined. From i(x,y), an edge signal e(x,y), which represents the edges of l(x,y) detected within the closed boundary, is derived. The edge signal is augmented by adding additional data to i(x,y) so that e(x,y) is a signal e'(x,y) defined over its entire domainwith respect to an independent variable within the closed boundary. One, g 2~77~69 .
two, or more signals may be derlved from e'(x,y) which are each one dimensional signals g'(t) where g Is the signal of the independent varlable t which is a reference frame dependent parameter.
In accordance wlth still another aspect of the Inventlon, a method of forming a word shape from an Image of te:~t is provlded, from which information about a discrete symbol string therein may be derlved, including the steps of: a) detecting the skew of text wlthin the Image wlth respect to a reference; b) determlnlng wlthin the text Image, upper and lower limits of any lines of text; c) operatlng on the image to distlngulsh between inter-symbol spacing and inter-strlng spacing; d) uslng sald determined text line limlts and said determlned inter-string spacing to define limits of a symbol string; e) establishlng a reference with respect to the image of the symbol string and the orlentation of the image; and f) making a series of measurement with respect to the image and the reference, sald series of measurements defining a shape or cur~/e from which information about the symbol string may be derlved.
Other aspects of this invention are as follows:
A rriethod of forming a word shape, from which informatlon about a symbol string may be derived, inciuding the steps of:
a) isolating a symbol string image;
b) identifying a first reference with respect to the symbol string;
c) deriving a set of single independent variable measurements about at least a portion of the shape of the symbol string with respect to the reference.
A method of forming a word shape, from which information about a symbol string may be derived, including the steps of:
deternlining orientation of a symbol string within an image;
isolating a discrete symbol string in the image by differentiating between adjacent symbol strings;
establishing a reference at least partially enclosing a discrete symbol string;

A~

20779Z~
defining a reference line parallel to, and extending through, the symbol strlng;
deriving a set of distance measurements for each of a set of line segments between the symbol string or the reference line, and the enclosing reference.
A method of forming a word shape, from which informatlon about a symbol string may be derlved, Includlng the steps of:
deterrnining orientation of a symbol string wlthln an Image;
isolating a discrete symbol strlng In the image by differentlating between adjacent symbol strings;
defining a reference line parallel to, and extending through, the symbol string;
defining a set of points along an outer edge of the symbol string;
deriving a set of distance rneasurements for each of a set of line segments between the refe~ence line, and symbol strlng outer edge polnts defined.
A method of forming a word shape from an Image of text, from which information about a discrete symbol string thereln may be derived, including the steps of:
a) detecting the orientation of text within an Image;
b) determining within the text image, upper and lower limits of any lines of text;
c) operating on the text image to distinguish between Inter-symbol spacing and inter-string spacing;
d) using said determined upper and lower limlts of any lines of text, and said distinguished inter-string spacing, to define at least a first reference at least partially enclosing a discrete symbol string;
e) establishing a reference line with respect to the symbol string image and the orientatlon of the image, said reference parallel to the test orientation and through the symbol string image;
.

- 10a-A~

2~77969 fl making a set of distance measurements for each of a set of line segments between the reference, and the enclosing reference.
A method of deriving a signal ~epresentative of the shape of a symbol string in an array of image data comprising the steps of:
a) iderltifying a distinct symbol string in the array of image data;
b) identifying a reference with respect to which the shape signal will be derived for the symbol string;
c) representing the shape of the Identified symbol string as a closed curve; and d) for a selected portion of said closed curve, representing sald selected portion as a signal f(t) derived with respect to said reference.
A method of deriving a signal ,.pr..en~ali.~ of the shape of a symbol string in an array of image data comprising the steps of:
a) about a selected symbol string, represented by the signal l(x,y), defining a closed boundary uniquely enclosing said selected symbol string in the array of image data;
b) deriving from l(x,y) the edge signal E(x,y) representing the edges of l(x,y) detected within the closed boundary;
c) augmenting with additional data l(x,y), such that E(x,y) is a signal E'(x,y) defined at every sampling point over a range of data;
d) representing a portion of E'(x,y) as a signal f(t), where f~t) is a single ind~ de"l variable representation of at least a portion of the shape of said selected symbol string.
- 10b-A~

2~7796g The present Inventlon seeks to civold the problems Inherent In OCR methods Specifically, the slgnal to nolse ratio Inherent In Image derivation, or the imaging process, Is relatlYely small for a character, but relatively large compared to a larger character string. Moreover, word-to-word spacing tends to be larger than character to character spaclng, and therefore, allows improved isolatlon and therefore Identlficatlon of character strings as compared to identlfication of characters. OCR methods also tend to require several correct declslons about aspects of a character preparatory to a correct identification, Including identlfication of portlons of the character as as~enders, descenders, curves, etc., all of whlch are fallible. Identification by word shape in accordance wlth the Inventlon, Initially reciulres derivation of a slgnal representatlve of the ~vord shape, and comparlson of the derlved signal to known word shape slgnals.
Assumptions about the word are not made untll the compa~lsons occur, thereby eliminating the impact of Invalld assumptlons whlch may erroneously impact subsequent comparlsons and declslons. Furthermore, the present invention has the added advantage that the representatlve 1 Oc -~ 2077~69 derived signal is generally inYertibi~ without a significant loss of information content.
In examining potential uses of computer processed text, it has been determined that, at least in certain cases, deriving each letter of the word is not required for processing requirements. Thus, for example, in a key word search of a text image, rather than converting, via OCR
techniques, each letter of each word, and subsequently determining from the possibly flawed charader coding whether one or more key words are present, a computer might instead generate and compare the shapes of words with the shape of the keyword, and evaluate whether the key word is present by shape. The output of such a system would most likely present an ind;~dLion of the presence of the key words to an accuracy acceptable to a user. Furthermore, it is believed that the described method will have ., u~essi~ ,9 speed advantages over OCR methods.
The probability of an incorrect determination of a letter by OCR
methods may be relatively low, however, the probabilities are multiplicatively cumulative over an entire word. Hence, using OCR to convert words into character code strings, prior to searching for or recognizing the words may result in considerable error. The present invention is directed towards implementing word recognition in a manner similar to that which humans use while reading or skimming a text passage.
Furthermore, when using OCR the bitmap image of the letter is .on~. led to a character code, and the bitmap becomes irretrievable for examination by a user. However, in the described word shape process, several advantages over this method are noted. First, the bitmap is not irretrievably lost, and a reasonable representation of the bitmap remains so that a user may examine a reconstructed bitmap for word determination, if desired. Secondly, by utilizing complete words, each letter has the context of the word to assist in the word's comparison to other word shapes. The presence of a poorly formed letter in a word only minimally affects the total identifiability of the word shape signal, by slightly increasing the difference value between two compared signals. Thirdly, in small words, which have the greatest probability of false recognition, it is noted that ;. 2077969 such words tend to carry relatively little informati~n content. This is the reason that some indexing schemes, such as keyword searching, ignore the most common wo~ds in language as noise, with respect to the meaning of a text passage. Accordingly, the words in which errors are most likely to occur are the words which are of least importance in an information content sense. By contrast, the probability of failed detection is highest in OCR for longer words, i.e., words carrying the most information content, since the error is cu mulative over the length of the word.
OCR methods convert from a bitmap to a representative character code, thereby losing the informational content of the bitmap. In general, the process is not reversible to obtain the original bitmap from the character code. However, identification of words based on shape, as described in accordance with the present invention, tends to retain bitmap information, thereby enabling a reasonable reconstruction of the bitmap from the single variable signal. Hence, a significant portion of the bitmap information is retained by the single variable signal used to represent the shape of the selected text orcharacterstring.
Other objects and advantages of the present invention will become apparent from the following description taken together with the drawings in which:
Figure 1A shows a generalized system diagram of an image processing system in which the present invention would find use;
Figure 18 shows a block system diagram of the arrangement of system components forming one e",Lod;",e-,l of the inventive word shape recognition system;
Figure 2 shows an image sample of example text over which the inventive processwill be de,.,ol1,L,dl~d;
Figure 3 is a copy of a scanned image of the example text;
Figures 4A, 4B and 4C graphically illustrate the process used to determine the angle at which the example text is oriented in the image sample prior for further processing, while Figure 4D shows graphs of the responses taken from the example text, which are used to determine the 2~77~69 angle at which the example text is oriented in the image sa,~ple prior to further ~rv.~,~ing;
Figures 5A and SB respectively show the derivation and use of a graph examining the sample image of the example text to determine baselines of text within the image;
Figures 6A and 6B are flowcharts illustrating the procedures executed to d~:L~:r"-;"e the baselines shown in Figure 5A;
Figure 7 shows the scanned image of the example text with baselines indicated thereon after derivation from the data shown in Figures 5A and 5B;
Figure 8 is a flowchart illustrating the steps used in the application of a median filtertothe image of Figure 2;
Figure 9 is an enlarged pictorial ~ s~ld~ion of a portion of the image of Figure 2, illustrating the application of the median filter;
Figure 10 demonstrates the resulting image after appli~dLioll of a median filter, a process known herein as blobifying, to the scanned image of the example text, which tends to render character strings as a single set of connected pixels;
Figure 11 shows a subsequent step in the process, in whic~ lines of white pixels are added to the blurred image to clearly delineate a line of character strings from adjacent lines of character strings;
Figure 12 is a flowchart illustrating the steps required to add the white lines of Figure 11;
Figures 13A and 13B are flowcharts representing the procedure which is followed to segment the image data in accordance with the blurred image of Figure 1û;
Figure 14 shows the sample text with bounding boxes placed around each word group in a manner which uniquely identifies a subset of image pixelscontaining each characterstring;
Figures 1 5A and 1 5B illustrate derivation of a single independent value signal, using the example word "from", which appears in the sample image of example text;

20779~9 Figure 16 illustrates the resulting contours formed by ~he de,h/dlion processillustrated in Figures 10A, B;
Figure 17 illustrates the steps associated with deriving the word shape signals;
Figures 18A, 18B, 18C and 18D illustrate derivation of a single ~depende~Lva~uesignallusingtheexampleword nfromN;
Figures 19A, 19B, 19C and 19D illustrate derivation of a single i,~depende"l value signal, using the example word "red", which does not appear in the sample image of example text;
Figure 20 shows a simple comparison of the signals derived for the words ared" and Nfrom" using a signal normalization method;
Figures21A,21B,and 21Cillustratethedetailsofthediscrepancy in font height, and the method for normalization of such discrepancies;
Figure 22 is a flowchart detailing the steps used for one method of determining the relative difference between word shape contours;
Figure 23 is a flowchart detailing the steps of a second method fordetermining the relative difference between word shape contours; and Figures 24A and 24B are respective illustrations of the relationship between the relative difference values calculated and stored in an array, for both a non-slope-constrained and a slope-constrained comparison The Appendix contains source code listings for a series of image manipulation and signal processing routineswhich have been i" ~'E."e"~ed to de",on,l,ale the functionality of the present invention. Included in the Appendix are four sections which are organized as follows:
Section A, beginning at page 1, comprises the declarative or NincludeN files which are commonly shared among the functional code modules;
Section B, beginning at page 26, includes the listings for a series of library type functions used for management of the images, error reporting, argument parsing, etc.;
Section C, beginning at page 42, comprises numerous variations of the word shape comparison code, and further includes code illustrating -2û77969 alternative comparison te~hniques than those specifically cited in the following des.,i~ lion;
Sectior~ D, beginning at page 145, comprises various functions for the word shape extraction operations that are further described in the following description.
Referring now to the drawings where the showings are for the purpose of illustrating a preferred embodiment of the invention, and not for limiting same, Figure 1 A shows a generalized image processing system, which covers numerous situations in which the present invention may find advdnLageous use. Generally, a source image may be derived from a source image derivation system 2, which may be a scanner, facsimile device, or storage system. The source image is forwarded to a computer processing device 4 which may be any of several well known devices including the inventive device described herein. In response to commands entered at user interface 6, processing device 4 produces an output at an output device 8, which may be a printer, display, facsimile device or other storage device. In essence, as is shown in the upper portion of Figure 1, an input document is directed into a system and an output document is retrieved from it.
In the following description, an image is generally described as an image bitmap, where an image is represented as a plurality of image signals. These signals, commonly referred to as pixels, are typically denoted as black when intended to represent a corresponding mark or active position on a document from which they were produced. However, these constructs have been used for to enable the description of the present i nvention, and are in no way intended to I imit the domain of such to that of black-and-white or binary images Rather, the present invention is generally applicable across a broad range of image representation tech niq ues.
Figure 18, shows a system which embodies the present invention for deriving, defining, and comparing words in terms of their shapes. It will, of course, be recognized that each element of the system may be many devices, or may simply be a program operated within a single device.

2~77~69 Beginning with an input bitmap 10, whose source is indeterminate, and not part of the inYention, a bitmap of an image is initially directed to a ",~"ldlion system 12, in which words, or character strings, or other multi-character units of understanding, will be derived. Initially, the image bitmap passes through skew detector 14, which determines the angle of ori~"Lalion of text in the image. Using information about the orientation of the image, and the image itself, at text baseline processor 16, toplines and baselines of the text are determined, so that upper and lower boundaries of lines of text within the image are identified. At median filter 18, the function referred to as nblobifyN is performed, which operates on the image so that each word group in a line may be treated as a single unit.
As used herein, "wordn, "symbol stringn or "character string" refers to a set of connected alphanumeric or punctuation elements, or more broadly, signs or symbols which together form a single unit of semantic understanding. It will be appreciated that these terms may also be used to refer to the images thereof. Such single units of understanding are characterized in an image as separated by a spacing greater than that which separates the elements, signs or symbols forming the unit. To the blobified image, a set of white lines are added at block 20, to clearly separate adjacent lines of text. The white lines are based on baseline determinations provided by processor 16. Using this information, i.e., the blobified words, which are clearly separated from adjacent words and words in adjacent lines, a bounding box is defined about the word at block 22, thereby identifying and enclosing the word.
Thereafter word shape signal computer 24 derives a word shape signal representing the indiYidual words in the image, based on the original image and the bounding box determinations. This information is then available for use at a word shape comparator 26, for comparing word shape signals reple~el~ldLi~ of known words from a word shape dictionary 28, with the as yet unidentified word shape signals. In an alternative embodiment word shape comparator 26 may be used to compare two or more word shapes determined from image 10. More importantly, word shape comparator 26 is not limited to the comparison of word shapes from . 2077g6g unrecognized strings of characters to known word shapes. In a simplified context, comparator 26 is merely an apparatus for comparing one word shape against an~ther to produce a relative indication of the degree of similarity between the two shapes.
In general, a method accomplishing the invention includes the following steps. Once orientation of the image is established and line spacing and word group spacing is established, each word can be surrounded by a bounding box. A reference line is then created ex~ d;"g through the character string image. The reference line may be a block having a finite thickness ranging from two-thirds of the x height to one-third of the x height, or in fact it may have a zero width. At the resolution of the image, the distance from the reference line to the upper edge of the text contour or bounding box is measured in a direction perpendicular to the reference line. Similarly, measurements may be made from the reference line to the lower bounding box edge orto the text contour along the lower portion of the word, whichever is closer. Because the set of values derived computationally can be expressed in terms of position along the horizontal axis versus length, the signal can be considered a single independent variable or one dimensional signal. Either or both of these sets of values may be used to describe the word shape. Additionally, although possibly less desirable, it is well within the scope of the invention to measure the distance of a per~ d;cular line drawn from the top of the bounding box or the bottom of the bounding box, to the first contact with theword orthe reference line, asdesired.
With a system and process for word shape derivation given, the invention may also be considered mathematically. Considering image data i(x,y), which in one common case could be an array of image data in the form of a bitmap, a character set is identified in one of many methods, perhaps as described above, which defines a boundary enclosing the selected symbol string within a subset of the array of image data. From i(x,yJ, an edge signal e(x,y), which represents the edges of i(x,y) detected within the closed boundary, is derived. The edge signal is augmented by adding additional data to i(x,y) so that e(x,y) is a signal e'(x,y) defined oYer ~ 2~ 69 its entire domain with respect to a single dimension or variable within the closed boundary. One, two, or more signals may be derived from e'(x,y) which are each one dimensional signals J'(tJ, where g is a function of parameter t which is a reference frame dependent parameter.
It is important to reali2e that the mathematicai process used for the derivation of the one dimenslonal signal is essentially reversible up to the information it contains, e.g., a bitmap may be reconstructed from the upper and lower bitmap contours, as illustrated in Figure 16. It will be noted that if the reference has a finite thickness and is therefore taken out of the image, that that portion of the image is not identifiable, however, if it has a zero width the information still remains.
A recognition dictionary, or look up table of word shapes, can clearly be created through use of the described process. The process can be operated on using either scanned words as the source of the information, or in fact, they can be computer generated for a more "perfect" dictionary.
To demonstrate the process of the invention, at Figure 2, a sample image, taken from a public domain source is shown, having several lines of text contained therein. Figure 2 demonstrates approximately how the image would appear on the page of text, while Figure 3, shows a scanned image of the page, which J~",on,Lrdtes an enlargement of the image of a bitmap that would present problems to known OCR methods.
Looking at, for example, the image of the word 5û "practitioner" in the first line of the text image, it may be seen that several of the letters run together. Also, at the lower left hand portion of the image, circled and numbered 52, noise is present. Looking at the word ~practitioner's", circled and numbered 54, the running together of a punctuation mark and a letter is further noted.
In one possible embodiment of the invention, skew detector 14 may be implemented in the following manner. A general method for d~L~r",i"i"g the orientation of the text lines in the image, looks at a small number of A~

~77969 randomly selected edge pixels (defined as a black pixel adjacent to at least one white pixel), and for each edge pixel considers, at Figure 4A, a number of lines, 56a, 56b-; 56c being examples, extending from the pixel at evenly spaced angular ir,-l...,e"l~ over a specified range of angles. The edge pixels are selected randomly from the set of all image pixels by the fun*ion Rand~",Cdg~rixel0 tAppendix, page 243). Figures 4A (see lines 56a, 56b, 56c), 4B (see lines 58a, 58b, 58c) and 4C (see I ines 60a, 60b, 60c) represent aseries of increasingly smaller angular ranges over which the above ",~ iolled technique is applied to illustrative edge pixels to accurately determine the angular orientation of the text within the image.
Subsequentto finding edge pixels and defining the lines, skew detector 14 traces the path of each line, determining the lengths, in pixels, of strings of successive black pixels which are intersected by the line. Upon reaching the image boundary, an average black pixel string length is calculated by summing the lengths of the individual strings, and dividing the sum by the total number of distinct strings which were found. This operation is carried out for all the lines, thereby arriving at an average black pixel string length for each line extending from the selected edge pixel. These lengths are plotted on Figure 4D as curve A, showing minima at approximately 0 and 3.14 radians. Curve A is a graphical represe,)~ation of the summationl averaging function over each of a series of angled lines extending from the edge pixel, and spread over a range from 0 to 2n radians. Once a first minimum has been located, verification of the minimum (in the example, appro.~,..,dl~ly O radians) is achieved by determining whether a second minimum exists at approximately n radians from the first minimum. Upon verifying the existence of a second minima (in the example, approximately 3.14 or n radians), a coarse skew angle is identified. Subsequently, it is necessary to more closely determine the skew angle of the text. This is accomplished by utilizing a number of lines which extend from a randomly selected edge pixel, where the lines differ by smaller angular increments, and the angular range is centered about the coarse skew angle. However, the fine skew angle may be determined by analyzing the total number of black pixels contained along a predetermined length of the lines. More _19_ specificOlly, the number of pixels over a unit distance are piotted as curve B
on Figure 4D, and the fine skew angle is determined by identifying the maxima of the c~rve. In other words, the point of the curve where the highest con~el~,dLion of black pixels per unit line length exists, more accurately represents the angle of the text lines in the image. As shown by curve B, this results in a fine skew angle of approximately 0 radians, where the line intersects with the most black pixels along its length, and therefore is ,~Jr~ "laL;~ of the closest angle of orientation that needs to be d~l~".,;ned.
Alternatively, the skew angle may be d~ " .i"~d as indicated by the NewFineO function (Appendix, page 245~, which determines the skew angle using multiple iterations of the procedure described with respect to the fine angle determination. As indicated by Figures 4A, 4B, and 4C, each ite~ation would also use lines coYering an increasingly smaller angular range, until a desired skew angle accuracy is reached. In the imple",~ Olion illustrated by Figures 4A, 4B, and 4C, the desired accuracy is achieved by a series of three iterations, each using a series of 180 distinctangles about the selected edge pixel.
In the next process step, iilustrated in the graphs of Figure 5A
and Figures 5B, text baseline processor 16 identifies the characteristic lines, upper topline and lower baseline, of each line of text. The process steps executed by text baseline processor 16 are illustrated in detail in Figure 6A
and 6B The histogram of Figure 5A, shown to the left along the image, is derived by examining lines, at the resolution of the image, and oriented parallel to the skew orientation of the image, as defined by the previously determined skew angle. These parallel lines spanning the image are used to determine the number of black pixels intersected by each of the lines.
Along lines passing through inter text line spaces, no black pixels should be i"lel~epled, while along lines through the text, large numbers of black pixels should be intercepted.
More specifically, the function BaseLines~), (Appendix page 1 6û), first finds the coordinates of a "main" line, block 142, constructed through the center of the image and perpendicular to the text lines, as determined -2û -2~9~
bytheskewanglepassedtothefunctionasshownbyblockl40. Next,Line Engine Procedure 144 is executed, where by proceeding along the main line from one end ta the other, at a series of points along the main line, perpendicular branch lines are constructed which extend outwardly from the main line for a fixed distance, block 146. Along the branch lines, the number of black verti~al edge pixels are counted, block 148, and the number of black pixels intersected by the lines are counted, block 150, and summed for the opposing pairs of lines, block 152. Black vertical edge pixels, as counted by block 148, are defined as black pixels having a white neighboring pixel at either the upper or lower neighboring pixel position.
LineEngine()procedure 144 is repeated until all points, and associated branch lines, along the main line have been processed, as determlned by decision block 154. An x-height value may be returned from this procedure, which will subsequently be used by the word shape computer 24.
Subsequently, the counts for all the branch lines are analyzed to determine the branch line pairs having the highest ration of black vertical edge pixels to black pixels. In general, those lines having the highest percentages would correspond to lines lines passing along the upper and lower edges of the characters which form the text lines. As illustrated in the enlarged view of Figure 5B, a definite distinction exists between those branch lines having a high vertical edge pixel ratio, line 82, and those having a low ratio, line 84. Application of a filter mask and comparison of the maximum peaks within the mask enables the identification of those lines which represent the text toplines and baselines, for example, line 82.
The process is implemented in the maxFilter.c module, beginning at line 57, the code for which is also incorporated in the newBaselines.c module at line 274, page 214. An additional test may also be applied to the histogram operation of step 150. This added test, a boolean test, may be used to assure that a minimum run of black pixels was detected during the analysis of the line. For example, a A~

2~77~6g -flag, which is cleared at the ;tart of each branch line analysis, may be set whenever a series of five sequential black pixels are detected along the line.
Thistestwouldassurethatsmallnoiseorimageartifactsarenotrecognized as baselines due to a high vertical edge pixel ratio.
As an alternative method, it is possible to utilize the total number of black pixels Iying along the branch lines to determine the locations of the baselines. Using histogram curve BL, which le~,~se~ the number of black pixels counted along the branch lines, it is possible to determine which branch lines have the most black pixel intersections.
Applying a threshold of the maximum allows the determination of the upper and lower characteristic line pairs for each text line. Hence, the rising and falling portions of the hi,~ l dlll curve BL, constitute the characteristic lines of the text, and the threshold would be used to specifically identify the localized maxima surrounding an intervening minima, thereby enabling identification of the baseline positions which would be used for further processing. More importantiy, this alternative approach, illustrated as step 162, may be utilized to identify the upper and lower baselines of a baseline pair, based upon the slope of the BL histogram curve. It is important to note that there is little additional processing associated with the identification step as the histogram information was collected previously during step 150. Once the preliminary characteristic line or baseline pairs are identified, block 162, a verification step, block 164, is executed to verify that the baseline pairs are separated by more than a minimum distance, the minimum distance being established by calculating the average line pair separation for ail line pairs in the image. After verification, the valid baseline information is stored by output block 166 for later use by the white line addition and se~",t!"Lalion blocks, 18 and 20, respectively.
An important advantage of these baseline determination methods, are that they are highly insensitive to noise or extraneous marks in the interline space. Figure 7 shows the result of the baseline determination on the example image of the sample text, showing that baseline pair, baseline and topline Bn and Bn', respective~y, have been 207796~
located on the image, indi~ating thos~ portions of the image in which a predominant portion of the text occurs. While some portions of the character ascender strokes are outside the baselines, no detriment to the remainder of the process is noted. Of course, a smaller threshold value might enable the system to capture more of the ascending strokes.
With reference again to Figure lB in conjunction with Figures 8 and 9, the next process step is a word group isolation step. A filter 18 is applied to a copy of the image which results in an image that tends to render the word into blobs distinguishable from one another. The filter is applied with a small window, to each area, to render as black those areas that are partly black. As shown in Figure 8, the blobify function (Appendix page 165) first initializes mask variables which establish the mask size and angle, block 18û, and then processes the upper scanline to initialize the data array, block 182. Median filtering is a~c~.,.pl;,~led by sequentially moving the mask window through the image, blocks 184 and 186, and whenever the number of black pixels appearing in the window exceeds a threshold value, the target pixel, about which the window is located, is set to black. Figure 9, which illustrates some examples of the filter process, has a mask window 200 placed over a portion of the image. For example, with a twenty percent threshold and a generally rectangular mask having twenty-one pixels, arranged at an angel approximately equal to the skew de~el ...;ned for the text, the result of filtering in window 200 would be the setting of pixel 204 to black. Similarly, window 206, which primarily lies within the intercharacter spacing between the pixel representations of the letters "rN and nO", would cause pixel 208 to be set to black. On the other hand, window 210, which lies in the region between word groups, would not have a sufficient number of black pixels present within the window to cause pixel 212 to be set to black. The size, shape and orientation of mask window 20û is optimized to reduce the filling in between text lines, while maximizing the fill between letters common to a single word.
As illustrated by Figure 10, the result of the median filtering is that the relatively small spacing between characters in a word generally becomes inconsequential, and is filled with black pixels. Words become a single connected set of pixels, i.e., no white sp2ces completely separate characters in a single word. However, the relatively large spacing between character strings~r between words, is a larger space outside of the ability of the filter to turn into black, and therefore serves to distinguish adjacent symbol strings. With reference now to Figures 7 and 10, it can be seen that the first two words of the sample text, "A" and "practitionera have been ~blobifiedN, as this process is referred to, so that, for example, the np~ of "practitioner" is no longer separated from the Nr" of that word. (Compare, Figure 3). Once again, despite the blobifying or blurring of characters, NA nd "practitioner" remain as discrete blobs of connected symbols, or words.
With reference again to Figure 1B, as an adjunct to this step, white line addition 20, superi"~poses upon the blobified image of Figure 10 a series of white pixel lines to make certain that lines of text are maintained separately from adjacent lines of text (i.e., no overlapping of the filtered text lines). With reference to Figures 10 and 11, noting the circled areas 258 and 258', a combination of an ascender and descender has resulted in an interline merging of two words. The text line overlap illustrated in area 258 of Figure 10 is exactly what is eliminated by superimposing the white lines on the blobified or filtered image.
This superposition of white lines operation, the outcome of which is illustrated by Figure 11, is carried out by the process illustrated in Figure 12 as executed in the ~rawMiddleLines() function (Appendix page 233). Generally, white lines WL are added to the image, approximately halfway between adjacent baseline and topline pairs, to assure that there is no cross-text line blobifying. Once again, Figure 11 shows the result of white line addition to the blobified image of Figure 10.
Referring now to Figure 12, white line addition block 20 begins by initializing variables in step 280 and subsequently reads in the topline location from the baseline information of the first text line. The topline information is discarded, block 282, and the next baseline and topline locations are popped from the storage stack or list, blocks 284 and 286, respectiYely. With respect to the image, this baseline-topline pair respectively represents the bottom and top of adjacent text lines. Next, at 2~77969 step 288, the point Iying at the ~enter of the pair is locat~ to provide a starting point for the white lines which are drawn from the center of the image in an out~vard direction. The endpoints of the white lines are calculated in step 290, using the skew angle d~le,..,i"ed by skew detector 14 of Figure 1B White lines are drawn or superimposed on the blobified image at step 292, and the process is continued until all text lines have been effectively sepa rated, as control led by test bl ock 294.
With reference again to Figure 1B, as a result of the blobify or median filtering, the position of bounding boxes about each connected set of pixels formed in the blobify step may be determined. Bounding boxes are placed only about those connected components or words that are in a text line Iying between the superi""~osed white lines. The bounding boxes are placed at the orientation of the text line, by identifying the extreme points of each group of connected pixels in the direction of the text line, and in the direction orthogonal to the text line, as opposed to the image coordinate system. This operation is performed by the function FindBorders(), (Appendix, page 172). Generally, the FindBorders function steps through all pixels within the image to find the bounding boxes of the connected characters (Paint Component), to determine the coordinates of the upper left corner of each box, as well as the length and width of the box.
Referring now to Figures 13A and 13B, which detail the FindBorders() procedure, segmentation step 22 begins by placing a white border completely around the filtered image, step 300. This is done to avoid running outside the edge of the array of image pixels. Next, pixel and line counters, x and y, respectively, are initialized to the first pixel location inside the border. Calling the ReadPixel procedure, block 304, the pixel color (black or white) is returned and tested in block 306. If the pixel is white, no further processing is necessary and processing would continue at block 322. Otherwise, the PaintComponent() procedure (Appendix, page 171) is called and begins by storing the location of the black pixel in a queue, block 308. Subsequently, in a copy of the image, the pixel is set to white and the boundaries of the box, surrounding the connected pixels or 2077~69 ~c""pon~"Ls, are updated, blocks 310 and 312, respectively. Next, adjoining black pixels are set to white, block 314, and the locations of the black pixels are added to the~end of the queue, block 316. At block 318 the queue pointers are tested to determine if the queue is empty. If not empty, the next pixel in the queue is retrieved, block 320, and processing continues at block 312. Otherwise, if the queue is empty, all of the connected black pixels will have been set to white and the box boundaries will reflect a box which encompasses the connected components. Subsequently, the boundaries of the box which encompasses the word segment are verified and may be adjusted to an orthogonal coordinate system oriented with respect to the skew of the text lines, block 322.
It will no doubt be apparent here that while finding each text line is an integral part of the described method, and serves to make the present embodiment more robust, other methods of deriving the information acquired by that step are possible. The primary use of the text line finding function is a) to determine x-height, and b) define the white line addition for separating interline blobs. Certainly this step may be removed, with a sacrifice in robustness, or other means of deriving the necessary information may be available.
The looping process continues at block 324 which checks pixel counter x to determine if the end of the scanline has been reached, and if not, increments the counter at block 326 before continuing the process at block 304. If the end of the scanline has been reached, pixel counter x is reset and scanline counter y is incremented at block 328. Subsequently, block 330 checks the value of scanline counter y to determine if the entire image has been processed. If so, processing is completed. Otherwise, processing continues at block 304 for the first pixel in the new scanline.
Thus, as shown in Figure 14, for the word "practitioner" the extremities of the connected character image define the bounding box.
Once bounding boxes have been established, It is then possible at this step, to eliminate noise marks from further consideration. Noise marks are determined: 1) if a bounding box corner is outside the array of image pixels (Appendix, page 171); 2) if a box spans multiple text lines in the array 20779~9 (Appendix 229), or lies ~,..,pl~l~ly outside.a text line; 3) if boxes are too small compared to a reference , in either or both longitudinal or latitudinal directions, and accordingly are discarded. Noise marks 70 and 72 and others will be not be considered words. The OnABaseline() function (Appendix, page 229) is an example of a function used to eliminate those boxes Iying outside of the baseline boundaries.
With reference again to Figure 1 B, at word shape computer 24, a signal representing the image of a word, or at least a portion thereof, now isolated from its neighbors, is derived. The derived signal is referred to as a word shape contour. The shape contour for each word is determined using the MakeShell() function (Appendix, page 228). As illustrated in Figure 15A, this function first moves along the top of each bounding box, and starting with each pixel location along the top of the box, scans downward relative to the page orientation, until either a black pixel, or the bottom of the box, is reached. A record of the set of distances d between the top of the box and the black pixel or box bottom is maintained. The set of distances d, accumulated over the length of the box, constitutes the top raw contour of the word shape Subsequently, a bottom raw contour is produced in a similar manner as illustrated in Figure 1 SB, for the same word depicted in Figure 15A, by sequentially moving across the bottom of the box, and looking in an upwards direction, for either the first black pixel or the top of the bounding box.
With reference now to Figure 17, at block 100 which preferably operates on the actual image as opposed to the filtered image, which could be used in this step, one or more reference lines are established through each word. In other terms, the data lep,~se,~ g the symbol string is augmented, so that it is defined over the range of the symbol string. In one embodiment, a blackout bar, which may have a finite thickness or a zero thickness is constructed through the word, preferably having an upper limit or reference line at approximately two thirds of the x height, and a lower limit or reference line at approximately one-third of the x height (which was determined at the baseline determination step). At contour calculation 102, a set of measurements is derived, for the distance d between the upper or lower edge of the bounding box, and the word, or the nearer of the reference lines closer edge of the black out bar. The calculations measurements are made at the resolution of the image. With reference to Figure 18A, where the calculations measurements are illustrated pictorially, it can be seen that the reference lines serve to allow the signal that will ultimately be derived from this step to be defined at eYery sampling position over the length of the word. In a preferred one embodiment, the calculations measurements of d are actually generated from the contour data derived in accordance with Figures 15A, 15B
previously collected, and are adjusted to limit the distance d with either the upper or lower edge of the blackout bar as indicated. In the embodiment shown in Figure 18A, measurements are made from the upper line of the bounding box to the upper reference line or the word, although this is not a requirement. Thus, for example, the measurement could alternatively be made from the reference line to either the upper or lower bounding line, or the character. Figure 18B better shows how the set of measurements is used to form the signal output from block 1û4 The contour is represented as a set of measurements distance d', relative to the reference line.
Measurement d' is therefore derived from the measurements shown in Figure 18A, which designate the stopping point of line d, and the known position of the black out bar. Calculating the distance relative to the reference line enables scaling of the word shape contours to a common x height, thereby facilitating any subsequent comparison of the shapes.
Accordingly, the distances d' represent a measurement from the reference line or blackout bar to the outer limits of the letter, and in the absence of a letter, provide a zero measurement. These measurement might be derived directly, but the proposed indirect methods appear easier to implement.
Figures 18C and 18D shows that the sets of d' values can be plotted on a graph to form a one dimensional signal or curve representing the word shape. Details of the contour determination are contained in the function StoreOutlinePair() beginning in the Appendix at page 255. Figure 16 is an image of the contour locations as established for the text sample of Figure 2. It is important to note the informational content of Figure 16, where, for the most part, it is relatively easy to recognize the words within the passage by their contours alone.
In stuo~ies of the infGrmation delivered by the appearance of English language words, it has been determined that in a majority of cases, words can be identified by viewing only approximately the top third of the image of the word. In other words, the upper portion of the word carries with it much of the information needed for id~llLiri~alion thereof. In a significant portion of the remainder of cases, words that are unidentifiable by only the upper third of the image of the word, become identifiable when the identification effort includes the information carried by the lower third of the image of the word. A relatively small class of words requires information about the middle third of the word before identification can be made. It can thus be seen that a stepwise process might be used, which first will derive the upper word shape signal or contour, second will derive the lower word shape signal or contour, and thirdly derive a word shape signal central contour (from the reference line towards the word or bounding box), in a prioritized examination of word shape, as required. In the examples of Figure 18A, 18B, and 18C, the word afrom" is fairly uniquely identifiable from its upper portion only. In the examples of Figure 19A, 19B, 19C and 19D, the word Ured'' is less uniquely identifiable from its upper portion, since it may be easily confused with the word arod", and perhaps the word "rad". While the lower portion of the letter naa may distinguish "reda and arad", it is doubtful that the lower portion of the letter "o" will distinguish the words ared" from ''rodU.
However, the central portions of aredN, "rada, and aroda are quite distinct.
With reference again to Figure 1B, the next step performed is a comparison at word shape comparator 26. In one embodiment, the comparison is actually several small steps, each of which will be described.
With reference to Figure 20, generally, the two word shape signals, one a known word, the other an unknown string of characters are compared to find out whether or not they are similar. However, in this case, signal R is the upper contour of the word "red", while signal F is the upper contour of the word afroma. Actually, reiatlvely few signals could be expected to be -2~79~9 exactly identical, given typical distinctions between character fonts, reproduction methods, and scanned image quality. However, the word shape signals to be compared may be scaled with respect to one another, so that they have the same x-heights. This is achieved by determining the x-height of the pair of word shape contours to be compared. Once determined, the ratios of the x-heights are used to determine a scale factor to be applied to one of the contours. As the x-height is a characteristic measurement for fonts, it is used to determine the scaling factor in both the horizontal and vertical directions. An example of the scaling operation is found in the fontNorm.c file beginning at line 172, where the StoreOutlinePairO function carries out the scaling operation in both the x and y, horizontal and vertical, directions. Alternatively, the shape signals may be compared without normalization and a weighting factor imposed upon the portion of the measured difference due to the unequal lengths.
Furthermore, the amplitude or height of the signals has been normalized to further reduce the impact of the font size on the word shape comparison.
Referring next to Figures 21A - 21C, which illustrate details of the ascender/descender normalization operation, each of the shape signals are normalized based upon a common relationship between the ascender and descender heights and the x-height of the text characters. As illustrated, the actual ascender heights of characters printed with s~rrose~ly similar font size, or what is now an appropriately scaled font size, may be slightly different. This occurs as a result of type faces or fonts which are small on body or large on body, implying that similar characters exhibit variations in height across fonts that are the same size, for example 24 point fonts. As an illustration, distance dl in Figure 21A represents the difference in ascender height for two occurrences of the letter "h N
Likewise, distance d2 illustrates a similar difference between the heights of the letter "fN in Figure 21B. As illustrated in Figure 21C, the typical character may be broken into three sectlons, ascender portion 390, x~height portion 392, and descender portion 394 In addition, the relative heights of these sections are illustrated as a, c, and b, respectively. Again, the normalization operation applied to the shape contours is found in the -3û-20~7969 fontNorm.c module, beginning at page 183 of the Appendix. Applying the operations described with respect to StoreOutlinePair() function, page 255 of the Appendix,~the areas of the contour Iying above the x-height are scaled as follows:
a + c Similarly, the descenders are scaled by the following equation:
a + 1~ 1 where, in both cases, the Yalue used in the numerator (1.5) is arrived at based upon observation of the relationship between ascender or descender heights and the x-height. Also included within the StoreOutlinePair() function is an operation to remove the portions of the contours which do not represent portions of the text string. These regions lie at the ends of the bounding boxes illustrated in Figure 14. For example, the box surrounding the word "practitioner" in Figure 14 can be seen to extend beyond the actual word image. As further illustrated at the ends of the word "fromN in Figures 18A - 18D, the contour does not contain useful information. By removing these regions from the contour shape, less error will be introduced into the comparison operations.
Subsequent to the normalization operation, standard signal pr~.~e~ g steps can be used to determine the similarity or dissimilarity of the two signals being compared. Alternatively, the following equation may be used:
ro (~ g'(~)2d~
where ~stnng iS the difference value between the two signals f(x) is the known signal; and g'(x) is the unknown signal.
In a simple determination, the difference could be examined and if it is close to zero, such would be indicated that there would be almost no difference between the two signals. However, the greater the amount of difference, the more likely that the word was not the same as the word to which it was bei ng compared that val ue wo u Id be.

It is important to note that the embodiments described herein, as supported by the code listings of the Appendix, compare the word shape contours using the upper and lower contours for each word in conjunction with one another. This is an i"".le",e"Ldlion specific decision, and is not intended to limit the invention to comparisons using only the top and bottom contours in conjunction with one another In fact, sufficient information may be contained within the upper contours alone so as to significantly reduce the requirements for a comparison of the lower contours, thereby saving .ol1siderable processing effort.
The steps of this simplified comparison method, as first contemplated, are illustrated in Figure 22. Beginning at step 41û, the contour for the first word shape is retrieved from memory, and subsequently, the second word shape is retrieved by step 412. Next, the centers of gravity of the word shapes, defined by the upper and lower contours, are determined and aligned, step 414. The purpose of this step is to align the centers of the word contours to reduce the contour differences that would be attributable solely to any relative shift between the two sets of contours being compared. The center of gravity is determined by summing the areas under the curves (mass) and the distances between the contours (moments) which are then divided to give an indication of the center of gravity for the upper and lower contour pair. Once determined for both sets of contour pairs, the relative shift between the pairs is determined, step 416, and the contours are shifted prior to calculating the dirreren~e between the contours. The shifting of the contours is necessary to reduce any error associated with the establishment of the word shape boundaries and computation of the word shapes at block 24 of Figure 1B.
Step 418 handles those regions Iying outside the overlapping range of the shifted contour pairs, determining the difference against a zero amplitude signal in the non-overlapping regions. This is done by summing the squared values of the, upper and lower, contours at the non-overlapping ends of the contours. Subsequently, the overlapping region of the contours are compared, step 42û. The difference in this region is determined as the sum of the squared differences between the upper curves and the lower 2~77969 curves, as shown in the function L2Norm() on page 100 of the Appendix.
Next, the values returned from steps 418 and 420 are added to determine a sum of the differences over the complete range defined by the shifted contours. This vaiue may then be used as a relative indication of the similarity between the contour pairs for the two word shapes being compared.
An alternative to the center-of-gravity comparison method, uses a signal processing function known as time warping, as described in the article "Performance Tradeoffs in Dynamic Time Warping Algorithms for Isolated Word Recognition", by Myers, Rabiner, and Rosenberg, IEEE
Transactions on Acoustics, Speech, and Signal Processing, Vol. ASSP-28, No.
6, December 1980, and the book, "Time Warps, String Edits, and Macromolecules: The Theory and Practice of Sequence Comparisona, by Sankoff and Kruskal, Addison-Wesley Publishing Company, Inc., Reading, Massachusetts, 1983, Chapters 1 and 4, both specifically incorporated herein by reference, may be used to provide for compression and expansion of points along the contours until the best match is made Then a score is derived based on the amount of difference between the contours being compared and the stretching required to make the contours match. Once again, the score providing a relative indication of the match between the two signals being compared.
Referring now to Figure 23, which depicts the general steps of the dynamic warping method, the method relies on the use of a iirr~,ænce array or matrix to record the distances between each point of the first contour and points of the contour to which it is being compared. As illustrated in the figure, and detailed in the code listings contained in the Appendix, the process is similar for all of the measures which may be applied in the comparison.
First, the organization of the code is such that a data structure is used to dynamically control the operation of the various comparison functions. The structure DiffDescriptor, the declaration for which is found on page 9 of the Appendix (see diff.h), contains variables which define the measure to be applied to the contours, as well as, other factors that will be 20779~9 used to controi the compa.rison. These factors include: normalization of the contour lengths before comparison; separate comparisons for the upper and lower contours; a centerWeight factor to direct the warping path; a bandwidth to constrain the warp path; a topToBottom ratio which enables the top contour comparison to be weighted more or less with respect to the bottom contour comparison; and a hillToValley ratio to selectively control weighting the contour dirrt~ .eS when an unknown contour is being compared to a known or model word shape contour.l,,l~,,ur~Ldtion of the various factors is actually completed in the diff2.c module at page 56 of the Appendix, although descMain.c at page 49 proYides an illustration of the i~ ".r~ldlion of the factors.
In generai, each measure ;" r~e.".:"l, a .u",pari~on technique, however, each is optimized for a specific type of dynamic comparison, for example, a slope limited dynamic warp having a non-unitary centerweight and a topToBottom weight greater than one. The first level of selection enables the use of a slope-constrained warping function for comparison, an unconstrained warp, or a simple, non-warped, comparison. Within both of the warp comparison methods, there are both separate comparison functions, where the top and bottom contours are warped independently, and parallel comparison functions, where the warp is applied to both the top and bottom contours simultaneously. Specific details of the comparison functions are generally ~ull; ,ed within the newMatch.c file beginning at page 101 oftheAppendix.
In the general ~",bo.li",~r,L, the dynamic warping process starts byallocatingspaceforthepathldistancearray,step450,whichwill holdthe distance values generated during the comparison and warping of one word shape contour with respect to another. After allocating space, the border regions of the array must be initialized as the process used by all the warping measures is an iterative process using data previously stored in the array for the determination of the cumulative difference between the contours. At step 452, the array borders a re i n itialized . In itial ization of the first row of the array entails the determination of the square of the difference between a first point on the first contour and each point on the second contour. SIJhcequ~nt to boro~r initialization, the coiumn and row index values, L1 and L2"~ e-Lhl~ly, are reset to 1 to begin processing the individual, non-border, points along the contours.
r~u~essi"g of the contours proceeds at steps 458 through 464, where the dirr~,~"~ in distance between each point along the second contour, with respect to a point on the first contour is calculated.
~reu._., this difference, or distance, is calculated and then summed with a previously determined difference value. In addition, some of the previously d~ ""i,)ed difference values may be weighted differently, for example, in one ~",Lodi,.,~,)l weights of the difference values along the array diagonal may be modified by a centerWeight weighting factor. As an illustration, the operation of the NewMatch() function, beginning at line 106 on page 103, at first, the distance (rest) is calculated as the sum of the squares of the differences between a point on the first contour and a point on the second contour, over the upper and lower contours, where the top contour di rr~,~nce is weighted by the topToBottom variable. This distance (rest) is used in subsequent iterations to determine the horizontal, vertical and diagonal difference values in the loop beginning at line 137 on page 103. To determine each of these values, the current distance value, represented by rest, would be added to the previous values in the down, left, and down-left array positions, the down-left position Yalue being the diagonal position which is weighted by the centerWeight factor as previously described. Referring to Figure 24A, which illustrates the positional relationship between a previously determined value X, at array location 502, and subsequent array locations, the value X might be added to the difference values of subsequent locations to accumulate the total dirr~e,~e. calculations is shown. When calculating the difference value for array location 504, the value in location 502 would be used as the down value. Similarly, when calculating the value in location 506, the value of location 502 would be used as the center-weighted down-left, or diagonal, value. After calculating the three difference values, steps 458, 460, and 462, the process continues by selecting the smallest of the three values, step 464, for insertion into the current array position, step 466. As illustrated in -the Appendix at iine 144 of page 103, the FMi,~() function from page 101 returns the minimum of the three values previously calculated, the value being inserted into the storage array pointed to by pointer dc.
Subsequently, the process illustrated in Figure 23 continues by determining the differences between the point on the first contour, represented by L1, to points on the second contour"~pres~,~led by ~2.
Decision step 468 controls the iterative processing of the points along the second contour by testing for the end of the contour, or swath. In the ;..,ple."enlaLion shown in the Appendix, the index variables i and j are used in place of L1 and L2 to control the difference calculation loops. As indicated in the codeforthe NewMatch function beginning on page 102 of the Appendix, the swath is referred to as the bandwidth, and is determined by a desired ba~,dv~illl, which is adjusted for the slope defined by the contour lengths (see page 102, lines 83-89). If no limit has been reached, processing for the next point would continue at step 458 after the value of L2 was in.,t!",e"Led at step 470. Similarly, decision step 472 controls the processing of each point along the first contour, in conjunction with incrementing step 474. Once all the points have been processed with respect to one another, as evidenced by an affirmative response in step 472, the relative difference score, best score, is contained in the farthest diagonal position of the array (L1, L2~. Subsequently, the value determined at step 476 is returned as an indication of the dynamically warped difference between the contours being compared.
The code i",F!~."~"~dlion found in the NewMatch() function on page 103 of the Appendix has optimized the execution of the aforedescribed warping process by reducing the large two-dimensional array to a pair of linear arrays which are updated as necessary. Due to this modification, the minimum difference, or best score, for the Wdrp comparison value is found in the last location of the one-dimensional array Furthermore, the final difference value, dc, may be subsequently normalized to account for the length differences between the two sets of contours being compared. Finally, such a value might subsequently be compared against a threshold or a set of similarly obtained difference 2û77969 _ values to determine whether the contours are close enough to declare a match between the words, or to determine the best match from a series of word shape comparisons In yet another embodiment, the dynamic time warping process previously described may be altered to compare the difference values contained in the difference array to a thresho!d value on a periodic basis.
Upon cc l"parisOn, the process may be discontinued when it is determined that sufficient difference exists to determine that the contours being compared do not match one another, possibly saving valuable processing time. Moreover, the sequential operation of word shape comparator 26 might be done in conjunction with sequential output from word shape computer 24, thereby enabling the parallel processing of a textual image when searching fora keyword.
Having described a basic implementation of the dynamic warping comparison measures, the distinctions of the other dynamic warp comparison methods included in the Appendix and the application of the control factors previously mentioned will be briefly described to illustrate the numerous possible embodiments of the present invention. First, the method previously described may also be implemented with the slope of the warp path being constrained as it moves across the array. Details of the i"~ ",e"lalion are found in the SlopeCMatch() function beginning on page 111 of the Appendix. This measure is further illustrated graphically in Figure 24B, where the value of array location 512, X, may be added to only the three subsequent array locations shown. For example, X may be added to array location 514, when considered as the d211 value for location 514.
The nomenclature used for the variable names, and followed in the figure, is as follows: d211 refers to the array location which is down 2 rows and left one column, d111, refers to the lower left diagonal array location, and d112 refers to the array location that is down one col umn on left 2 rows from the current array location. In a similar manner, X may be added as the d112 value for the calculation of the cumulative difference value for array location 516.
-2~77969 As is apparent from a ~ulllparison of Figures 24A and 24~, the slope constrained warping measure limits the warping path which can be followed during~the generation of the cumulative difference value. The reason for implementing such a constraint is to prevent the warping process from removing, or compressing, a large area of one of the two contours being compared, without imposing a significant "costN to such a compression.
Next, the method previously described with respect to the parallel warping process may also be implemented on only one pair of contours at a time, for exampie, the upper contours of two word shapes.
The functions SepMatch() and SepCMatch(), as found in the Appendix on pages104and 113,respectively,i"" ~e."t"Ltheseparatematchingmeasure in both the non-slope-constrained and slope-constrained fashions previously described. In general, these measures separately calculate the difference between the top or bottom contours of a pair of wordshapes.
The general implementation indicated for the measures in the code shows that these measures are typically used sequentially, first determining the warped difference for the top contours, and then adding to it the warped difference from the bottom contour comparison, resulting in a total difference forthe wordshapes.
By carrying out the comparison methods described in a npiece-wisen cascaded fashion, further processing benefits may also be derived.
More specifically, cascaded comparison would entail, first, utilizing the upper contours of the words being compared to identify a word, or at least narrow the set of possible alternatives and, second, using the lower contour comparison to provide complete identification. It is believed that such an approach to word shape comparison operation 26 would considerably reduce processing time spent on identifying unknown word shapes by comparison to a dictionary of known word shapes, 28, as illustrated in Figure 1 B. Important to the cascaded comparison, is the constraint that the top and bottom warps applied to the contours must be relatively equivalent. This requirement arises from the fact that the upper and lower curves have a relationship to a common word, and if this relationship is not 2~77969 rr~ ed during the warp analysis, the accuracy of the comparison will be cc""~.ru..,;;c~.
Alternatively, the dynamic warping technique may be applied as described, with the addition of a function suitable for accumulating the relative warp applied to the upper and lower curves in achieving the best match. For example, when a known, non-italicized word shape is compared to an unknown word shape, a shift in the warp applied to the upper curve relative to the lower curve could be indicatiYe of an italicized word, however, the length of the warped region will remain the same for the top and bottom warps. Such a technique may prove useful in the identification of important words within a larger body of text, as these words are occasionally italicized for emphasis.
One of the control factors which has not been previously described isthe bandWidth factor. As i" ~'~ ."2n~ed, the bandWidth factor controls the relative width of the signal band in which the warping signal will be constrained. More specifically, the band width limitation is i,.,~l~n,e"led by defining a region about the array diagonal in which the warp path which traverses the array is constrained. The constraint is i"" '~."~"led by assigning large values to those areas outside of the band width, so as to make it highly unlikely that the path would exceed the constraint.
Another factor which was briefly mentioned is the topToBottom factor. When applied, the value of this variable is used to weight the difference value determined for the top contour warping process.
Therefore, use of a number greater than one, will cause the upper contour difference to be weighted more heavily than the lower contour difference.
A very large number would effectively eliminate the lower contour difference completely and, likewise, a zero value would eliminate the upper contour difference completely. This factor is generally considered important to enable the upper contour to be weighted in proportion to its information content, as it generally carries more information regarding the word than does the lower contour.

-2077g69 The hillToValley ratio is a va!iable which is usually applied in situations when a known, or model, set of word shape contours is being compared agains~ a set of word shape contours from an unknown image.
In exercising this option, the model set of contours is passed as the comparison measure functions, for example, NewMatch() on page 102 of the Appendix. When determining the difference between points on the contours, the comparison functions commonly call the function SquareDifference() on page 101 of the Appendix to determine the sum of the squared difference. SquareDifference() applies the hillToValley ratio to the squared difference whenever it determines that the value of the model contour is less than the contour being compared. The result of applying a hillToValley value greater than one is that the relative "cost" of the difference when the modei contour is less than the target contour is smaller than the same difference when the model contour is greater than the target contour. The basis for this type of weig hting is that when compari ng against a model contour, the comparison should treat those areas of the target contour that are subject to being "filled in" during a scanning or similar digitizing operation with less weight than regions not likely to be filled in, as evidenced by contour positions below the model contour. For instance, the regions where ascenders and descenders meet the body of the character are likely to be filled in during scanning, thereby causing the target contour to have a gradual contour in those regions, whereas the model contour would most likely have a defined peak or valley in these regions. Hence, the contour value of the model would be less than the contour value of the target, even though the characters may have been identical. Therefore, the hillToValley variable attempts to minimize the impactto the calculated difference value over these regions.
It is important to note that the aforedescribed measures and control factors allow the comparison measures to be conducted in numerous permutations However, the flexibility which these measures permit is intended to enhance the applicability of the comparison process, so that when information is known about a particular word shape contour, for example, a model contour generated from a computer generated ~ 2077~59 character font, the measures may place reliance on that information to make the comparisons more robust.
The mathematical explanation of the word shape derivation process suggests that alternative methods of deriving the word shape signal exist. Some possible alternatives are the ~CtA~'' 'III~IIl of the one I;."~I-sio~al signal using an alternative coordinate scheme, for example polar coordinates. Another possibility is generation of signal g(t), where g(t) ,~pr~,e"l~ the direction from each contour point to the succeeding contourpoint,where twould representthe pointnumber.
The invention has been described with reference to a preferred ..,Lodi",~"~, namely a software implementation, butthe invention may be ."e~lted using specialized hardware. Moreover, the invention has been described with respect to textual images. However, this invention would also be applicable for images that include non-textual image portions as well. Obviously, modifications will occur to others upon reading and understanding the specification taken together with the drawings.
This embodiment is but one example, and various alternatives, modifications, variations or i,,,pro,l~., ,e" Ls may be made by those skilled inthe art from this teaching which is intended to be encompassed by the following claims.

Index for Code Appendix ~7~969 ~'~ k~ r.~.c ............. 147 match.c --- - -.. 83 ~ ~a ' - - c . .. . ................ 45 match.h , ., ..... , .............. ,,, 1 5 args.c .. ,.. ,.............. 27 matchparallel.c .. ,.,,............ 90 args.h , ................. , . 1 .,. t~llpa. "-~ h, .,,,, .,,, .,.. 16 baselines.~ .,.. ,. 158 maxFilter.c ...... ,..... ,......... 209 baselines.h ,.,.. ',... ,.. ,......... 3 mis~.h .,......... ,,,,,.,......... 17 blobify.c .,... ,.,..... ... ..... 165 mylib.h .......... ,,,.,. ......... 18 blobify.h .. ,.,.,.. ,......... , 4 myWc.c ........... ,,.,.,,,,....... 212 boolean.h ... ,,... ,.,.,,...... 5 new~a~ '' ~es.c .. ,,,.. ,.......... 214 boxes.c ... ,, ,. ,, ,,..... 168 nev~lJL ~.c , . ,,.. ,,,.,,. 223 boxes.h ,,,,.,..... ,........ ,, 6 newContour.~ .,.,.,,.,,,.,. 226 descMain.c , ...... ..... 49 newContour.h .,, .,,,, ., ., ...... , l 9 d~.~.;plols.c .,,.,... ,,,,.. 53 newDiff2.c .,,...... ,.,.. ,........ 232 descriptors.h .,.,.......... ,. 7 newL2,c .,,,,.,,............... 99 di~t.~ ,,.,.... .. 175 newMain.~ ,.,...... ,.... ,........ 233 dicth .,.,.,.. ,,.... 8 newMatch.c .. ,.... ,,... ,,....... 101 diff.h ,,,,,......... 9 newMatch.h .,....... ,.... ,........ 20 diff2.c .. ,......... 56 numbers.c .,.,.,,.,.............. 239 diff2.h .. ,,,....... 10 numbers.h ..... ,.... ,,....... 21 dmain.~ , .. . . . . . 60,1 79 orient.c ., ... . .... . . , .. . 243d~ .ve~c~s c ,,,,, .. , .... 61 orient.h .. , .. ,, .. ,, ..... , 22 equiY.c ... ,............ 63 overlay.c .. ,,.,.... ,........ 247 error.c ,,,,,... ,,.,.. 32 pagestats.c ,..... ,..... ,.,., 248 error.h .,.,,......... 11 pict.c .,.... ,,,.......... 35 extract.c .,,..... ,,.... 66 pict.h .,.,,,........ ,........ 23 fft.c ,.,.,... ,..... 180 postproc.c .,.... ,................ 255 fontNorm.c .,............ 183 read.c ,,.......... ........... 41 fcir.. ~:: .,.. h ,,............ 12 read.h ,,..................... 24 getAll.c .. ,,.......... 194 re-.~aD~ ...... ,................ 118 getOutline.c ,,... 196 .~ c .,........ ,............ 124 guassian.c .............. 198 sepMatch.c ,.,,....... ............ 126 12Norm.c ............... 68 single.c ,..... ,,............... 139 12Ncr, ~ c ............... 74 slope~l~tch.c .,, ...... ,, .......... 141 lines.c .............. 201 sortMatrix.c ..... ,... ,............ 142 lines.h ,,,............. 13 testFine.c .,.,,,,.. ,,............ 264 lists.~ ,,,............. 33 types.c .,........... .......... 267 lists.h ,- ----- --- 14 types.h .,,,..... ,,............ 25 Makefile ........ 26, 42, 144 c~i,63 Section A APPENDIX Page 1 ~ul2619:281991args.h 2077969 2 /~Supportforcommandlineargumentscanning.
3 ~ When a program is run from the shell, its name Is followed by a number of4 required command line ARGUMENTS and then some optional command line OPTIONS
S ~ Each argument consists of a list of required PARAA/IETERS, each of which can 6 ~ be either an int, string, or float. Options are like arguments with the 7 ~ exception that their required parameters are predeced by a keyword denoting 8 ~ which option Is belng Invoked.
~0 ~Requiredargumentsaredefinedus,ngtheDefArgfunction. Theformatstrlng 11 ~consistsofalistofdataformatspecifiers(%d,~of,and%sforinteger,float,and 12 string, respectively) that speclfy the types of the parameters to the arguement.
13 ~ The documentation strlng shouid contaln a one line descrlptlon of the argument.
14 ~ Itwill be printed if the argument list cannot be scanned ~5 TheremalningargumentstoDefArqarepolnterstolocationswherethevaluesofthe 16 ~ command line arguments wlll bestored.

18 ~ Optional arguments are defined with the DefOption function. The format strlng ~9 ~issimilartotheDefArgformatstring,buthasakeywordbeforetheformat specifiers The exists parameter is a pointer to BOOLEAN that is set to true 21 ~iffanoccuranceofthisoptionwassuccessfullyparsedfromthecommandline 22 ' The remaining arguments are polnters to the locations where the values of the 23 t command line arguments will be stored.

' Short example:
26 ~ The following program expects one required command line argument that is a string 27 ~ and will be stored in s. In addition, it will accept three different optional 28 ~ keyword arguments. They are the keyword -int followed by an integer, with result 29 ' stored in ~; -float followed by a float stored in f, and -pair followed by a float ~ and then an int, stored in f and i, respectlvely.
31 ~ .
32 ~ Suppose the program is called foo. Here are some legal invocations:
33 ~ % foo hello 34 % foo hello -int 1 ~ % foo hello -int S ~float 10 36 ~ % foo hello -pair 12 38 Here are some error invocations and responses 39 ~%foo ~ Usage:
41 scanArgs 42 ~ filename 43 [-int cint~
44 ~ [-float <float>
[-pair <float> <int>
46 % foo hello -Int 47 ~ Option -int expects 1 parameters:
48 ~ -i nt < i nt >

51 ~void main ~int argc,char -argv) Copyright~ 1991 XeroxCorporation Al I Rlghts Reserved Section A APPENDIX I Page 2 2~77969 52 ~{
53 ' inti;
54 floatf;
~ char ~s;
56 BOOLEANhaveAString~haveAnlnt~haveAFloat~haveAPair;
57 t 58 DefArg("%s","filename",&s);
S9 DefOption(''-int /Od","-int <int>",&haveAnlnt,&i) DefOption('' -float % f ", " -float < flodt > " ,&haveAFloat,&f);
6~ DefOption(''-palr %f %d","-pair <float> <Int>",&haveAPair,&f,&i);

63 ~ ScanArgs(argc,argv);

printf("%s~n",s)-66 if (haveAPair) 67 printf("%f %d~n",f,i);
68 if (haveAnlnt) 69 printf("%d~n",i);
if(haveAFloat) 7t prlntf("%f~n",f);
72 if (haveAString) 73 printf("%s~n",s);
74 }

78 f- Possible additions:
79 l)PassingNUL~pointersasexlstsvariables.
2) Pred icate cal cu I u s f or error checki ng .
81 3) Only need one DefArg call.
82 4) Combi ne with error.c to save program n2me i nfo.

84 void DefArg(char format,char documentation,) 85 void DefOption(char ^format,char documentatlon BOOL~AN exists,) 86 void ScanArgs(int argc,char argv);

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon A APPENDIX Page 3 ~an ~1 ~ 7.00199i baselines.h 2 ~ ~ 7 9 ~ ~
Lisl BaseLines(Picture pict,double angle,char ~plotFi~e);
2 #ifdef foo 3 Int ~count, 4 int ''returnCoordx, int ~returnCooray);
S #endif 6 vold DrawBaseLines(Picture pict, Llst polntList, double angle);

COpyrlrJht D 1991 Xerox Corporation ~11 Rights Reserved Section A APPENDIX; P39e ~
'~07~969 Aug2313:031991 bloblfy.h Picture Blobify(Picture old,int half mask si~e,double threshold);
2 Plcture New~lobify~Picture old,int halfMaskWldth,double threshold,doub7e angle);

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectl o n A APPE N 21X i~ a g e S
~ug 102 59 i991 boolean.h 2077~9 typedef int BOOLEAN;
2 #define FALSE û
3 #define TRUE (!FALSE) Copyright ~1991 Xerox Corporation AlI R,ghtsReser\/ed Sectlon A APPENDIX Page 6 Jan 11 17:001991 boxes.h List FindBorders(Picture pict,double theta); 2 0 7 7 9 6 2 vold DrawBox(Picture pict,Box box);
3 void DrawColorBox(Picture pict,Box box,int color);

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon A APPEN Dl X Pa ge 7 ~12613:42 1991 descrlptors.h 2typedef unsigned char ~Descriptor~DescrlptorElement; ~ ~ 7 ~ 9 ~ 9 3void PrintField(char ~s,intw);
4void PrintDescriptor(Descriptor d,int tstarCount,int 'correctCount);
Svoid PrintWords(char ''wcrds,int numberOfWords);
6Descriptor ComputeDescriptor(int modellndex,Dictionary models, 7 Dictionary thisFont,lnt numberOfWords, 8 DiffDescriptor dd);

lû #define MAX FONTS (20) 11 #defineMAX_WORDS(~00) Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon A APPENDIX Page 8 Jan 1612 551991 dict h /~ Dictionary file have the following format 2 intmagicnumber = 1234567 2~7;~9 3 int numberOfEntries 4 ~ int infoStringLength (inc~udes the ~O at the end) S char infoStringLinfoStringLengthl 6 ~ OutlinePair30dyLnumberOfEntrie5]
9 typedef struct {
80x box;
11 float blackoutHeight;
12 int numberOfLegs;
13 int offset;
14 intwidth;
l S float -x;
16 float ~top;
17 float ~boltom;
18 } OutlinePair,OutlinePairBody;

typedef struct {
21 Boxbox;
22 int numberOfLegs;
23 int~x;
24 int top;
int ~bottom;
26 } ~RawOutlinePair,RawOutlinePair60dy;

28 typedef strua {
29 int numberOfEntriff;
char infoString;
3~ RawOutlinePair ~rawOutlines;
32 OutlinePair ~outlines;
33 } Dictionary,DictionaryBody;

void WriteDictionary(Diaionary dict, char ~fiiename);
36 Dictionary ReadDictionary(char ~filename);
37 Dictionary l~lewDict(int numberOfEntries);
38 char ArgLi%ToString(int argc, char ~-argv);

Copyright2 1991 XeroxCorporation All RightsReserved Sectlon A APPENDIX Page 9 ~ul 30 23:041991 diff h 2typedef enum {L2,CONSTRAINED.WARP} DiffType; 2 ~ 7 7 9 ~ 9 3typedef struct {
4DiffTypediffType;
S300LEAN lengthNormalize;
6300LEAN separate;
7f I oat ~el ~ ~el we- yl ~ ~;
8int bandWidth;
9floattopToBottom;
10floathillToValley;
1~FI LE ~ pathFP;
t2} ~DiffDescriptor,DiffDescriptor30dy;

~4 PictureCompareDictionarles(Dictionarydictl,Dictionarydict2,DlffDescrlptordd);I Svoid WritePictureAsAs~ Picture plct, char 'filename, 16 char iinfo~, char 'Info2);
17float DiffPair(OutlinePalr one, OutlinePalr two,DiffDescrlptor dd);
18#ifdef foo 19 floatDiffPairAndPath(OutlinePairone,OutllnePairtwo,DiffDescriptordd);
20#endif Copyright ~ 1991 Xero~t Corporation All Rights Reserved Section A APPENDIX Page 10 Jan ~518:561991 dlff2.h 2~7~G9 #i~def OWNER
2 #oefine EXTERN
3 #else 4 #oefine EXTERN extern S ~endif OWNER
7 EXTERN int FileCountX;
8 EXTERN Int FileCountY;
10 flodt DiffPair(OutlinePair one, OutlinePa~r two, char ~matchtype 12 char ~pathFile);

Copyright~ t991 XeroxCorporation All Rights Reserved Sectlori A APPENDIX P~ge 11 ~12619:29199i error h 1' Possible additions: 2 ~ 7 7 ~ ~ 9 2 1 ) Variable nu mbers of parameters to DoError().
3 ' 2~ Error recovery language.
4 ~1 S void DoError(char 'stringl,char 'strlng2);

Copyright~ 1991 Xero~Corporation All Rlghts Reserved Sectlon A APPENDIX ' Page 12 Au9150~5.371991 fontNormn void StoreRawOutlinePair(Dictionary dict, int dictEntry, 2 30x box,int bothX,int ~topY, int ~baseY, 3 int numberOfLegs); 2 0 7 7 ~ 6 9 S #define HIT_THE_BOX ~OOOû) Copyright3 1991 XeroxCorporation All Rights Reserved .

Sectlon A APPENDIX Page 13 anll 17:00~991 lines.n typedef BOOLEAN pistfunc~Picture pIct, Int x, Int y, BOOLEAN test 2 UCHAR color~; 2 0 7 7 9 6 9 4 pistFunc DrawPiston, CountPiston, Di~L.,~ '`, .tol " BaseLi nePiston;
S : ~
6 voidLineEngine(Picturepict,intxl,intyl,intx2,inty2,UCHARcolor, 7 pistFunc PerPixel);
8 voidDrawLine(Picturepict,intxl,intyl,lntx2,inty2,UCHARcolor);
9 floatCountLine(Pictureplct,intxl,intyl,lntx2,inty2) int DistanceLine(Picture pict, int xl, intyl, intx2, inty2j;

Copyright ~ ~991 Xerox Corporation All Rlghts Reserved Section A APPENDIX / Page '4 Jan 11 17 001991 lists h typedef struct {
2 void car;
3 void ~cdr;
4 } cel~Body,-cell;
s 6 typedef ce~l List;
7 typedef void mapFun(void ~);
8 tyl~edef void collectFun(void ~);

10 Listcdr~List);
11 void car(List);
12 void poplntern(List );
13 BOOLEAN endp(List);
14 Listcons(void ,List);
void map(List,mapFun);
16 List collect(List,collectFun);
17 i nt ListLength(List l);

19 #definepush(a,l)((l) = cons((a),~l))) 20 #define pop(l) (poplntern(&(l))) 21 #define nil ((List)NULL) Copyright~ 1991 XeroxCorporation All Rlghts Reserved -SectlonA APPENDIX Page 1 ~n IS 18:39 1991 match.h #ifdef OWNER
2 #define EXTERN 2 0 ~ 7 9 6 ~
4 #define EXTERN extern S #endif OWNER

7 EXTERN int debug;

9 typedef struct l o float cost;
I l int xptr;
12 int yptr;
13 }elt;

l S #define MAXSEQLENGTH 800 17 float DPDiffPair~OutlinePair one, OutlinePair two);
18 floatmatchvecs(float~Vecl,intlenVecl,float~Vec2,intlenVec2);
19 floatsq distance~floatx1,floatx2~;
floatbest _ score(elt'array[][MAXSEQLENGTHI,intlenVec~,intlenVec2);
21 void print best path(elt ~array[]lMAXSEQLENGTHI, int lenVecl, int lenVec2, 22 char ~pathFile);
23 void print atray costs(elt ~array[][MAXSEQLENGTHI, int lenVec1, int lenVec2);
24 void print array dirs(elt ~array[l[MAXSEQLENGTH~, int lenVec~, int lenVec2);
2' 27 #ifndef debug 28 #define debug FALSE
29 #endif ~/
3 ~ #ifndef horweight 32 #define horweight l .S
33 #endif 3s #ifndef venweight 36 #define venweight l .S
37 #endif 39 #ifndef diagweight #define diagweight 1.0 41 #endif Copyright~l991 XeroxCorporation All Rights Reserved Se~tion A APPENDIX ! Page 16 J2n 1518:471991 matchparallel.h 2 ~ 7 7 9 ~ 9 float pi DPDiffPair(OutlinePair one, OutlinePair two, char ~pathfile);
2 floatpl matchvecs(float~Veclt,float~Veclb,lntlenVec~,float'Vec2t,float~Vec2b,int ~enVec2, char ~pathFi~e);
4 float faster pl DPDiffPair(OutlinePair one, OutlinePair two, char pathFile);
S flo.atfaster pl matchYecs(float~Veclt,float~Veclb,intlenVec1,float'Vec2t,float~Vec2b, i nt lenVec2, cha~pathFile);
7 float simple pi _ DPDiffPair(OutlinePair one, OutlinePair two);
8 floatsimple pl matchvecs(float~Veclt,float~Vec~b,lntlenVecl,floatiVec2t,float ~2b,1n~ ~nV~c2~, Copyright ~ 1991 Xerox Corporation All Rights Reserved Section A APPENDIX ~' Page 17 ui g 16 01 1991 mlsc h 2 It 2~779~
3 ~ misc h - miscel laneous types and declarations S ~/

7 /~Somelibraryroutinesthatneverseemtogetdeclared~!

9 /' Memory allocation functions ~/
1 û extern void malloc~unsigned size);
11 extern void tcalloc(unsigned nelem, unsigned elsize~;
12 extern void ~realloc(void tp, uns~gned slze);
13 extern void free(void ~p);

l S /~ I don't feel like including setjmp h '/
16 /~
17 externint setjmp(jmp bufenv);
18 extern volatile void longjmp(jmp buf env, int val);

21 /~ String-to-X functions ~/
22 extern intatoi~char ~s);
23 extern double atof~char ~s);

/~ String functions ~/
26 extern int strcmp~char ~s l, char ~s2);
27 externintstrncmp~char-sl,char~s2,intn);
28 extern char ~strcpy~char ~d, char ~'s);
29 extern char ~strncpy~char ~d, char ~s, int n);
intstrlen~char~s);
31 extern char ~strdup~char ~);
32 extern char 'strchr~char ~s,char c);

34 /~ stdio functions /
35 extern int fclose~FlLE ~stream);
36 extern int fread~char ~ptr, int size, int nitems, FILE ~stream);
37 extern int f~vrite~char 'ptr, int size, int nitems, FILE ~stream);
38 /-thesearenecessarytoavoidimplicitdeclarations~/
39 extern int flsbuf~);
4û extern int_filbuf();

42 /' Formatted IIO functions ~/
43 extern intprintf~char ~format, );
44 extern intscanf~char ~format, );
45 extern int fprintf~FlLE ~stream, char ~format, );
46 extern int fscanf~FlLE ~stream, char ~format, );

48 /~ and misc stuff ~/
49 extern volatile void exit(i nt val);
Sl extern void perror(char ~s);

Copyright~ 1991 XeroxCorporation All Rights Rese~ved SectionA APPENDIX Page 18 Aug 102:591991 mylib h #include ''error.h" 2 0 ~ 7 9 ~ 9 2 #i ncl ud e '' boolean . h "
3 #i ncl ude " l ists. h "
4 #include"3rgs.h"
S #include"pict.h"
6 #include"~ead.h"

Copyright~ 1991 XeroxCorporation All Rishts Reser\~ed -Sectlon A APPENDIX P~ge 19 AuglSû6:361991 newContour.h 2~77g69 void BoxToShell(Picture pict,30x box,List baseLinePoints, 2 Dictionarydict,lntdictEntry,~l.,""dli~L,~.l,Descriptor~nd);
3 void Bar~oxList(Picture pi~t,Llst boxList,List baseLinePoints, 4 char ~filename, char ~InioString, NormalizationDescriptor ~nd);

Copyright~ 199~ Xero~Corporation All Rights Reserved Sectlon A APPEN Dl X Page 20 ~ul31 17 11 1991 newMatchh 2077969 ~
extern float hillToValley;
2 extern float L2Compare(OutlinePair o l ,OutlinePair o2,float toproBottom);
3 extern float NewMatch~float a 1 ,float a2,int aLength,float bl ,float ~b2,int bLength, 4 float~ L '~V~ BooLEANle~ lalize~intnormalBandwidth~
S float topToBottom);
6 externfloatSepMatch~float-a~,intaLength,float-bl,intbLength, 7 rloat~"Le,~ l,L,BOOLEANl~ ,yLl,~",lalLe,intnormalBandWidth);
8 externfloatNewMatchAndPath~float-al,float-a2,intaLength,float-bl,float'b2, 9 IntbLength,f~oat~"Le,Wci~l.L,BOOLEANlengthNormalize,intnormalBandWidth, lû floattopToBottom,FlLE-fp);
11 externfloatSlopeCMatch(float-al,float-a2,intaLength,float-bl,float-b2,intbLength, 12 float c~"Le, We ~l,L,BOOLEAN lengthNormalize,float topToBottom);
13 externfloatSepSlopeCMatch(float~al"ntaLength,float-bl,intbLength, 14 float,~"L~,~Ve;~l,L,BOOLEANlengthNormalize);
lS externfloatSlopeCMatchAndPath(float~al,float~a2,intaLength,float-bl,float-b2, 16 int bLength,float ~el ~L~ ei~l ,L,BOOLEAN lengthNormalize,float topToBottom, 17 ~ILE pathfP);

Copyright 1991 XeroxCorporation All Rights Reserved Sectlon A APPE N Dl X Pag e 21 ~Jan ~ 1 1 7 ^0 1 99 ~ n u m r e~s h voidDrawNumber(Pi~turepict,intx,inty,intcolor,floatscale,intn~; 2i~773~9 Copyright~ ~991 Xero~tCorporation All Rights Reserved Sectlon A APPENDIX Page 22 ~an 14 t6:52 1991 orlent.h ~73~9 300LEAN Coarse(Picture pict, int coarseSamples, int coarseDirectlons, 2 floa~ ~orientation, char ~plotFile);
4 float Fine(Picture pict,int fineSamples, int fineDirections, intcoarseDirections, floatcoarseAngle, char ~plotFile);
7 float NewFine(Picture pict,int fineSamples, Int fineDirections, 8 float angleStart,float angleEnd, char ~plotFile);

Copyright~ 1991 XeroxCorporation All Ri3htsR~eserved Sectlon A APPENDIX, Page 23 Aug 23 19 19 1991 plct h 2 typedef un5igned char UCHAR; 2 0 7 7 9 ~ 9 3 #define ROUND8(x) ((x~h81?(x + 8-x%8) x~
4 #define ROUND16(x) ((x% ~6)?(x ~ ~6-x% 16) x~
S #defineROUND2(x~((x%2)?(x 1 l) x~

7 typedef int Color 8 #define COLOR RED 0 9 #defineCOLOR ~iREEN 1 #define COLOR_8LUE 2 12 typedef struct cmapstruct {
13 int numberOfEntrles;
14 UCHAR'red lS UCHAR green 16 UCHAR blue 17 } ColorMapBody, ~ColorMap 19 typedef struct pstruct {
2a intvvidth 21 int height;
22 int depth 23 int uchar width 24 ColorMap cmap;
UCHAR ~data 26 } PictureBody, Picture;

28 void doerror(char ~stringl,char string2);


31 ColorMap NewColorMap(int size) 32 void FreeColorMap(ColorMap cmap) 33 UCHAR ReadColorValue(ColorMap cmap, Color prlmary,int index) 34 UCHAR WriteColorValuelColorMap cmap, Int Index, UCHAR red, UCHAR green, UCHAR blue);
36 Picture new pict(int width,int height,int depth);
37 void free p~ct(Picture pict);
38 Picture load pict(char filename);
39 Picture load header~FlLE fp);
void write _ p~ct~char filename,Picture pict);
41 void write header(FiLE fp, Picture pict) 42 /-int BytesFer'icanline(Picture pict) 1 43 #defineBytesPerScanline(pict)(pict->uchar NIdth) UCHAR ReadPixel(Picture pict,int x,int y) 46 void WritePixel(Piaure pict,int x,int y,int color);
47 void WriteCl ~ driA~l(Picture pict,int x,lnt y,lnt color);
48 void CopyPicture(Picture dest, Picture src~;

Copyright ~ 1991 Xerox Corporation All Rlghts Reserved Sectlo n A APP~ N DIX Page 2 4 Jul 261 3 : 09 i 99 1 read .h ~7~3~ --int Readlnt(FlLE tfp~;
2 int ReadFloat(FlLE tfp);
3 char'lReadString(FlLE tfp);

Copyright~ ~991 XeroxCorporation All Rights Reserved Sectlon A APPENDIX i Page25 ug ~500:~9 l991 types.h typedef struct { ~j 2 BOOLEANnoA,c~"d~ o-,l,alize; 2~7 3 BOOLEANnoXIl~ rl~,l"~lize;
4 } Normal i zationDescri ptor;
6 typedef struct {
7 int x;
8 inty;
9 intwidth;
10 intheight;
~ ~ I nt paqeX;
12 int pageY;
13 double angle;
14 } 30x30dy, '30x;
16 typedef struct {
17 int x;
18 inty;
19 ~ PointBody,'Point;
21 30x MakeBox(int x,inty,intwidth,intheight,doubleangle);
22 Point MakePoint(int x,int y);

Copyright ~1g91 Xerox Corporation All Rights Reserved Sectlon B APPENDiX Page 26 Jul 2613:25 1991 Makefile 2~7 7 9 6 9 2 CCFLAGS = -g~c-l/neVpigleVpiglet~ up~,u~t/n~ include 3 INCLUDE = /I~_J~ J~ -1c/hop~,u~U,l_.. ',n~lude/

S ARGS = S(lNCLUDE)args.h 6 aOOLEAN = S(IN~ DF~boo~a~-l.h 7 EF~ROR = S(lNCLUDE)error.h 8 LISTS = S(lNCLUDE)lists.h 9 MISC = S(lNCLUDE)misc.h PICT = S(lNcLuDE)pict.h 1 t READ = S(lNCLUDE~read.h 13 Oi:UNS = args.o error.o pict.o lists.o read.o ~S mylib.a: S(OFUNS) 16 Id-rS(OFUNS)-omylib.a 18 args.o: args.c S(BOOLEAN) S(ERROR) S(MISC~ S(ARGS) 19 gcc S(CCFLAGS) args.c 2û
21 error.o: error.cS(ERROR) 22 gcc S(CCFLAGS) error.c 24 pict.o: pict.cS(BOOLEAN)S(ERROR)S(PlCT) gcc S(CCFLAGS) pict.c 27 lists.o: lists.c S(BOOLEAN) S(LISTS) 28 gcc S(ccFLAGS) lists.c read.o: read.c S(MISC) S(READ) 31 gcc S(CCFLAGS) read.c Copyr~ght~ 1991 XeroxCorporation All Rights Reserved Sectlon B AppENDlx ?age 27 ~ul2613 23:1991 args.c #include <stdio.h> 2 2 #include <stdarg.h>
3 #include"error.h"
q #,nclude"boolean.h"
S #include"misc.h"
6 #include"args.h'' 8 #define MAX NAME LENGTH ~50) 9 #define MAX PARAMETERS (6) #defineMAX OPTIONS(20) 11 #define MAX ARGS (20) 13 typedef enum {INTEGER,FLOAT,STRING} Paramrype;

typedef struct {
16 char ~documentatlon;
17 intnumberofparameters;
~8 ParamType types[MAX PARAMETERSI;
19 void ~valuesLMAX PARAMETERSI;
2û } 'Arg,Argaody;

22 typedef struct {
23 char optionName[MAX NAME _ LENGTH + 11;
24 char ~documentation;
BOOLEAN ~exists;
26 int numberOfParameters;
27 ParamType typeslMAX PARAMETERSI;
28 void ~values[MAX PARAMETERSI;
29 } tOption,OptionBody;
31 staticBOOLEANoptionsRecluired = TRUE;
32 static int numberOfArguments = 0;
33 static ArgBody args[MAX ARGSI;
34 static int numberOfOptions = 0;
static OptionBody options[MAX _ OPTIONSI;

37 void DefArg(char format,char 'documentation,. ) 38 {
39 va list ap;
char ^p;
41 int i;
42 int parameterCounter;

44 if (numberOfArguments = = MAX ARGS) DoError("DefArg:toomanycommandlineopt~onsnow:~"%s~ n'',format);

47 args[numberOfArgumentsl.documentation = documentation;

49 /' now parse the format string '/
1~ get option parameters ~/
51 va start(ap,docu,~ LR~
52 for~p = format,parameterCounter = 0; ~p; p + + ) {
Copyright 1991 XeroxCorporation All Rights Reserved Section 8 APPENDIX Page 28 54 if(parameterCounter = = MAX PARAMETERS) 2~ g --DoError("Def Arg: too mzny parameters in \"~6s\".\n",format~;
56 p+ +;
57 switch (~p) {
58 case 'd':
S9 args[numberOfArgumentsl.types[parameterCounter] = INTEGER;
args[numberOfArgumentsl.values[parameterCounterl = va arg(ap,void~);
61 parameterCounter+ +;
62 break;
63 case'f':
64 args[numberOfArgumentsl.t~p~,~pd,d,1,.te,Counterl = FLOAT;
args[numberOfArgumentsl.values[parameterCounterl = va arg(ap, void ~);
66 parameterCounter+ +;
67 break;
68 case's':
69 args[numberOfArgumentsl.ty~ pd,~ tt.Counter~ = STRING;
args1numberOfArgumentsl.values[parame~erCounterl = va_arg(ap, void ~);
71 parameterCounter+ +;
72 break;
73 default:
74 DoError("DefArg:badoptionln~"/0s\n.`n'',format);
}
76 }
77 }
78 args[numberOfArgumentsl.numberO~P~,~".. t.. , = parameterCounter;
79 + + numberOfArguments;
8û va _ end(ap);
81 }

83 void DefOption~char ~format,char ~documen~ation,BOOLEAN ~exists,) 84 {
va listap;
86 char ~opti onName;
87 char ~p;
88 inti;
89 int parameterCounter;
91 if(numberOfOptions= =MAX oprloNs) 92 DoError("DefOption: too many command line options now:\"YOs\".~n",format);

94 /~recordexistssothat~eldstswillbeTRUEifthisoptionisscanned~/
9S options[numberOfOptionsl.exists = e~ists;

97 options[numberOfOptionsl.documentation = documentation;

99 1~ now parse the format stri ng ~/
1 0û p = format;
lûl /~skipleadingspaces~/
102 while (~p = = ' ' && ~p! = '~0') 103 P+ +;

105 1~ get the option name ~/
106 optionName = options[numberOfOptionsl.optionName;
107 i=0;
Copyrig~1t 1991 Xero~ Corporation All Rights Reserved Sectlon B APPENDIX, Pacie 2CJ
108 whlle (tp ! = ':0' && 'p ! = ' ' && 'p ! = ' 1') {
109 If(i<MAX NAME LENGTH~
110 optionName[i + +r= P; 2 0 7 7 9 6 9 111 else ~12 DoError("DefOptions:optionnametoo!ongin\"%s\".\n",format);
113 p+ +;
114 }
1 I S optionName[i I = '\0';

117 /t get option parameters t/
118 va start(ap,exists):
119 for(parameterCounter=O;tp;p+ +){
1 20 if (~P = = '% ') {
12~ if(parameterCounter = = MAX PARAMETERS) 122 DoError("DefOptions:toomanyparametersin\"%s~ n'',format);
123 p+ +;
124 switch (~p) {
125 ~ase'd':
126 optlons[numberOfOptionsl.typ~,;~.c,,~,r.~ Counterl = !NTEGER;
127 options[numberOfOptionsl.values[parameterCounter¦ = va arg(ap,voidt) ~28 parameterCounter+ +;
129 break;
130 case ' f ':
131 options[numberOfOptionsl.types[parameterCounterl = FLOAT;
132 optionslnumberOfOptionsi.values[parameterCounterl = va_arg~ap, void t):
133 parameterCounter+ +;
1 34 break;
135 case's':
136 options[numberOfOptionsl.types[parameterCounterl = STRING;
137 options~numberOfOptionsl.valueslpdrameterCounter] = va_arg(ap, void t);
138 parameterCounter + +;
1 39 break;
140 default:
141 DoError("DefOptions: badoptlonln\"%s\''.\n'',format);
142 }
143 }
144 }
145 uulio--s[i,u",L~IOfOptionsl.numberOfParameters = parameterCounter;
146 + +numberOfOptions;
147 va _ end(ap);
148 }

150 void PrintHelp(char ~name) 151 {
152 inti;
153 ~.,;"~r(.LJ~.""Usage:\n %s\n",name):
154 for(i =0;i<numberOfArguments; + +i) 155 ~IJ' il l.i'(s~cl~. "" %s\n",args[il.documentat~on);
156 for(i=0;iCnumberOfOptions;++i) 157 rJ,;"Lt(,L~."" [%sl\n'',optlonslii.documentation);
1 58 DoError("~n",NULL);
159 }

161 vold ScanArgs(int argc,char t~argv) 162 {
Copyright~ 1991 XeroxCorporation All Rights Reserved Sec+lon B APPENDIX P~ge 30 163 Intl,j,k;
l664s fOI a=o;i <numberOfOptj ons; + +i) 2~ 9 166 '(options[jl.exists) = FALSE;

168 if ~argc = = I &&optionsRequired) 169 PrintHelp~argvLo~);

17t i = ~;
172 for (j = 0; j C numberOfArguments; + + j) {
173 if (i ~ args[jl.numberOfParameters > a~gc) {
174 r~ll"l~(,Ld~.""Requiredargumentexpects/~dparamete~s:\n %s\n'', 175 args~jl.numberOfParameters, 176 args[jl.documentation);
177 DoError~"~n",NULL);
178 }
179 for(k=û;k<args0]numberO~Fa.~ :e,s;+ +k) 180 switch (argslj].types[k]) {
t8~ ~ase INTEGER:
182 ~(int')(argsO].values[k~) = atoi(argv[i+ +
183 break;
t84 case FLOAT:
185 t(float')(argsUI.values[k]) = atof(argv[i+ +]);
1 86 break;
187 caseSTRlNG:
188 '~char-~)(args01.values[kl) = argv[i+ +];
1 ~9 break;
190 default:
191 DoError("ScanArgs: internal error- bad type.\n'',NULL);
192 }
193 }

l 9S while (i < argc) {
196 ~or~j=0;j<numberOfOptions;+ +j) 197 if (!strcmp(options[j~.optionName,argv[i¦)) {
198 if (i +options[jl.numberOfParameters > = argc) {
199 fprintf(stderr,"Option %s expects %d parameters:\n %s\n", 200 options0¦.optionName, 201 options0].numberOrP~ te,s, 202 optionsGI.documentation);
203 DoError("\n",NULL);
204 }
205 ~(optionsG¦.exists~ = TRUE;
206 + + j;
207 for(k=O;k~optionsOI.numberC~f~a,.,,.,~:~.,, + + k) 208 switch (options[j].types[k]) {
209 case INTEGER:
210 '(int~)(options[j].values[k]) = atoi(argv[i+ +]);
2 11 break;
212 case FLOAT:
213 '(float ')~optionsljl values[kl) = atof(argv[i + + ]);
214 break;
215 caseSTRING:
216 '~char'~)(options[j].valueslk]) = argv[i+ +1;
217 break;
Copyright'~ 1991 XeroxCorporation All Rights Reserved Sectl o n B APPE N DIX Pag e 31 ~2 18 default:
2~9 DoError("ScanArgs: Internal error - bad type.~.n",NULL);
22210 break; 2~773~9 222 }
223 if(j = =numberOfOptions~ {
224 fprintf(stderr,''Bad command line argument.\n");
225 PrintHelp(argv[O¦);
226 }
227 }
228 }
229 #ifdef foo 23û void main (int argc,char ~arsv) 231 {
232 int i;
233 floatf;
234 char ~s;
235 300LEAN haveAStri ng, haveAn Int,haveAFloat,haveAPai r;

237 DefArg( %s', filename ,&s);
238 DefOption("-int %d","-int Cint>",&haveAnlnt,&i);
239 DefOption("-float %f","-float <float>",&haveAFloat,&fl;
24û DefOption("-pair%f %d","-pair <float> <int>'',&haveAPair,&f,&i);

242 ScanArgs(argc,argv);

244 printf("%s~n'',s);
245 if (haveAPair) 246 printf("1/of %d\n",f,i);
247 if (haveAnlnt) 248 printf("~/~d\n",i);
249 If (haveAFloat) 250 prlntf(" % f~n " ,fl;
251 ,f (haveAString) 2 52 prl ntf( " % s~n ', s);
253 }
.54 #endif Copyright 9 1991 Xerox Corporation All Rights Reserved Se~tlon 3 APPENDIX ' Page 32 Ju126i2:571991 errorc 2~79~9 #include <stdio.h>
2 #include"error.h"

4 void Co~rror(char ~stringl,char ~string2) S {
6 if (string2 = = NULL) 7 prlntf(strlngl);
8 else 9 printf(stringl,string2);
exit(-l);
11 }

Copyright~ 1991 XeroxCorporation All Rights Reserved - - -Se~tlon B APPENDIX Page 33 Jul 26 12:57 1991 lists.c 2 #include ~stdio h~ 2 0 7 ~ ~ 6 9 3 #include"lists.h"

Listcdr(Listl) 6 {
7 if(l = = NULL~
8 return 1;
g else ~0 return l~>cdr;
11 }

13 void tcar(List 1) 14 {
if(l = = NULL) 16 retu~n 1;
1 7 else 18 return l->car;
19 }
21 void ~poplntern(List ~1) 22 {
23 Listtemp;
24 if (~1 = = NULL) return ~'1;
26 else {
27 temp = (~ >car;
28 'I = (~l)->cdr;
29 return temp;
}
31 }

33 BOOLEAN endp(List 1) 34 {
return (I = = NULL);
36 }

38 Listcons(void~theCar,ListtheCdr) 39 {
cell temp;
41 temp = (cell)calloc(7,sizeof(cellaody));
42 if (temp = = NULL~ {
43 printf("Cons: out of memory~n");
44 exit(- 7 );
}
46 temp->car = theCar;
47 temp->cdr = theCdr;
48 return temp;
49 }
51 void map(List l,mapFun f) 52 {
Copyright ~ 1991 Xerox Corporation All RightsReserved Section B APPENDIX Page 34 53 while(l ! = NULL) {
55 1 _ I >cdr; 2 ~ 7 7 9 & 9 56 }
57 }
59 List collect(List l,collectFun c~
60 {
6t List temp;
62 wlli~e (I ! = NULL) {
63 (~'c)(l->car);
64 temp = 1;
65 1 = I->cdr;
66 free(temp);
67 }
68 }

70 int ListLength(List 1) 71 {
72 i nt count = 0;
73 wllile (I ! = NULL) {
74 ~- ~count;
75 1 = I->cdr;
76 }
77 return count;
78 }

Copyright~ 1991 Xero~tCorporation All RightsReserved Sectlon B APPENl)IX Page 35 Aug 23 19:20 1991 plct.c #include <stdio.h>
2 #include <math.h> 2 ~ ~ ~ 9 6 9 3 #include<rasterfile.h>
4 #include"booledn.h'' S #include''error.h"
6 #includepict.h"

8 static UCHAR bltmasks[l = { 0X80,UY~iO~ ,n~0,n~ 10,0x8,0x4,0x2,0x 1 };

1 û ColorMap NewColorMap(int size) 11 ~
12 ColorMap cmap;
13 if (size > 156) i 4 DoError(" NewColorMap: size greater than 256. " ,N U LL);
if(size < 1~
16 DoError( NewColorMap: si ze less than 1 ,NU LL);
17 if((cmap = (ColorMap)calloc(~,sizeof(ColorMapBody)))= =NULL) 18 DoError(''NewColorMap: cannot ailocate space.",NULL);
19 cmap->numberOfEntries = size;
cmap->red = (UCHAR )calloc(size,sizeof(UCHAR));
21 cmap->green = (UCHAR-)calloc(size,sizeof(UCHAR));
22 cmap-~blue = (UCHAR ~)calloc(size,sizeof(UCHAR));
23 if((cmap->red = = NULL)Il(cmap->green = = NULL)¦¦(cmap->blue = = NULL)) 24 DoError("NewColorMap: cannot allocate space.",NULL);
return cmap:
26 }

28 void FreeColorMap(ColorMap cmap) 29 {
if (cmap I = NULL) {
31 if (cmap->red I = NU~L) 32 free(cmap-~red);
33 if (cmap->green 1 = NULL) 34 free(cmap->green);
if (cmap->blue ! = NULL) 36 free(cmap->blue);
37 free(cmap~;
38 }
39 }
41 UCHAR ReadColorValue(ColorMap cmap, Color primary, Int index) 42 {
43 if (index > cmap->numberOfEntries) 44 DoError("ReadColorValue: index too big. '',NULL);
if (primary = COLOR RED) 46 return ~(cmap- >red + index);
47 if (primary = COLOR GREEN) 48 return (cmap->green + index);
49 if (primary = COLOR_BLUE) return ~(cmap->blue t index);
51 DoError("ReadColorValue: bad primary color.",NULL);
52 }
Copyright ~ ~991 Xerox Corporation Al I Rights Reserved Sectlo n B APPE N Dl X Pag e 36 54 UCHAR WriteColorValue(ColorMap cmap, Int index, UCHAR red, UCHAR green, UCHAR blue) 56 {
57 if ~index > cmap->numberOfEntrles) 58 DoError~"WriteColorValue index ~oo big ",NULL); ~ 6 9 59 ~(cmap->red + index~ = red; 2 ~7 ~cmap->green ~ index) = green;
61 ~tcmaP->blue ~ index) = blue;
62 }

64 Picture new pict(width,heiqht,depth) intwidth,helght,depth;
66 t 67 Picture pict;
68 Int uchar_~vidth;

if((pict = ~Picture)calloc(l,sizeof(Picture80dy))) = = NULL) 71 DoError("new_pict cannotallocatespace",NULL);
72 pict->width = wldth;
73 plct->height = height;
74 pict->depth = depth;
pict->cmap = NULL;
76 if(pict->depth = = 32) 77 uchar width = pict->width-4;
78 elseif~cl->depth = = 8) 79 uchar width = ROUN02~pict->width);
e~eif~ct->depth = = t) 81 uchar width = ROUND16~pict->width) > > 3;
82 else 83 DoError("new pict only depths of I and 8 are supported\n'',NULL);
8854 pict->uchar=dth = uchar_width;
86 plct->data = (UCHAR-)calloc(uchar wldth~pict->height,sizeof(UCHAR));
87 if(pict->data = = NULL) 88 DoError("new pict cannotallocatespace~n",Nl)LL);
89 return pict;
}

92 ~oid free pict(pict) 93 Picture pict;

if (pict->data ! = NULL) 96 free(pia->data);
97 ~reeColot~', (pi~1 >cmap);
98 free~pict);
99 }

iOI Pictureload pict~fn) 102 char ~fn;

04 FILE fp;
105 Picture pict;
106 intuchar width;
107 struct rasterfile header;
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon B APPENDIX ~age 37 ~09,f ((pict = (Picture)calloc~1,slzeof(PictureBody))) = = NULL) 110DoError~"load_pict:cannotallocatespace',NULL);

112If(~fp = fopen~fn,"r")) = = NULL) 113DoError("load_pict: error openlng Input file %s\n",fn);
114 ,. ç
llS /~wARNlNG-thlsfreadlsvERyunsafe! If assumesthattheCcompller 116~ puts all fields of a structure adja~ent. This is not always the case.
117 ' ~t appears that it works with gcc on a sparcstation, but may not work 118t on other systems. ~/
1 19fread(&header,sizeof(struct rasterfile), I,fp);
120If(header.ras magicl= RAS MAGIC) 121DoError("load pict:onlysupportsrasterfileformat~n",NULL);
122If ~(header.ras typel= RT SrANDARD)Il 123(header.ras=maptype ! - RMT NONE~ ¦¦
124~header.ras maplength ! = 0)) 125DoError(''load _ pict: unsupported rasterfile format`n",NULL);

127plct->width = headerras wldth;
128plct->height = header.ras_helght;
129pict->depth = header.ras _ depth;

13~If (pict->depth = = 32) 132uchar width = pict-~width~4;
~33elseif~ict->depth = = 8) 134uchar width = ROUND2(pict->width);
135elseif~ct~>depth = = 1) 136uchar width = ROUND16(pict->width) > > 3;
1 37else 138 DoError("load pict:onlydepthsofl,8,and32aresupported\n",NULL);
139 plct->uchar width = uchar width;
140 -- _ 141 plct->data = (UCHAR ~) calloc(uchar wldth ' pict->height, sizeof(UCHAR));
142 I f (pict- >data = = N U LL) 143 DoError("load_pict:cannotallocatespace\n",NULL);

145 fread(pict- >data, sizeof(UCHAR), uchar wldth~pict- >height, fp);
146 fclose(fp);
return pict;
148 }

1 Sû Picture load _ header(FlLE ~fp) 152 Picture pict;
153 Int uchar width 154 struct rasterfile header;

156 If((pict = (Picture)calloc(1,sizeof(PictureBody))) = = NULL) 157 DoError(''load _ header:cannotallocatespace'',NULL);

159 /' WARNING - this fread is VERY unsafe! If assumes that the C compiler 160 ' puts all fields of a structure adjacent. rhis is not always the case.
161 It appears that it works with gcc on a sparcstation, but may not work 162 ' on other systems, ~/
Copyright~ 1991 XeroxCorporation All Rights Reserved Section B APPENDIX ! Page 38 163 ~f(f~ead(&header,sizeof(structrasterfile),l,fp)!= ~) 164 DoError("load header:errorreadingheader',NULL~;
165 if ~header.ras magic!= RAS MAGIC) 166 DoError("load pict:onlysuPportsrasterfileformat~n",NULL);
t67 if((header.ras type!= RT STANDARD)¦¦
168 ~header.ras maptype!- RMT NONE)~
169 (header.ras maplength ! = 0)) ,~ J ( `J O J
170 DoError("!oa~_pict: unsupported rasterfile format~n",NULL);

172 pict->width = header.ras width;
173 pict->height = header.ras height;
174 pict->depth = header.ras_depth;

176 If(pict->depth = = 32) 177 uchar width = pict->width-4 178 elseif~ct->depth = = 8) 179 uchar width = ROUND2(pict->width);
180 elseif~ct->depth = = t) 181 uchar width = ROUND16(pict->width) >> 3;
182 else 183 DoError("!oad header:onlydepthsofl,8,and32aresupported~n",NULL~;
184 pict->uchar_width = uchar_width;
185 pict->data = NULL;

187 return pict;
188 }

190 voidwrite pict(fn,pict) 191 char ~fn;
192 F~icturepict;

194 FILE fp;
195 intuchar width;
196 struct rasterfile header;

198 if ((fp = fopen(fn, "w")) = = NULL) ~99 DoError("write _ pict: error opening output file %s~n",fn);

2û1 header.ras magic = RAS MAGIC;
202 header.ras _ width = pict->width;
203 header.ras height = pict->height;
204 ~1eader.ras depth = pict->depth;
205 headerras length = pict->uchar width~pict->height;
206 header.ras type = RT STANDARD;
207 if(pict->cmap = = NUrL){
208 header.ras maptype = RMT NONE;
209 header.ras mapiength = 0;
210 /~WARNlNG-thisfwriteisVERYunsafe! If assumesthattheCcompiler 21 1 ' puts al I fields of a st~unu~e adjacent. This is not always the case.
212 ' Itappearsthatitworkswithgcc on asparcstation, butmay notwork 213 ~ on other systems. l 214 if (fwrite(&header,sizeof(structrasterfile),1,fp) ! = 1) 2tS DoError(''write _ pict: errorwriting header",NULL);
216 }
217 else{
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon a APPENDIX ,' P~ge 39 218 heade~.ras m2ptype = RMT E~UAL RG3; 2 219 header.ras maplength = pict->cmap->numberOfEntries~3; 1 ~
220 1~ WARNING - this fwrite is VERY unsafe! If assumes that the Ccompiler 221 ~putsallfieldsofastructureadjacent. Thlsisnotalwaysthecase.
~222 ~ It appears that it works with gcc on a sparcstatlon, but may not work 223 ~ on other systems. ~1 224 if(fwrite(&header,sizeof(structrasterfile),1,fp)!= 1) 225 DoError~"write pict: errorwritlng header",NULL);
226 fwrite(pict->cmap->red,sizeof(UCHAR),pict->cmap->numberOfEntries,fp);
227 fwrite(pict->cmap->green,sizeof(U~HAR),plct->cmap->numberOfEntries,fp);
228 fwrite(pict->cmap->blue,sizeof(UCHAR),plct->cmap->numberOfEntries,fp~;
229 }

231 uchar width = pict->uchar width;
232 fwrite~pict- >data, sizeof(UCHAR), uchar wldth~pict- >height, fp);
233 fclose(fp);
234 }

236 void write _ header(FlLE ~fp, Picture pict~
237 {
238 struct rasterfile header;

240 header.ras magic = RAS MAGIC;
241 header.ras width = pict->width;
242 header.ras height = pict->height;
243 header.ras depth = pict->depth;
244 header.ras length = pict->uchar_width'pict->height;
245 he3der.ras type = RT STANDARD;
246 header.ras maptype - RMT NONE;
247 header.ras maplength = 0;
24~3 /~WARNlNG-thisfwriteisVERYunsafel If assumesthattheCcompiler 249 ~ puts ali fields of a structure adjacent. This ~s not always the case.
250 ~ It appears that it works with gcc on a sparcstatlon, but may not work 2 5 ~ t on other system s. ~
252 fwrite(&header,sizeof(struct rasterfile),1,fp);
253 }

255 #define BytesPerScanline(pict) (pict->uchar w~dth) 257 UCHAR ReadPixel(pict,x,y) 258 Picture pict;
259 int x,y;
260 {
261 if(pict->depth = = 8) 262 return ~(pict->data +y~BytesPerScanline(pict) + x);
263 elseif~pict->depth = = 1) 264 return((~(pict->data+y~BytesPerScanllne(plCt)+(x>>3)))&
265 bitmasks[x/08l)?1:0;
266 else 267 DoError("ReadPixel: only depths of 1 and 8 are supported~n'',NULL);
268 }

270 void WritePixel(pict,x,y,color) 271 Picture pict;
272 int x,y;
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon B APPEND~X, P~ge40 273 UCHAR color;

275 if ~x<OIlx> = pict->width¦¦~, . ~ = plct->height) 276 char s[2561;
277 sprintf~s,"%d %d",x,y); ~ n 7 7 ~ ~ 9 278 DoError~"WritePixel:OutofbOunds:",s); r.,~
279 }
280 if ~pict->depth = = 8) 281 '(pict->data I y~pict->uchar width~x~ = color;
282 elseif~pict->depth = = 1) 283 if ~color) 284 t~pict- >data + y~BytesPerScanline~pict), (x > > 3)) 1 = bitmasks[x%81;
285 else 286 ~(pict->data ~ y'BytesPeffcanlinelpict) + (x> >3)) & = ~~itmasks[x%81;
287 else 288 DoError("WritePixel: only depths of 1 dnd 8 are supported\n",NULL);
289 }

291 void WriteClippedPixel(pict,x,y,color) 292 Picturepict;
293 int x,y;
294 UCHAR color;

296 if ~x<O¦¦x> = pict->width¦¦y<O¦¦y> = pict->height) {
297 return;
298 }
299 if ~pict->depth = = 8) 300 ~(pict->data ~ y~pict->uchar width ~x) = color;
301 elseif(pict->depth = = 1) 302 if (color) 303 ~(pict->data I y~8ytesPeffcanline(pict) I ~x>>3))1= bi~,.,a,k,[A~81;
304 else 3ûS '~pict->data ~y~8ytesPerScanline~pict) ~x>>3)) &= ~bitmasks[x~81;
306 else 307 DoError~"WritePixel: on~y depths of ~ and 8 are supported\n",NULL);
308 }

310 void CopyPicture(Picture dest, Picture src) 312 int uchar width;
313 dest->w~th = src->width;
314, dest->height = src->height;
315 dfft->depth = src->depth;
316 cest->uchar width = BytesPeffcanline~src);
317 uchar width = BytesPeffcanline(src);
318 memcpy(dest->data,src->data,uchar _ width~src->height);
319 }
Copyright~ 1991 Xerox~orporation All Rights Reserved Sectlon B APPENDIX P~ge ,Ll ~1126~3:~5~991 readc 2077969 #include <stdio.h>
2 #include"misc.h"
3 #include"read.h"

S #define MAX 'iTRlNG_LEN (255) 7 int Readlnt(FlLE ~fp) 8 {
9 chars[MAX_STRING LEN];
~0 intx;
~2 fgets~s,MAX _ STRING LEN,fp);
13 while(sscanf(s,"%d",i~x)! = 1) 14 ~,u,i".r(,L.~ ,"Readlnt:integerexpected-reenter.~n");
return x;
6 }
18 int ReadFloat(F~LE ~fp) ~9 {
char s~MAX STRING LEN~;
21 f~oatx;

23 fgets(s,MAX STRING LEN,fp) 24 while(sscanf~,''96f'',&x)! = 1) fprintf(stderr,"ReadFloat: integerexpected - reenter.~n");
26 return x;
27 }

Z9 char ~ReadStting(FlLE fp) {
31 char s~MAX STRING LENI;
32 char ~endFtr;

34 fgets(s,MAX STRING LEN,fp);
endFtr = strchr(s,'~n'), 36 if ~endr~tr I = NULL) 37 "endPtr = '~0';
38 return strdup(s);
39 }

Copyright'~ ~991 XeroxCorporation All Rights Reserved Section C APPENDIX Page 42 .
Aug 13 Oû: t3 1991 Makefile CCFLAGS = -g-~-l/neVpigleVpiglet-1-JI,up-~urU~ ';,)clude 2 0 7 7 9 ~ 9 3 EXTRNS = /n~ .;s'LVp:c,'~t-1~/1,uu~-urL'~.,u,~.-u,.o\
4 /"~ ,;gl~J~,igl~L-lr~l~ùu~u~U~ Uu;ct.o\
S IneVpigl eVpi glet- I c/h opcrofVI ists/l ists. o 7 ARGS_MODULE = IneVpigleUpiglet-l~/l,ùu~,urUl,e. 'ScanArgslargs.o 9 SaURCES = Makefile d~ff2.c dmain.c 12Norm2.c match.c matchparallel.c slngle.c EXTRNSOURCES = /n_~'p;~l~Jp;gl~ /l,uu~lurU~,,u,/~llol.c\
11 /n~Jp;yl~Up,gl~ /l,o~.~,u~U,,~. 'rJi~UL,ct.c\
lZ /"~ ,;gl_U~.;glet 1~/1,u,~)~lu~Uli,L,/l;,b.c IS INICLUDE = /neVpigleVpiglet-lchopcrofVnew/include/
16 ARGS = S(lNCLUDE)args.h 17 B~SELINES = S(lNCLUDE)baselines.h 18 BLOBIFY = SllNCLUDE)blobify.h 19 BOOLEAN = S(lNCLUDE)boolean.h 80XES = S(lNCLUDE)bo~es.h 21 CONTOUR = S(lNCLUDE~newContour.h 22 DESCRIPTORS = S(lNCLUDE)descriptors.h 23 DICT _ S(lNCLUDE)dict.h 24 DIFF - S(lNCLUDE)diff.h DIFF2 = S(lNCLUDE)diff2.h 26 ERROR = S(lNCLUDE)error.h 2~ LIIUES = S(lNCLUDE)lines.h 28 LISTS = S(lNCLUDE)lists.h 29 MATCH = S(lNCLUDE)match.h MATCHPARALLEL = S(~NCLUDE)matchparallel.h 31 MISC = S(lNCLUDE)misc.h 32 MYLIB = S(lNCLUDE)mylib.h 33 NEWMATCH = S(lNcLuDE)n~d~ h 34 OrLlENT = S(lNCLUDE)orient.h PICT = S(lNCLUDE)pict.h 36 Rr-AD = S(lNCLUDE)read.h 37 TYPES = S(iNCLUDE)types.h 39 INCSOURCES = S(BASELINES)S(9LOBIFY)S(BOOLEAN)S(BOXES)S(CONTOUR)\
S(DICT) S(DIFF) S(DIFF2) S(LINES) S(LISTS) S(MATCH) S(MATCHPARALLEL) \
41 S(ORIENT) S(PICT) S(TYPES) 43 anomalies: anomalies.o diff2.o newMatch.o /maln/dict.o 44 gcc anomalies.o diff2.o newMatch.o . /maln/dict.o S(EXTRNS) -Im -o S@
46 descriptors: descMain.o descriptors.o diff2.o newMatch.o newL2.o /malnldict.o47 gcc descMain.o descrlptors.o diff2.o newMatch.o newL2.o .. /main/dict.o .. /liblmylib a -Im -o S@

49 drawBlobs: drawBlobs.o/main/dict.o SO gcc~ .E' ~io.. /main/dict.o.. /lib/mylib.a-lm-oS@
Copyright~ 1991 Xero~Corporation All Rights rLeser~led Sect~on C APPENDIX, Page 43 52compdre: diff2.o dmain.o newMatch.o Imainldict.o 53gcc dmain o diff2.o newMat~h,o ./malnidict.o \ f~ r r~
54S(EXTRNS) -Im -o $@ 2 ~ 7 7 ~ ~ ~
ss 56 equiv:equiv.odescriptors.odiff2onewMatchonewL2o lmainldicto 57 gcc equiv.o descriptors.o diff2.o newMatch.o newL2.o .. /main/dict,o .. /lib/mylib.a -Im -oS@

S9 extract: extract.olmain/dict.o gcc extract.o ,Imain/dict.o S(EXTRNS) -o S@

62 12Norm: 12Norm2.o.. 1main/dict.o 63 gcc ~2Norm2.o .. /main/dict.o S(EXTRNS) -Im -o S@

65 recosDesc: recogDesc.o /main/dict,o diff2.o newMatch.o newL2.o 66 gcc recogOesc.o ./main/dict.o diff2.o newMatch.o newL2.o .,/iib/mylib,a -Im -o $@

68 resample: resample.o ,/main/dict.o 69 gccresample.o... /maln/dict.oS(EXTRNS)-lm-oS@
77 single: single,o newMatch.o diff2.o newL2.o .Imain/dict.o 72 gccsingle.onewMatch.odiff2.onewL2.o ,/main/dict.o.. /lib/myliba-lm-oS@~

74 sontMatrix: sortMatrix.o gcc sortMatrix.o S(EXTRNS) -o s@

77 printl~ll: printlncludes printExtrns printCode 79 printCode: S(SOURCES) /usr/Sbinlpr -n3 S(SOURCES) ¦ Ipr -PWeekly`~l/u- Iur~ s 82 printExtrns: S(EXTRNSOURCES) 83 /usr/Sbin/pr -n3 S(EXTRNSOURCES) ¦ Ipr -PWe klyW~I IdNews print~ncludes: S(INCSOURCES) 86 /usr/Sbin/pr-n3S(lNCSOURCES)Ilpr rWo~lyWo,l.~ 6.. 5 88 anomalies.o: anomalies.c S(ERROR~ S(TYPES) S(PICT) S(DlcT) S(DIFF) S(MISC) 89 gcc S(CCFLAGS) anomalies.c 91 descripto~s.o: descriptors.cS~MYLlB)S(TYPES)S(DlCT)S(DlFF)S(MlSC)S(DESCRlPTORS) 92 gcc S~CCf LAGS) descrl ptors.c 94 descMain.o: descMaincs(MyLlB)s(TypEs)s(DlcT)s(DlFF)s(DEscRlpToRs) 9S gcC S(CCFLAGS) descMain,c 97 diff2.o: diff2.c S(BOOLEAN) S(TYPES) $(PICT) S(DIFF2) S(NEWMATCH) 98 gcc S(CCFLAGS) diff2.c 100 dmain.o: dmain.c S(BOOLEAN) S(PICT) S(DIFF~
~ gcc S(CCFLAGS) dmaln.c 103 drawBlobs.o: draw310bs.cS(MYLlB)S(TYPES)S(DlCT) 104 gcc S(CCFLAGS) drawalobs.c Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APP~NDIX Page 44 106 equiv.o: equiv.cS(MYLlB) S(TYPES) S(DICT) S(DIFF) S(DESCRIPTORS) 107 gcCS(CCFLAGS)equiv.c 109 extract.o: extract.c S(BOOLEAN) S(TYPES~ S(DICTl 2 n 7 ~ i3 ~ n 110 gcc S(CCFLAGS) extract c ~ U ~7 112 12Morm2 o: 12Norm2.c S(BOOLEAN) S(TYPES) S(ERROR) S(DICT) 1 13 gcc S(CCFLAGS) 12Norm2.c 115 match.o: match.c S(BOOLEAN) S(TYPES) S(PICT) S(DIFF2) S(MATCH) S(MATCHPARALLEL) 116 gcc S(CCFLAGS) match.c 118 ,n~L.l,~,.,,c,llr~l.o:matchparailel.cS~BOOLEAN)S(TYPES)S(PlCT)S(DlFF2)\
119 S(MATCH) S(MATCHPARALLEL) 120 gcc$(CCFLAGS) ,.,~1"~ ' c 122 newL2.o: newL2.c S(BOOLEAN) S(ERROR) S(TYPES) S(DICT) 123 gcc S(CCFLAGS) newL2.c 125 newMatch.o: newMatch.c S(ERROR) $(MISC) S(NEWMATCH) S(DICT) S(TYPES) 126 gcc S(CCFLAGS) newMatch.c ~27 128 recogDesc.o: recogDesc.c S(MYLIB) S(n'PES) S(DICT) S(DIFF) 129 gcc S(CCFLAGS) recogDesc.c 131 resample.o: resample.cS(BOOLEAN)S(TYPES)S(ERROR)S(DlCT) 132 gcc S(CCFLAGS) resample.c 134 single.o: single.c S(MYLIB) S(TYPES) S(DICT) S(DIFF) S(DIFF2) S(MATcH) S(MATCHPARALLEL) 135 gccS(CCFLAGS)single.c 137 sortMatrix.o: sortMatrix.cS(ERROR)S(PlCT) 138 gcc $(CCFLAGS) sortMatrix.c Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlo n C APPE N D IX ' P~ge d,S
JI 9 19:36 1991 anomalles c #include<stdioh> 207~9~9 2 #i ncl ude "error.h "
3 #include"types.h"
4 #include"pict.h"
S #inc~ude"dict,h"
6 #include"diff,h"
7 #include"mlsc.h"

9 #defineMAX STRING LEN(100) #define MAX DICTIONARIES (15) 11 #defineMAX WORDS(100) 12 #defineMAX_ENTRIES(MAX_WORDS~MAX WORDS) 14 typedefstruct{
I S float score;
16 intx;
17 Inty;
18 } ~CompareTuple,CompareTupleBody;

21 int Readlnt(FlLE fp) 22 {
23 char s[MAX STRING LENI;
24 i nt x;
26 fgets~s,MAX STRING_LEN,fp);
27 wh~l e (sscanfT, " ,'0 d ", &x) ! = 1 ) 28 fprintf(stderr,''Readlnt: integer expected ~ reenter.\n");
29 return x;
}

32 char ~ReadString(FlLE ^fp) 33 {
34 ch2r slMAX STRING LENI;
char ~endPtr;

37 ~gets(s,MAX STRING LEN,fp);
38 endFtr = strchr(s,'\n'), 39 if (endFtr ! = NULL) tendF~tr = '\0';
41 return strdup(s);
42 }

44 Int rupleLessThan(CompareTuple ~x,CompareTuple ~y) {
46 If((~x)->score = = (~y)->score) 47 return 0;
48 else if ((~x)->score < (~y)->score) 49 return-1;
else 51 return 1;
52 }
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX P2ge~16 54 Int~ountAnomalies(Dictlonarydl,Dictlonaryd2,char'dNamel,char'dName2,char t'words,FlLE ~outfp) 55 {
56 CompareTupleBodyscoreBodies[MAX ENTRIESI; ~)rr~r~,~
57 CompareTuple scores[MAX_ENTRIES~ ~ V I I ~f 6 9 58 Picture pict;
59 int x,y,i,j;
int anomalies;
6i 62 pict = CompareDictionaries(dl,d2);

64 for(y=0,i=û;y<pi->height; + +y) for(x = 0;x<pict->width; + + x) {
66 CompareTuple temp;
67 /~ temp = (CompareTuple)calloc(l,sizeof(CompareTupleBody));
68 If (temp = = NULL) 69 DoError(' %s: cannot allocate space.~n",argv[01), '/
71 temp = scoreBodies+i;
72 temp->score = ((float )(pict->data) + x + y'plct->width);
73 temp->x = x;
74 temp->y = y;
scores~il = temp;
76 + +i;
77 }
78 qsort(sccres,i,si~eof(CompareTuple),TupleLessThan);
79 for (j - 0,anomal ies = 0; j <d 1- > numberOf Entries; + + j) If (scores[j]->x I = scores[j]->y) {
81 fprintf(outfp,"%s:%s %s:q~iis\n'',dNamel,~.. d~[s~u,c.j'j]->xl, 82 d Name2nr. ~ [s~u- ~-[i ]- > Yl);
83 + +anomalies;

86 free pict(pict);
87 return anomalies;

void main(int argc,char 1'-argv) 91 {
92 char ~outFile, 1 istFile;
93 int numberOfDictionaries;
94 Dictionanydi~lio~d~ 'sX DICTIONARIESI;
char -" . ;r 1.'\X DICTIONARIESI;
96 char ~words[MAX WORDSI;
97 int numberOfUfori~;
98 FILE ~listfp,~outfp;
99 Int anomalies[MAX DICTIONARIESI[MAX DICTIONARIESI;
100 int i,x,y;

102 if (argc I = 3) 103 DoError("Usage: %s listfile outfile.\n",argv[ûl);
104 listFile = argv[11;
105 outFile = argv[2];

Copyright ~ 1991 Xerox Corporation All Rights Reserved Section C APPENDIX Page 47 107 ~ f ((1 I stfp = fopen(l i stFi I e, " r )) = = N U LL) 108 DoError("Erroropeningfile~/~s.~n'',listFile~;

1~ 0 1~ Read i n the number of words in edch di ctionary ~ 9 6 9 1 tl numberOfWords = Readlnt(listfp); p 112 if (numberOfWords > MAX WORDS) 113 DoError(''%s: too manywords.\n",argv[0]);

l l S /~ Read in the words '/
~16 for (i = 0;i <numberOfWords; + + i) {
~17 words[il = ReadString(listfp);
~8 }
1~9 120 /~ Read in the number of dictionaries 'l 12~ numberOfDictionaries = Readlnt(listfp);
122 If (numberOfDictionaries > MAX DIC~IONARIES) ~23 DoError("']s: too many dicitionarles.\n",a-gv[0]);

~ 25 1' Read in the d ictionari es and their names ~1 126 for(i = 0;i<numberOfDictionaries; + + I) {
127 names[i¦ = Readstrins(listfp);
128 dictlonaries[il = ReadDlctionary(names[ll);
~29 }
~30 ~3~ /~Checktoseethatalldictionarieshavethesamenumberofshapesasthespeclfiednumber of words. '/
~32 for(i=~;i<numberOfDictionaries;+ +i) ~33 if (di.~.io"<-,;c.[-3->numberOfEntries I = numberOfWords) ~34 DoError("Dictionary%shaswrongnumberofentries.\n",names ~35 36 /' Write the results '/
~37 if((outfp = fopen(outFile,"w"))= =NULL) ~38 DoError("Erroropening%sforoutput.~n",outfile);
~39 fprintf(outfp,''Words:~n");
140 for(i =0;i<numberOfWords; + +i) 14~ fpri ntf(outfp, " % d: 'f~l s\n '' ,i ,words[il);
142 fprintf(outfp,"\n'');
143 fprintf(outfp,"Dictionaries:\n");
144 for (i = 0;i<numberOfDictionaries; + + ~) 145 fprintf(outfp,''%d: %s\n",i,names~
~46 fprintf(outfp,''\n");
~47 ~48 /' Fil~ in the anomaly counts ~/
~49 for (y = 0;y< numberOfDictionaries; + + y) ~Sû for(x=0;x<numberOfDictionaries;+ ~x){
~S~ anomalies[yl[xl =
CountAnomalies~dictionaries[yl,dictionaries[xl,names[yl,names[xl,words,outfp);
~52 printf(''(~d,%d): %d\n",x,y,anomalies[yl[~
~53 }
~54 lSS fprintf(outfp,"\n\n");
~56 fprintf(outfp," ");
57 for (x = 0; x < numberOfDictionaries; x t ~ ) 158 fprintf(outfp,"%7d ", x);
lS9 fprintf(outfp,"\n");
Copyright ~ 199~ Xerox Corporation All Rights Reserved Sec~tl on C APPEN D I X ' Pag e 48 160 far (y = 0:y<numberOfDictlonaries; ~ ~ y) {
161 fprintf(outfp, " /~3d ", y);
162 for (x = 0; x < numberOf Dictionaries; ~ ~ x) 63 fprintf(outfp,''~7d ,anomalies~yl[~l); 2 0 ~ ~ g 6 9 164 fprintf(outfp,"\n");
165 }
1 66 fclose(outfp);

168 }

Copyright ~1991 Xerox Corporatlon All Rights Reserved Sectlon C APPENDIX, Page 49 ul3t 17:141991 des~Maln.c #include <stdio.h > 2 ~ 7 7 r~ 6 9 2 #include"mylib.h'' 3 #include"types.h"
4 #include"dict.h"
s #include"diff.h"
6 #include"descriptors.h"

8 void PrintDescriptors(Dictionary models,char 'modelName,char ~wordNames, 9 int numberOfFonts,r~ictionary fonts[], char-'r~"LN~ .,intnumberOfWords, 1 1 DiffDescriptordd) 12 {
T3 int modellndex,fontlndex;
14 int starCount,correctCount;
l S Descriptor thisDescriptor;
16 int lineCount;

18 printf( "~f n " ~;
19 Pli~llWu~J~ .u~ ,^umberOfVvords);
2û lineCount = 0;
Zl starCount = 0;
Z2 correctCount = 0;
Z3 for (modellndex = O,mû~ A<numberOfWords; ~ + mùd~ J~A) t Z4 printf~''C/os%s\n'',modelName,wordN ,.-nod~llndex]);
Z5 + + lireCount;
Z6 for (fontlndex = û; fontindex < numberOfFonts; + + fontlndex) {
Z7 thisDescriptor =
ComputeDescriptor(modellr~^laY,^!~od~ fonts[fontlndexl~numberofwords~dd);
Z8 printf(~ ");
zg PrintField(fontNames[fontlndex],20);
3û PrintD~.~rii.Lul(~l-i,Descriptor,&starCount,&correctCount);
31 prlntf("~n");
32 + + lineCount;
33 }
34 if (lineCount>30) {
pri ntf("~f n " );
3 6 Pl i - ~'u, ,~ ,(~ .. . ' ' , nu m berOfWords~, 37 lineCount = 0;
38 }
39 }
4û rju. i"Lr(,L.Jout,"There were %d mismatches " ,starCount-numberOfVvords~numberOfFonts);
41 rju,i-,~r(,Lduut,"betterthan%dcorrectmatches.(:,fi6.2f%)\n", 42 numberOfVvords~numberOfFonts, 43 (float)(numberOfWords~numberOfFonts)/(float)starCount);
44 r,~.. i."r(,i,~out,"Therewere%dcorrectiymatchedwordsoutof%d.(%6.2f.~o)\n", correctCount,numberOfWords~numberOfFonts, 46 (flodL)~u.. c,~LCount/(float)numberOfVvords/numberOfFonts);
47 }

49 void main(int argc,char ~argv) Sû {
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sec+~ion C APPEN D IX ~ Pe-ge 50 51 char listFile;
52 Dictionary models;
53 char ~modelName; 2 0 7 7 9 6 9 54 intnumberOfFonts;
SS Dictionary fonts~MAX FONTS];
56 char ~fontNames[MAX FONTSI;
57 char 'wordNameslMAX WORDS];
58 i nt numberOfWords;
59 float.t~.L.Il~Ve ~
int normalBandWidth;

, l lt~l 7,~lopeConstrai n,warp,topToBottomOption,hi l l ToVal leyOption;
62 EIOOLEAN separate;
63 floattopTo80ttom,hillToValleyLocal;
64 FILE ~listfp;
inti,x,y;
66 DiffDescriptorBodydd;

68 celt-~'e~ = 1.0;
69 normalBandWidth = 20;
topToBottom = ~.0;
71 hillToValleyLocal = 10;
72 DefArg("%s","listFile",&listFile);
73 DefOption("-L2","-L2",&useL2);
74 DefOption("-slopeConstrain %f","-slopeConstrain <centerweight>", &slop~onstrair~ V~
76 DefOption("-warp %f %d","-warp <centerweight> <bandwidth>", 77 ~warp,8~"le.`~ ,&n~ dWidth);
78 DefOption(''-separate","-separate",&separat~);
79 Defoption(~-normalize"~"-normalize~ yll~x~ alize);
DefOption( '' -topToBottom % f", "-topToBottom <ratio> '',&topToBottomOption,&topToBottom);
81 DefOption(''-hillToValley %f'',"-hillToValley <ratio>",&hillToValleyOption,&hillToValleyLocal);
883 ScanArgs(argc,argv);
84 if ((listfp = fopen(listFile,''r")) = = NULL) DoError("Erroropenlngfile%s.~n'',listFile);

87 /' Read in the number of words in each dictionary '/
8B numberOfWords = ~ II"l(l;,lr~
89 if (numberOfWords > MAX WORDS) DoError("%s: too many words.~n",argv[01);

92 1' Read in the words 1 93 ~or(i =û;i<numberOfWords; + + i) {
94 wordNames~i] = ReadStrlng(listfp);
ss }

97 1~ Read in the model dictlonary ~1 98 1~l~ ' 2''' ~ = ReadString(listfp);
99 models = ReadDictlonary(modelName);

10t 1'~ Read in the number of dictionaries 'I
~02 numberOfFonts = Readlnt~listfp);
Copyright 1991 Xerox Corporation All Rights Reserved Sectlon C APP~NDIX, Page 51 103If (numberOfFonts > MAX FONTS) 04DoError("%s:toomanydictlonarles.~n",argv[0]); 2~77~69 106/~ Read ~n the dictionaries and their names '/
107for~i=0;i<numberOfFonts:+ +i){
108fontNames[i] = ReadString(listfp);
109fonts[i] = ReadDictlonary(fontNamesli]);
tlO }

112 /'Checktoseethatalldictlonarieshavethesamenumberofshapesasthespecifiednumberof words. '/
113for(i= 1;i<numberOfFonts; + +i) 114if(fonts[il->numberOfEntries ~ numberOfWords) 115DoError(''Dictionary J~S has too few entries.\n",fontNames[i]);
116if ~models->numberOfEntrles < numberOfWords) 117DoError("Model dictionaryhastoo fewof entrles.\n",NULL~;

120if (useL2~ {
121fprintf(stdout,"Using L2 on length norma~ized shapes.\n"~;
122dd.diffType = L2;
123 }
124else if (slopeConstrain) {
125 r~ l;"~(sldout,''Usingdynamictimewarpingwithslopecontrainedto[0.5,2].\n");
126 dd.diffTyp~ = CONSTRAINED;
127 dd.separate = separate;
128 if (separate) 129 fprint"stdout,''Top and bottom warped separately ~n");
130 else 131 fprintf(stdout,''Topand bottom warped together.\n");
132 }
133 else {
134 fprlntf(stdout,''Using dynamic timewarplng with bandwidth ~od.\n",,~c""alBd--d~t'iU~
135 dd.diffType = WARP;
136 dd.bandWidth = normalBandWidth;
137 dd.separate = separate;
138 if(separate) 139 fprintf(stdout,"Top and bottom warped separately.\n");
140 else 141 r~.,il,Lr(~L~lout,"Topandbottomwarpedtogether.\n'');

143 if(!useL2){
144 r~ "~ out,''Centerweight = Y0f.\n",~"~e,W~ l,L), 145 dd.. t- ,~, W~ t., '~, Wt,~
146 if (I~"~LI,~ ,.,al,.~) {
147 dd.l~.ly~l,r~ liL~ = TRUE;
148 fprintf(stdout,''Scores normalized by signal length.\n");
149 }
1 50 else 151 dd.l~,n~LlitLIl-.dli~ = FALSE;
152 }
153 dd.hillToValley = hlllToValleyLocal;
154 dd.topToBottom = topToBottom;
155 dd.pathFP = NULL;

Copyright ~ 1991 Xerox Corporatlon All Rights Reserved Sectlon C APPENDIX ~ Page 52 157 fprintf(stdout,"Words:\n');
158 for(i=û,i<numberOfWords + +I) 159 ~,,i"Lr(s~out,"%d: %s\n",i wordNames[i~ 7 ~ ~ 9 160 ~ ,L~(~Ldout,"\n'');
161 f~., i"~ ut,"Model font is Ycs.~n",modelName);
162 ~,."i"L~(,Ldout,''Fonts:~n");
163 for(i=0;i<numberOfFonts;+ +i) 164 r~,"~ dout,"%d: %s~n'',i,fontNames[i¦);
165 r~.,i-,L~(,ldolJt,"~n");

PrintCescriptors(models,modelName,~ n~;,numberOfFonts,fonts,fontNamff,number Of Words,&dd);
168 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlc~n C APPENi~lX Page 53 Jul 26 ~ 3:48 l991 descriptors.c #include <stdio.h > ~ ~ 7 7 ~ 6 ~
2 #include''mylib.h"
3 #inciude''types.h"
4 #include"dict.h"
S #include''diff.h"
6 #include"misc.h"
7 #include"descriptors.h'' 9 typedef struct {
l û f I oat score;
l t int word;
t32 } ~Compareruple,CompareTupieBody;
14 int TupleLessrhan(CompareTuple x,Compareruple y) {
16 If(x->score = = y->scote~
7 return û;
18 e~se if (x- >score < y- >score) 19 return-~;
else 2t return 1;

24 int CompareD.~ .l.,. El~ . ,L,(Descriptor x,Descriptor y~
{
26 i f (~ x = = ~y) 27 return û;
28 else if (-x < ~y) 29 return-1;
else 31 return l;

34 Descriptorr, 1l tr~n~scriptor(intmodellndex,Dictionarymodels,DictionarythisFont,int numberOfWords, DiffDescriptor dd) 36 {
37 D~ ;.o(El_.. _"~d~ \X WORD5+ 1]
38 CompareTupleBody results~MAX WORD51;
39 inti;
4t for(i =0;i<numberOfWords; + +i) {
42 results[il.score =
DiffPair(~(modeis->outlines+modellndex),'(thisFont->outlines+i),dd);
43 results~il word = i;
44 }
qsort(results,thisFont->numberOfEntries,s,zeof(CompareTupleBody),rupleLessThan);46 for (i = û; i < numberOfWords; + + i) {
47 descriptor[il = results[i].word + 1; /~ Descrlptor values are one greater than word indices ~1 48 if (results[i~.word = = modellndex) {
49 + +i;
Copyright~ 1991 XeroxCorporation All Rights Reserved Section C ~ APPENDIX Page 54 So break, ~ t 9 ~ 9 52 }
53 descriptorli] = '~0';
54 qsort(descriptor,i,sizeof(DescrlptorElement),CompareDes-,iul~,-EI~",~.,.~);
return(D~,.,i~.L~,,),l,.lup((char~)descrlptor);
56 }

58 void Pri ntField(char ~s,int w) 59 {
6û int i,l;
61 printf("%s",s);
62 1 = ~v-strlen(s);
63 for(i =0;i<1; + + i) 64 printf(''");
}

67 void PrintDescriptor(Descriptor d,int ~starCount,int ~correctCount) 68 int i = 1; 1~ Descriptor values are one greater than word indices '/
7û int temp;
71 temp = ~starCount;
72 i f (~d = = '\0') {
73 printf("t'');
74 + + starCount;
}
76 while ("d I = '\0') 77 whi le (i + + < ~d) 78 pri ntf~ " '' );
79 printf(""");
+ +~starCount;
81 d+ +;
82 }
83 if l~starCount-temp= = 1) 84 + + ~correctCount;
}

87 void PrintWords(~har ~"words,int numberOfWords) 88 {
89 int lengths[MAX_WORDSI;
go int i,j;
91 int maxLength = 0;

93 maxLength = 0;
94 for(i=0;icnumberOfWords;+ +i){
lengths[i~ = ,L.I~ d~[il);
96 if(lengths[il > maxLength) 97 maxLength = lengths~i];
98 }

100 for (j = 0; j < maxLength; + + j) {
lûl printf(" ");
102 for (i = 0;i <numberOfWords; + + i) 103 if (j<lengthsli]) 104 printf(''%c",~(words[il + j));
Copyright~1991 XeroxCorporation All Rlghts Reserved Sec~lon C APPENDIX Page 55 05 else 106 printf(" ")~ 6 107 printf~"~n");
108 }
109 }
~10 11~

Copyrirht~ 1991 XeroxCorporation All Rights Reserved Section C APPENDIX . Page 56 Jul 31 ~7:11 1991 dlff2.c 2 0 7 7 i~ 6 9 #include <stdio.h~
2 #include''boolean.h"
3 #include''types.h'' 4 #include"error.h"
s #include"pict.h"
6 #illclude"dict.h"
7 #i ncl ude " d i ff h "
8 #include"newMatch.h'' 11 extern double fabs(double);

13 /~ Dynamlc programming version of DiffPair t 14 inline float DiffPair(OutlinePair one, OutlinePair two, l S DiffDescriptor dd) 16 {
17 hillToVailey = dd->hillToValley;
18 if ((dd->sé~.d,~ (dd->pathFP! = NULL)) 19 DoError("DiffPair: separate cannot be used with pathfile option.\n",NULL);
swltch (dd->diffType) {
21 caseCONSTRAlNED:
22 if (dd->pathFP ! = NULL) 23 returnSlopeCMatchAndPath(one->top,one->bottom,one->numberOfLegs, 24 two->top,two->cott~rn, ->numberOfLegs, dd->~.,.t~.W~ ,dd-~!~.,y~ ",aiize,dd->toproBottom, 26 dd->pathFP);
27 else 28 if ~dd->separate) 29 return SepSlopeCMatch(one->top,one->numberOfLegs,two->top,two->numberOfLegs, dd->~ellLelWe.. ~ ,dd->~ y~ J~ alize)~dd->topToBottom +

SepSlopeCMatch(one->bottom,one->numberOfLegs,two->bottom,two->number Of Legs, 32 dd->~ell~e~w~ dd->~ yLllN
33 else 34 return SlopeCMatch(one->top,one->bottom,one->numberOfLegs, two->top,two->bottom,two->numberOfLegs, 36 dd->~."~ ,dd->l~.,yl~ ,--,alize,dd->topToBottom);
37 break;
38 case U:
39 if (dd->pathFP ! = NULL) DoError("DiffPair:L2doesnotsupportpathcomputation.\n'',NULL);
41 else 42 return L2Compare(one,two,dd->topToBottom);
43 break;
44 case WARP:
if (dd->pathFP I = NULL) 46 return NewMatchAndPath(one->top,one->bottom,one->numberOfLegs, 47 two->top,two->bottom,two->numberOfLegs, 48 dd->cellt~ dd->lL~ o~ dd >bandwidth~
49 dd->topTo80ttom, Copyright- 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX ~ Page 57 S~ else dd->pathFP); 2 ~ 7 7 9 ~ 9 52 if (dd->separate) 53 returnS~"M '.("n~ >top,one->numbe~OfLegs,two->top,two->numberOfLegs, dd->~ellLe~ c ~ dd->len5thNormalize~dd->bandWidth)~dd->topro30tto m +
SepMatch(one->boUom,one->numberOfLegs,two->bottom,two->numberOfLegs, 56 dd->~ell~e~ R~ dd >lengthNormalize~dd->bandWidth);
57 else 58 return NewMatch(one->top,one->bottom,one->numberOfLegs,two->top,two->bottom, two->numberOfLegs, 59 dd->~ellL~ IWt-i~l,L~dd->lengthNormalize~dd->bandWidth~
dd->topToBottom);
61 break;
62 default:
63 DoError("DiffPair: internal error.~n'',NULL);
64 }
}

67 #ifdef foo 68 inline float DiffPairAndPath(OutlinePair one, OutlinePair two, 69 float~tlllel~t~ 8ooLEAN lengthNormalize,int normal3andWidth, char ~filename,BOOLEAN doPath) 72 FILE ~fp;
73 floatscore;
74 if ((fp= fopen(filename,"w")) = = NULL) DoError("DiffPairAndMatch:erroropeningoutputfile/Os.\n",filename);
76 score = NewMatchAndPath(one->top,one->bottom,one->numberOfLegs, 77 two- > top,two- > bottom, two- > n u m berOf Legs, 78 ~e.. ~e,~'eiy;,L,I~"yLl,~lo-,.,allze~normalBandWidth~
79 fp,doPath);
fclose(fp);
81 return score;
82 }
83 #endif 85 BOOLEAN IsSymmetric(Picture pict) 86 {
87 int x,y;
88 floatmaxDiff = û;
89 for(y=0;y<pict->height;+ +y) for (x = 0;x<pict->width; + + x) {
91 floattemp = fabs(~((float~)(pict->data)+plct->width-y+x)-92 ~((float ~)(pict- >datd~ + plct- >wldth~x + y));
93 If (temp > maxDiff) 94 maxDiff = temp;
}
96 r,u,i.. ~(,L.le.""maxDiff = /~f.\n",maxDiff);
97 if (maxDiff > 0.01 ) 98 return FALSEj Copyright D 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX ' P~ge 58 99 return TRUE; 7 7 9 ~ 9 101 2 1~
102 /~Giventhenamesoftwodictionaryfi~es,COmputethescluareddifferenCe 103 ~ between every pair of shapes In the cross product of the dictlonaries.
104 ~1'he result is a matrix printed to stdout. rhe width and height are 105 ~ followed by the matrix entries in row major order. rhe output is in 106 asciitofacilitatereadingbyaSymbolics.~
107 PictureCompareDictionaries(Dictionarydictl, Dictionanydict2,DiffDescriptordd) 108 {
~09 Picture pict;
110 int x,y;
1 1 1 plct = new pict~dict2- >numberOf Entries, 112 dial-~numbe~OfEntr~es, I 1 3 32);

l l S for (y = 0; y < pict- > height; + + y) 116 for(x =0;x<pict-~width; + +x) ~
1 17 /~ for output files when printing and match ~/
118 printf("---> (%d,%d) <---\n",y,x);
119 ~((float~)(pict->data)+pict->width~y+x) =
lZû DiffPair(~(dictl->outlines+y), 121 ~(dict2->outlines+x), 1 22 dd);
123 }
124 i f ( ! Is.J . . . ~ :, ic~pict)) 125 r~,,i"lr(,l~.""Matrixisnotsymmet~ic.\n");
126 return pict;
127 }

129 void WritePictureAsAscii(Picture pict,char ~filename, 130 char Info1, char ~info2) 132 F~LE ~fp;
133 Int x,y;
134 intcount;

136 if((fp = fo~t~"(ri'~ t,Yt~,"w"))= =NULL) 137 DoError(''WritePictureAsAscii: error opening output file\n",NULL);
138 fprintflfp,"%s\n",infol);
139 fl~rintflfp,''%s~n",info2);
140 f l~ri ntfl fp, " #\n " );
141 f pri ntf~ f p, " % d\n% d\n ", pi ct- > wi dth, pi ct- > height);
142 fprintf(fp,"%3s","");
143 for (x = 0; x < pict->width; x + + ) 144 fprintf(fp,"%7d ", x);
145 fprlntf(fp,''\n");
146 for(y=0;y<pict->height;+ +y){
147 fprintf(fp, " %3d ", y);
148 count = 1;
149 for(x=0;x<pict->width; ~ +x~{
150 fprintf(fp,"%7.3f",~(((float~)pict->data)+ +));
lSl /~ if((pict->width > 10)&&(!((count+ +)%10))) 1 52 fprintf(fp,"\n");
1 53 ~/ }
Copyright ~1~ 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX Page 59 54 fprlntf(fp,".n");
1 5~5 fclose(fp); 2 ~ 7 ~
~s7 }

Copyright ~ 1991 Xerox Corporation A~l Rights Reserved Section C APPEN DIX ' Page 60 ~ul 22 15:21 1991 dmain.c 2 0 7 7 9 ~ 9 #include <stdio.h>
2 #include <math.h~
3 #include <values.h >
4 #include"booiean.h"
S #include"types.h"
6 #include"pict.h"
7 #include''dict.h"
8 #include''diff.h"
9 #include"match.h"
~0 #include "loclL~lly~ "-' h"

13 void main(int argc,char ~ ~argv) 14 {
Picturepict;
16 char ~infilel,~infile2,~outfile,~format;
17 Dictionarydictl,dict2;

19 i~largc ! = S) t printf~"Usage:\n");
21 printf(" %s infilel Infile2 outfile format\n",argvI01);
22 printf(" where fo~mat is either ascii or pict.\n'');
23 exitl- 1 );
24 }
26 infile1 = argv[ll;
27 i,lfile2 = argv[21;
28 outfile = argv[3];
29 format = argv[41;
3i dictl = ReadDictionary(infilel);
32 dict2 = ReadDlctionaryIinfile2);
33 pict = CompareDictionaries(dict~,dict2,1,TRUE,20;FALSE);
34 if(!,l,.,.,~,(r-,-l.,at,"pict")) write _ plct(outfile,pict);
36 else 37 WritepictLl~A~ ;;(r;ct~outfilp~d~ >infostring~dict2->infostring);
38 }

Copyright~ 1991 XeroYCorporation All F~lghts Reserved Sectic~n C APPENDIX Page 61 ~ug 15 20 20 199] drawBlobs.c #include <stdio.h> ~ ~ 9 S 5 2 #include "mylib.h'' 2 3 #include"types.h"
4 #include"dict.h"
6 #define WIDTH (800) 7 #define H MARGIN (20) B #defineV MARGIN(60) 9 #defi ne H SPAC~NG (20) 10 #define V SPACING ( 150) /- Must be cJreater than 2~X HEIGHT 'I
1~ #define X _ HEIGHT (~7) 13 extern int if int(double);
15 voidDrawVLine(Picturepict,intx,intyt,intyb) 16 {
17 Inti:
18 for (i = yt;i Cyb; + ~ I) 19 WritePixel(pict,x,i,1);

2 2 void D rawO u tl i ne(Picture pi ct,Outl i nePai r o, i nt x, i nt y) 23 {
24 int i,top,bottom;
for(i =0;i<c~>numberOfLegs; + +i){
26 top = irint(-~(o-~top+i)~X HEIGHT);
27 bottom = irint(~(o->bottorn+i)~X HEIGHT~X HEIGHT);
28 DrawVLi ne(pict,i + x,top + y,bottom ~ y);
29 }

32 int main(intarqc~char ~argv) 34 char ~infile,'outfile;
Dictionary dict;
36 Picture pict;
37 int i,totalLegs,totalLines;
38 int x,y,newX;

DefArg("%s~6s'',"infileoutfile",&infile,&outfile);
41 ScanArgs(argc,argv);
~2 43 dict = ReadDictionary(infile);

for (i = 0,total~egs = H MARGlN,totalLines = V MARGlN;i <dict->numberOfEntries; + + I) {
46 OutlinePair thisOutline = ~(dict->outlines + I);
47 totalLegs + = thisOutline->numberOfLegs + H SPACING;
48 if (totalLegs > WIDTH) ~
49 totalLines + = V SPACING:
totalLegs = H MARGIN + thisOutline->numberOfLegs + H SPACING;
51 If (totalLegs > WIDTH) Copyrightr~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX P~ge62 52 DoError("/~s: Shape is tOO wide. n ' .argv(OI), 2 ~ ~ 7 ~ ~ 9 54 }
5567 pict = new_pict(WlDTH,totalLines~V_MARGlNt2,1);
58 for(i=O,x=H MARGlN,y=V MARGlN;i<di->numberOfEntries;++i){
S9 OutlinePair thisOutline = ~(dlct->outlines + i);
61 newX = x + thisOutline->numberOfLegs + H SPACING;
62 if (newX > WIDTH) {
63 newX = H MARGlN+thisOutline->numberOfLegs+H SPACING;
64 x = H MARGIN;
y + = V _ SPACING;
66 }

68 DrawOutline(pict,~(dict->outlines + I),X,y);

x = newX;
71 }

73 write pict(outfile,pict);
7~ }

Copyrlght~ 1991 Xe!oxCorporation All Rights Reserved .

-Sectlon C APPENDIX i~ge 63 ~2616471991 equlvc 2~779~
#include <stdio h>
2 #include "myiib h "
3 #include "types h '' 4 #include "dict h"
S #include "diff h"
6 #i ncl ude " descri ptors h '' 8 void PrintEquivalenceClasses(int numberOfWords,char ~'wordNames, 9 int numberOfFonts,Dictionary fonts[~,char ~'fontNames, lû DiffDescriptordd~
Il ~
12 Descriptordescr~ptors[MAX FONTS'MAX FONTSI;
13 intllla~ /olJ[MAx WORDSI;
14 intword,fontl,font2,i;
int totalDifferent,totaiWords;
l6 int numberOfPairs;

18 for(word=0;word<numberOfWords;+ +word){
19 for(fontl=û,numberOfPairs=0;fontl<numberOfFonts;+ +fontl) 2 0 f or (font2 = 0; font2 < f on t 1; + + font2) 21 descriptorslnumberOfPairs+ +l = ~omputeDcL.~ u (. J,fonts[fontl], 22 fonts[font21,numberOfWords,dd);
23 for (i = 0;i < numberOfWords; + + i) 24 m/l~,l, Wo,J[i] = û;
for(i =û;i<rumberOfPairs; + +i) {
26 Descriptor p;
27 p = descnptors[i];
28 while (~p! = '~0') 29 mal~ 'o, i['p + + - 1 ¦ + +;
}
31 for (i = 0,total Di fferent = 0,totalWords = 0; i < numberOfWords; + + i) {32 if (mdL~ /o,J[i]) 33 + +totalDifferent;
34 totalWords + = mal~ v~olJli];
}
36 printf("%2ûs ~t\t%6d %6 2f ~66d %6,2f n",wordNames[wordl,totalWords, 37 (float)t,,~alW~, ~W"umberOfPairs,totalDifferent, 38 (float)totalDifferenU(floaL).u~dlWo,J,'numberOfPairs);
39 r~ 'c 1,''%20s:\t\t%6d %6 2f ~6d ~/~6 2f~n",~,ur~ia",~ Jl,totalWords, (flc~l~l~JLdl`Jv;~lJ~6lumberofpairs~totalDifferent~
41 (float)totalDifferenV(float)totalWo~ds'numbe~OfPairs);
42 }
43 }

46 void main(int argc,char '~argv) 48 char 'listFile;
49 intnumberOfFonts;
Dictionary fonts[MAX FONTSI;
51 char'~ul Lr!~ AY_FONTS];
52 char 'wordNames[MAX_WORDSI;
CopyrighttM991 XeroxCorporation All Rights Reserved Section C APPENDIX Page 6 53 int numberOfWords;
54 float., " lelW6i~1IL, SS int normalBandWidth;

lengthNorr~liz~ sr~l 7 elnreconstrain~warp~topToBottomoption~hillTovaileyoption;57 floattopToBottom,hillToValleyLocal;
58 FILE 'listfp;
59 inti,x,y;
DiffDescriptorBodydd; 2 ~ 7 7 9 6 ~
62 centerWeight = 1.0;
63 normalBandWidth = 20;
64 topToBottom = 1.0;
hiliToValleyLocal = 1.0;
66 DefArg("/Os","listFile",&listFile);
67 DefOption("-L2","-L2",&useL2);
68 DefOption("-slopeConstrain %f'',"-slopeConstraln <centerweight>", 69 &slopeconstrain~&~elll~lw6~
DefOption("-warp%f~/Od'',"-warp <centerwelght~ <bandwidth>'', 71 is~warp,&.ell~,Weiyl,l~&normalBandWidth);
72 DefOption(''-normalize'',''-normalize'',~lr.~yl~ nll~alize);
73 DefOption("-topToBottom %f","-topToBottom <ratio>",&topToBottomOption,&topTo80ttom);
74 DefOption("-hillToValley %f","-hillToValley <ratio>",&hillToValleyOption,&hillToValleyLocal);
ScanArgs(argc,argv);

77 if((listfp = foGen(listFile,"r"))= =NULL) 78 DoError("Errorop~ning file %s.~n",listfile);

/' Read in the number of words in each dictlonary ~1 81 numberOfWords = Readlnt(listfp);
82 i~(numberOfWords ~ MAX WORDS) 83 DoError(" /0s: too many words.\n" ,argv[0]);

/^ Read in the words '/
86 for (i = 0;i ~numberOfWords; + + i) {
87 ~OldNelll~:s[il = ReadSl,il,y(l;,lt~,), /' Read in the number of dictionaries '/
91 numberOfFonts = ~ " I.(li~r,.);
92 if (numberOfFonts > MAX FONTS) 93 DoError("ks:toomanydictionaries.\n",argv(01);

/^Readinthedictionariesandtheirnames~/
96 for(i=0;i<numberOfFonts;+ +i){
97 fontNames[il = ReadString(listfp);
98 fonts[i] = ReadDictionary(fontNames[i]~;
99 }

101 /'Checktoseethatalldictionarieshavethesamenumberofshapesasthespecifiednumbe~ of words. '/
102 for(i = 1;iCnumberOfFonts; + + i) 103 if (fontslil->numberOfEntries < numberOfWords) Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APP~NCilX ! Page 65 104DoError( Di~tionary%shastoofewen1rles.~n",fontNames[i¦): 779~9 ~06if (useL2) { 2 ~07printf("Using L20n length normalized shapes.`~n");
108dd.diffType = L2;
109 }
110else if (slopeConstrain) {
11 prlntf(" Using dynamic time warping wlth slope contrained to [0.5,21.\n");
~12 dd.diffType = CONSTRAINED;
~13 }
1~4else {
1~ 5printf(''Using dynamic time warplng with bandwidth :/~d.\n",norn~ ,d~'id~
l 16dd.di ffType - WARP;
1~7dd.bandWidth = normalBandWidth;
~8 }
119If (!useL2) {
120printf("Centerweight = :'Of.\n",centerWeight);
121dd.~ lLclWd.~ elllelWc.
122if (lengthNormali2e) {
~23dd.lengthNormalize = ~RUE;
124printf("Scores normaiized by signal length \n ');
125 }
1 26else 127dd.l~.,g~l,r~,,,,,c,li,e = FALSE;
~28 }
129dd.hillToValley = hillToValleyLocal;
130dd.topToBottom = topToBottom;
131dd.pathFP = NULL;

~33printf("Fonts:\n");
134for(i = 0;i<numberOfFonts; + ~ i) 135printf("~:d: %s~n",i,fontNames[il);
136printf("\n");

PrintEquivalenceClasses(numberOfWords,wordNames,numberOfFonts,fonts,fontNames,&dd);
139 }

~46 Copyright ~ ~ 99~ Xerox Corporation All Rights Reserved _ Section C APPE N DIX Page 66 Jul 314:31 1991 extract.c #include <stdio.h>
2 ~include < math.h >
3 #include <values.h> 2 0 7 7 9 6 9 4 #include"boolean.h'' S #include"types.h"
6 #include"dict.h"

8 #defineMAX STRING LEN 100 9 int Readlnt(FlLl~'fp) 11 char s[MAX STRING LEN¦;
12 Intx;

14 fgets(s,MAX STRING LEN,fp);
lS while(sscanf~s,"%d",is~x~l = 1) 16 r,u, i~ (,L.l~, l,''Readlnt: integer expected - reenter.~n'');
17 retur~ x;
18 }

void main(int argc,char argv) 21 {
22 char ~infile,'listFile,-outfile;
Z3 Dictionary dictl ,dict2;
24 int i;
intnumberOfE~tries;
276 FILE ~fp;
28 If (argc ! = 4) {
29 printf("Usage:~n");
printf(" ~.~s infile listfile outfile\n",argv[01);
31 exit(-l);
32 }

34 infile = argv[ll;
3s listFile = argv[21;
36 outfile = argv[3];

38 dictl = ReadDi~ aly(;~ e);

if ((fp= ro~,_"(li,lF;'e,"r")) = = NULL) 41 DoError("%s: error reading list file.~n",argv[01);

43 numberOfEntries = Readlnt(fp);
44 if (numberOfEntries < 0) DoError("%s:listfilemusthaveapositivenumberofelements.\n",argv[01);
46 printf("Copylng %d shapes.\n~numberofEntries);

48 dict2 = NewDict(numberOfEntries);

dict2->infoString = dictl->infoString;
S l for (i = 0; i < numberOfEntries; + + i) {
52 intshape;
Copyright~ 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDiX ' Page 67 shape = Readlnt(Fp), 4 if((shape<0)¦¦(shape>=dictl->numberOfEntrles)) DoError("%s: bad shape Index.\n",argv(0 56 ~(d'ct2->outlines+i) = ~(dictl->outlines+shape~
57 ~(dict2->-awOutlines+i) = ~(dictl >rawoutllnes+shape);
58 }
59 fclose~fp~;
WriteDictionary(dict2,outfiie);

62 }

Copyright D 1991 Xerox Corporatlon All Rights Reserved Sectlon C : APPENDIX Page 68 Jun 1416.12 1991 12Norm c 2 #include<values.h> 2~779 3 #include <string,h> 69 4 #include"bcolean.h"
S #include"types.h'' 6 #include''error.h"
7 #include''dict.h"

9 float L2Norm(OutlinePair signal, int startOffset.
OutlinePalrmodel) 11 {
12 float ~topl ,#top2,#bottom 1 ,#bottom2;
t 3 i nt i, overl ap;
14 float sum;
I S float temp;

17 If ~(startOffset < ) 11 18 ~startOffset + model->numberOfLegs > slgnal->numberOfLegs)) 19 ~oError("L2Norm: the model must over~ap the slgnal.\n",NULL);
21 topl = signal->top+startOffset;
22 top2 = model->top;
23 bottom 1 = signal- >bottom + startOffset;
24 bottom2 = model->bottom 26 overlap = signa~->numberOfLegs-startOffset;
27 if (over~ap > mode~->numberOfLegs) 28 over~ap = mode~->numberOfLegs:

3û for (i = 0,sum = 0; i < over~ap; + + i) {
31 temp = ~topl + + - 'top2 + +;
32 sum + = temp ~ temp;
33 temp = ~bottoml + + - #bottom2 + +;
34 sum + = temp # temp;
}

37 return sum;
38 }

Out~inePair LookupShape~char c, Dictionary mode~s) 41 {
42 /# dictionary file hasthe following order:
43 A8CDEFGH~JKLMNOPQRSTUVWXYZ
44 cL~d~ l, ;' ' ,op~-,Luvwxyz 47 ~1 48 intshape~ndex;
49 if ((c> = 'a'&&c< ='z')) shape~ndex = c-'a';
Sl e~seif(c = = ',') 52 shapelndex = 26;
Copyright~ lg91 XeroxCorporation A~ Rlghts Reserved Se~+lon C APPENDIX Page 69 else I f (c = = ' ') 4 shapelndex = 27; 2 ~ ~ 7 9 ~ 9 56 DoEtror("LookupShape:havenoshapeoneofthecharacters.\n",NULL~;
57 return ~(models->outlines + shapelndex);
58 }


6~ #define MAX STRING LENGTH 30 62 #defineMAX 'iHlFT ~0 63 #define MAX OVERLAP S
64 float L2Cu,~1,.,c., ~v~ String(OutlinePair signal, char ~string, Dictlonary models~
66 {
67 float ~costMatrix 68 int ~pathMatrlx;
69 int numberOfChars;
int letterlndex, startOffset;
71 float 'cursor;
72 int left;
73 int right;
74 OutlinePair modelShapes[MAX STRING LENGTHI;
char ~charCursor;
76 float minValue;
77 float temo;
78 int i,oldLeft,oldRight,mlnlndex;;

8û /~ Make sure inpLt string is not too long. ~/
81 numberOfChars = strlen(string);
82 if (numberOfChars > - MAX STRING LENGTH~
83 DoError("L2CompareWithString: strlng istoo long.\n'',NULL~;

/~Allocatespacefordynamic,,.u~l~,.,m".garray. /
86 1~ For now, be a space hog. /
87 costMatrix = (float )cailoc(signal-~numberOfLegs-numberOfChars, 88 si2eof(float~;
89 pathMatrix = (int ~)calloc(signal->numberOfLegs-numberOfChars, 9û sizeof(int~;
91 if ((costMatrlx = = NULL)¦¦(pathMatrix = = NULL)) 92 DoErrorl''L2CompareWithString: cannotallocatespace.~n",NULL);

94 /~ Lookup the shapes .c,-, ~",u~ i to the characters in the string. ~/
9S charCursor = string;
96 for(i=0;i<numberOfChars;+ +i) 97 modelShapes[i]=LookupShape~-charCursor+ +,models);

99 /~ Since the cost matrix is larger than the reglon containing valid 1ûû alignments,firstfillinthearraywithlargecosts. Later,some 101 ~ of thesewill beoverwritten. ~1 102 cursor = costMatrlx;
103 for(i =0;i<signal->numberOfLegs~numberOfChars; + +i) 104 cursor+ + = MAXFLOAT;

106 1- Fill in leftmost column ~1 107 left = 0;
Copyright~ 1991 XeroxCorporation All Rlghts Reserved Sec+~ion C APPENDIX Page 70 108 rlght = MAX SHIFT;
109 f~r(startOffset=left;startOffset<right; + +startOffset~
110 if(startOffset + modelShapesl01->numberOfLegsC=
111 signal - > n u m berOf Legs) 112 ~coslMatrix +startOffset-numberOfChars) = 21) 7 ~ 9 ~ 9 113 1, 1,,(siy.. e,l, startOffset, modelShapes[0l);

115 1~ Now do the rest of the columns ~/
116 for(letterlndex = 1; letterlndex < numberOfChars; + + letterlndex) {
117 oldLeft = left;
118 oldRight = rlght;
119 left + = modelShapes~letter~ndex-1]->numberOfLegs;
~20 right + = modelSh~p~. l ;Læ, I" le,~ ->numberOfLegs + MAX SHIFT;
121 for(startOffset= left;startOffset<right; + +startOffset~ {
122 if (startOffset + modelShapeslletterlndexl->numberOfLegs < =
123 signal->numberOfLegs) {
124 temp = L2Norm(signal,startOffset,modelShapes[letterlndexl);

126 /~ This could be made quite a bit faster si nce for each start offset, 127 wejustaddanelementtothesetwearemlnimlzlngover.~/
128 minValue = MAXFLOAT;
129 /~ ~(costMatrix+oldLeft~numberOfChars+letterlndex-1); ~/
130 minlndex = oldLeft;
131 for(i=oidLeft;(i<oldRight)&&(i<startOffset); + +i){
132 float temp2;
133 temp2 = ~costMatrix + i ~numberOfChars + letterlndex- 1 );
134 if (temp2 < minValue) 135 minlndex = i;
136 minValue = temp2;
137 }
738 }
139 ~(costMatrix + startOffset~numberOfChars + letterlndex) =
140 minValue + temp;
141 t~pathMatrlx + startOffset~numberOfChars + letterlndex) =
142 minlndex;
143 } /~ End of if ~/

1 4s } /^ for startOffset /
146 }/~ forletterlndex ~/

148 /~Nowthatallthecostshavebeenfilledin,findthecheapest~/
149 if (right-l + mc,J Shap~I.,umberOfChan-ll->numberOfLegs + MAX_SHIFT <
150 signal- > numberOf Legs) 151 /'rlnthiscase,thechainofleuershapesdoesnotspanthesignal.~/
152 minValue = MAXFLOAT;
153 else {
154 minValue = MAXFLOAT;
155 mlnlndex = left;
156 for(i = left;(i<right)&&(i<signal->numberOfLegs); + + i) 157 float temp2;
158 temp2 = ~(costMatrix + i~numberOfChars + numberOfChars-1);
159 if (temp2 < mlnValue) {
160 minlndex = i;
161 minValue = temp2;
162 }
Copyright~ 1991 XeroxCorporation All Rights Reser~led Section C APPE N DIX P~g e 71 63 }
64 } 2~37~i3~9 166 free(costMatrix);
167 free~pathMatrix);
168 return minValue;
169 }

171 void PrintPath(int ~pm, intwidth, int height, intindex) 173 inti;
174 for (i = width-l ;i > = 0;--i) {
175 printf("/Od",index);
176 index = ~(pm+;.,de~ JLl,+f);
177 }
178 printf("~n");
t79 }

18~ void PrintMatrix(float tm,int width, int height) 182 {
183 int i;
184 intj;
185 for(i=0;i<height;+ +i){
186 printf("/Od:",i);
187 for(j=û:j<width;+ +j) ~8B printf("%6.2e",~m+ +);
~89 printf("\n");
~90 }
~91 }
~92 193 typedef struct CTuple {
194 intindex;
l9S floatvalue;
196 } CompareTuple;

198 I nt TupleLessThan(CompareTuple ~tl, CompareTuple 't2) 199 {
200 return t I - >value > t2->value;
2ûl }

203 void L2CompareDictToString(Dictionary unknownDict, 204 char ~string, 205 Dictionary modelDict, 206 BOOLEAN is8atch) 207 {
208 CompareTuple ~results;
209 int i;

2~ ~ If ((results = (CompareTuple ~)calloc(unknownDict->numberOfEntries, 2~2 si~eof(CompareTuple))) = =
2~3 NULL) 214 DoError("L2CompareDictToString: cannotallocatespace.~n",NULL);

216 for (i = 0;i <unknownDict->numberOfEntries; + + i) {
2~7 (~(results+i)).index = i;
Copyrlght~ 199~ XeroxCorporation All Rights ~eserved Section C APPENDIX, Page 72 218 (~(results+l)).value = L2CompareWithStrlng(~(unknownDlct-~outl~nes+,), 2~9 strlng, 221 } mode~Dict); 2 !) ~ ~ 9 ~ 9 223 qson(resultS, 224 unknownDict->numberOfEntries, 225 si~eof~CompareTuple~, 226 TupleLessThan);

228 if (isBatch) {
229 printf("%d(%fl\n",(~results).index,(~results).value);
23û }
231 else ~
232 printf("\n");
233 for(i=û;(i<S)&&(iCunknownDict->numberOfEntries);++i) 234 printf(''%d: %f\n",(~(results + I)).index,(~(results + i)).value);
235 printf(''~n");
236 }

238 free(results);
239 }

241 void main(int argc,char ~argv) 242 {
243 char ~unknowns,~models;
244 chars[MAX STRIN6 LENGTH~ tl;
245 Dictionary unkno~rvnDIct, modelDict;
246 int selection;
247 char ~crPointer;
248 BOOLEAN done = FALSE;
249 BDOLEAN batch;
250 char words;

252 if (argc ! = 3 && argc I = 4) 253 pl~intf("Usage:\n");
254 prlntf(" hsCunknowns>Calphabet>[Cbatchwordlist>l~n",argv[0]);
255 printf(" If the batch file is not speclfied, the program runs\n");
256 printf(" ininteractivemode.\n'');
257 exit(- 1 );
258 }

26û ur~knowns = argv[ll;
261 models = argv[21;
262 if (argc = = 4) {
263 batch = TRUE;
264 words = argv[3~;
265 } else 266 batch = FALSE;

268 unknownDict = ReadDictionary(unknowns);
269 modelDict = ReadDictionary(models);

271 if (batch) 272 Fl LE ~fp;
Copyright 1991 Xerox Corporation All Rights Reserved Se~llon C APPENDIX Page 73 ~73If((fp = fopen(words,"r"))= =N(JLL) 74DoError("12Norm: can't open Input file '~cs. n",words);
275while (!done) {
276fgets(s,MAX STRING LENGTH,fp); ~ n 277if ((s[ûl = = r') 11 (s[Or= = '~n')) ;~ "
278done = TRUE;
279else {
280crPointer = strchr(s,'~n');
281if (crPointer ! = NULL) 282*crPointer = '\0';
283printf("%s:",s);
284L2CompareDictToString(unknownDi~t,s,mode~Dict,TRUE);
285 }
286 }
287 }
288else {
289while (!done) {
290printf("Enter a word to search for: ");
291fgets(s,MAX STR!NG LENGTH,stdin);
292if ((s[01 = = rO') 1l (s[Or= = '\n~)) 293done = TRUE;
294e!se {
295crPointer = strchr(s,'in');
296if (crPointer ! = NULL) 297*crPointer = '\0';
298printf("Comparing shape %s to the image\n",s);
299L2CompareDictToString(unknownDict,s,modelDict,FALSE);
300 }
301 }
302 }
303 }
3a4 Copyright ~1991 Xerox Corporation All Rights Reserved Sectlon C APPEN~IX ' Page 74 Jun 1817:001991 12Norm2 c #include Cstdio.h~ 2 0 7 ~ 9 ~ 9 2 #include <values.h~
3 #include <slring.h>
4 #include"boolean.h"
S #include"types.h"
6 #include"error.h'' 7 #include"dict.h"

9 #define MAX _ STRING _ LENGTH 3û
1û #defineMAX SIGNAL LENGTH300 11 #defineMAX_SHIFT 10 13 #define MlN(a,b) ((a)<(b)?(a):(b)) 14 #defineMAX(a,b)((a)~(b~?(a):(b)) 16 typedef struct ( 17 int numberOfSymbols;
18 intsignalLength;
19 float ~costs;
} ~CorrelationSet,CorrelationSetBody;

22 CorrelationSet NewCorrelationSet(int numberOfSymbols,intsignalLength) 24 CorrelationSettemp;
25 if((temp = (Cu,-~' ' ,S~ '1,sizeof(Cc,.. ~l~l,u.15_~30cly)))= =NULL) 26 DoError(" NewCorrelationSet: cannot al locate space.~n '' ,NULL);
27 temp->numberOfSymbols = numberOf'iymbols;
28 temp->signalLength = signalLength;
29 if((temp->costs = (float-)- 'lc:(nu".L~.OfSymbols"signal~ength,sizeof(float)~)= =NULL) 3û ~oError("NewCorrelationSet: cannot allocate space.\n",NULL);
31 return temp;
32 }
34 #ifdef foo float CorrelationValue(CorrelationSet c,i nt symbol ,i nt offset) 37 r~turn ~(c->costs ~ symbol~c->signalLength ~ offset);
38 }

voidSetCorrelationValue(CorrelationSetc,intsymbol,intoffset,floatvalue) 41 {
42 ~(c->costs I symbol~c->signalLength~offset) = value;
43 }
44 #endif #defineCûrrelationValue(c,s,o)(~((c)->cûsts~(s)~(c)->signalLength~(o))) 46 #defineSetCorrelationValue(c,s,û,v)(~((c)->costs I (s)~(c)->signalLength~(o))=(v)) 48 int CorrelationSetSize(CorrelationSet c) return c->numberOfSymbols;
51 }

Copyright~ 1991 Xero1~Corporation All Rights Reserved Sectlon C APPENDIX . P~ge /~
'lt CorrelatlonSetWidth(CorrelatlonSet ~) 2 ~ 7 7 9 ~ 3 SS returnc->signalLength;
56 }

58 void PrintCorrelation(CorrelationSet c,int character) 59 {
~nt 1;

62 for (i = 0;icc->signalLength; + + i) {
63 printf("%d:%6.2f\n",i,~(c->~osts+charactertc->slgnalLength+i));
64 }
printf("'~n");
66 }

68 float L2Norm(OutlinePair signal, int startOffset, 69 OutlinePairmodel) {
71 float top1 ,~top2,'bottom 1 ,~bottom2;
72 Int i,overlap;
73 fioat sum;
74 float temp;
76 if ((startOffset < 0)11 77 (startOffset + model->numberOfLegs > signal->numberOfLegs)) 78 DoError("L2Norm: themodel mustoverlapthesignal.\n",NULL);

topl = signal-~to~o+startOffset;
81 top2 = model->top;
82 bottoml = signal-~bottom+startOffset;
83 bottom2 = model->bottom;

overlap = signal->numberOfLegs-startOffset;
86 if (overlap > model->numberofLegs) 87 overiap = model->numberOfLegs;

89 for~i=0,sum=0;i<overlap;+ +i){
temp = 'topl + + - ~top2 + +;
91 su m + = temp ~ temp;
92 temp - ~bottoml + + -~bottom2+ +;
93 sum + = temp ~temp;

96 return sum;
97 }

99 CorrelationSet PreProcessSignalWithChars(OutlinePair signal,Dictionary charDict~
100 {
101 CorrelationSetcSet;
102 intthisChar,offset;
103 OutlinePaircharSignal;

105 cSet = NewCorrelationSet(charDict->numberOf~nt,ies,signal->numberOfLegs);
~06 107 for (this~har = ~; thisChar < charDict->numberOfEntries; + + thisChar~ {
Copyright ~ 1991 Xerox Corporation All Rights Reserved Secti o n C APPENDIX Pag e 76 108charSignal = ~(~harDict->outlines+thisChar~;
109for (offset = 0; offset < signal->numberOfLegs-charSignal->numberOfLegs + l, + toffset) ~, l IlSetCorrelationV2lue~cSet thisChar offset L2Norm(signal offset charSigndl)); 2 ~ 7 7 9 6 9 112return cS~t;
113 }

115 CorrelatlonSet~PreProcessDictionaryWithChars(DictionarysignalDict,DictionarycharDlct) 116 {
117CorrelationSet ~correlationSets;
118IntthisWord;

120corre~ationSets = (CorrelationSet ~)calloc(signalDict->numberOfEntries,sizeof(CorrelationSet));
121 If (correlationSets = = NULL) 122 DoError("PreProcessDicitonary: cannot allocate space.\n",NULL);
123 for (thisWord = 0; thi sWord < signal Dict- > nu mberOf Entries; + + thisWord) {
124 (correlatlonSets + thisWord) =
PreProcessS;gnalWithChars(^(signalDict- >outlines + thisWord),charDict);
125 printf("~rd",thisWord);
126 }
127 return correlationSets;
128 }

130 CorrelationSetFI.~,u~e~s;;y.-al~'ill,Bl~n~,(OutlinePairsignal) 131 {
132 CorrelationSet cSet;
133 intblankWidth,offset;
134 intnumberOfLegs = signal->numberOfLegs;

136 cSet = NewCorrelationSet(MAX SHlFT,numberOfLegs);

138 for (offset = 0; offset < numberOfLegs; + I offset) {
139 SetCorrelationValue(cSet,0,offset,0):
140 }
1 41 for (offset = 0; offset < numberOfLegs; + + offset) {
142 floattop,bottom;
143 top = '(signal->top+offset);
144 bottom = ~Isignal->bottom+offSet);
145 SetCorrelationValue(cSet,l,offset,top~top + bottom~bottom);
146 }
147 for (blankWidth = 2; blankWidth < MAX SHIFT; + + blankWidth) ~
148 for (offset = 0; offset < numberOfLegs-brankWidth t l; + + offset) {
149 floattop,bottom,temp;
150 top = '(signal->top+offset+blankWidth-1);
151 bottom = ~(signal->bottom+offset+blankWidth-l);
152 temp = top~top + bottom~bottom + CorrelationValue(cSet,blankWidth-1 ,offset);
153 SetCorrelationValue(cSet,blankWidth,offset,temp);
154 }
155 }
156 return cSet;
157 }

159 CorrelatlonSet ~PreProcessDictionaryWithBlanks(Dictionary signalDict) Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX ' Page 77 161 CorrelationSet ~correlalions; 2 0 7 ~ 9 162 int thisWord;

164 correlations = (CorrelationSet ~)calloc~signalDict->numberOfEntries,si~eof~CorreistlonSet)~;

166 for (thisWord = 0; thisWord < signalDict->numberOfEntries; ~ + thlsWord) {
167 ~correlations ~ thisWord) =
PreProcessSignalWithBlanks(-(signalDict->outlines ~ thisWord));
168 printf('':/ld'',thisWord);
169 }
170 return correlations;
171 }

173 int LookupShapelndex(char c, Dictionary models) 174 {
175 /~ dictionary file has the following order, 177 abcdefghij~lmnopqrstuvwxyz 179 ,.
1 80 ~/
181 intshapelndex;
182 if ((c> = 'a'&&c< = '~')) 183 shapelndex = c-'a';
184 elseif(c = = ',') ~85 shapelndex = 26;
186 elseif(c = = '.'~
187 shapelndex = 27;
188 else 189 DoError("LookupShape: have no shape one of the characters.`~n",NULL);
l9û return shapelndex;
~91 }
~92 194 float L2Cun~ ';Ll,String(intsignallndex, lgS char ~stting, 196 CorrelationSet charCorrelations, 197 Corre~ationSet blankCorrelations, 198 DictionarysignalDict, 199 . Dictionarymodels) 200 {
201 /~Allocatespacefordynamicu.vu~._,,,,,.,.~yarray 1 202 ~ For now, be a space hog. ~/
203 float costMatrix[MAX SIGNAL LENGTHI[MAX SrRlNG LENGTHI;
204 int pathMatrlx[MAX SIGNAL LENGTHIIMAX STRING LENGrHI;
205 char ~charCursor;
206 OutlinePair modelShapes[MAX STRING LENGTHI;
207 intmodellndices[MAX STRING LENGTl~;
208 int numberofchats;

210 int letterlndex, startOffset;
211 int left,right;
212 int searchLeft,searchRight,rightEdge;
Copyright''J 1991 XeroxCorporation All Rights Reserved Sec+~ion C APPENDIX ' Page 78 213 floatminValue 1 214 floattemp;
215 inti,oldLeft,oldRight,minindex; ~ i 7 7 (1~ /1 216 IntsignalLength; f~ J ~ ~ U

218 signalLength = (~(signalDict->outlines+signallndex))->numberOfLegs;

220 /' Make sure i nput string is not too long . '/
221 numberOfChars = strlen(string);
222 if ~numberOfChars > = MAX STR~NG LENGTH) 223 DoError(''L2Cù,~pa,~Will,Strlng:stringistoolong.~n'',NULL);

225 /' Make sure signal is not too long. '/
226 if (signalLength > = MAX SIGNAL LENGTH) 227 DoError("i.2Cu,.,~ 'J;li~tring:signalistoolong.\n",NULL);

229 1^ Lookup the indices of the signals ~ Jùn.l;l~9 to the characters in the string. '/
230 charCursor = string;
231 fûr (i = 0; i < numberOfChars; + + i) {
232 mûdellndices[il = LookupShapeindex('charCursor+ +,models);
233 modelShapes[i¦ = '(models->outlines+modellndices[il);
234 }

236 /~ Since the cost matrix is la~ger than the region contai ni ng val id 237 ' alignments, first fill in the array with large costs. Later, some 238 ' ofthesewill beoverwrltten. ~/
239 /~WARNlNG:doesMAXFLOAT + smallFloat = = MAXFLOATordûesitroll?~/
24û
241 Float ~cursor;
242 cursor = ~ [0][01);
243 for(i =0;i<MAX SIGNAL LENGTH'MAX STRING LENGTH; + + i) 244 'cursor + + = MAXFLOAT, 245 }

247 /' Fill in leftmost column '/
248 left = 0;
249 right = MIN(MAX SHlFT,signalLength-.,lùd~'Sha~ ]->numberOfLegs);
250 for(startOffset=le~t;startOffset<right; + +startOffset) 251 costMatrix[startOffsetl[01 = CorrelationValue(blankCorrelations,startOffset,startOffset) 252 CorrelationValue(charCorrelations,mod~'l,)di~.:,[01,startOffset);

254 /~ Now do the rest of the columns ~/
255 for (letterlndex = 1; letterlndex < numberOfChars; + + letterlndex) {
256 oldLeft = left;
257 oldRight = right;
258 left + = modelShapes[letterlndex-1~->numberOfLegs;
259 1~ If string of characters is too long for this signal, abort by returning a large cost. '/
260 if (left> = signalLength) 261 return MAXFLOAT;
262 right + = modelShapes[letterlndex~ >numberOfLegs + MAX SHIFT;
263 right = MlN(right,signalLength-modelShapes[letterlndexl->numberOfLegs+ 1);

265 for (startOffset = left;startOffset< right; + + startOffset) {
266 temp = CorrelationValue(charCorrelations,,,~ûclcllnd;~el,[leuerlndexl~startoffset);
Copyright ~1991 Xerox Cûrporation All Rights Reserved Sectl o n C APPEN Dl X P~ge 79 ~68 /~ This could be maae qul~e a blt faster slnce for ea~h start offset, 2 0 7 7 ~ ~ 9 269 ~wejustaddane;ementtothesetvveareminlmizingover.~/

271 searchLeft = startOffset-modelS~1a~ ;Lel 1~ ,deA- ~ 1- > numberOfLegs-MAX_SHIFT;
272 searchLeft = MAX(searchLeft,oldLeft);
273 rightEdcJe = searchLeft+modelShapes[letterlndex-ll->numberOfLegs;
274 searchRight = startOffset-modeiShapes~letterlndex-ll-~numberOfLegs;
275 searchRight = M;~.(sèd,~,lRiy~ oldRight~;

277 minlndex = searchLeft;
278 minValue = costMatrlx[searchLeftl[letterlndex-ll +
279 CorrelationValuelblankCorrelations,startOffset-rightEdge,rightEdge);

281 for (i = searchLeft;i <searchRight; + + i, + + rightf dge) {
282 float temp;
283 temp = costMatrlx~il[letterlndex-~l +
284 CorrelationValue(blankCorrelations,startOffset-rightEdge,rightEdge);
285 if (temp < minValue) {
286 minlndex = i;
287 minValue = temp;
288 }
289 }

291 , :r'. iA[~L.. ~offsetl[!-~e~ lé~l = minValue~temp;
292 pathMatrixlstarto~e~ elllldcAl = minlndex;
293 } 1~ for startOffset 'I
294 } /~ for letterlndex ~/

297 /Afillinthecostsforblanksattheendoftheword~/
298 rightEdge = left+modelShapes[letterlndex-ll->numberOfLegs;
299 for(startOffset=left;startOffset<right;+ +startOffset,+ +rightEdge){
300 if (rightEdge + MAX Sl-ilFT > = signalLength) {
301 costMatrix[startOffsetl[letterlndex-11 + =
302 CorrelationValue(blankCorrelations,signalLQngth-l-rightEdge,rightEdge);
303 }
304 else {
305 /~ this chain of letters does not span the word ~/
306 costMatrix[startOffsetl[letterlndex-ll = MAXFLOAT;
307 }
308 }

3~0 /~keepminlndexfordebugglngpruposes~/
3~1 minlndeA = left;
3t2 minValue = costMatrix[leftl[letterlndex-l¦;
313 for (i = left;i <right; + + i) {
314 floattemp;
3~5 temp = costMatrix[il[letterlndex-~¦;
316 if (temp < minValue) {
317 minlndex = i;
318 minValue = temp;
3~9 }
320 }

Copyright ~ 1991 Xerox Corporatlon All Rlghts Reserved Secti on C APP E N Dl X / Pa g e 80 322 return mlnValue;
323 }

326 void PrintPath~int ~pm, int width, int he~ght, int index) 2 ~ ~ r~ 9 6 9 327 inti;
328 for(i=width-l;i>=0;--i~{
329 printf("%d",index);
330 index = ~(pm+index~width~i);
331 }
332 printf(''\n");
333 }

335 void PrintMatrix(float 'm,intwidth, int height) 337 int i;
338 int j;
339 for (i = 0; i < height; ~ ~ i) {
340 printf("%d:",i);
341 for (j = 0;j <width;
342 printf("%6.2e ",-m 343 printf("\n");
344 }
345 }

347 typedef struct CTuple {
348 int index;
349 float value;
350 } CompareTuple;

352 i nt TupleLessThan(CompareTuple ~tl, CompareTuple t2) 353 {
3s4 return tl->value ~ t2->value;
355 }

357 void L2CompareDictToString(char ~string, 358 CorrelationSet ~charCorrelations, 359 CorrelationSet ~blankCorrelatlons, 360 DictionarysignalDict, 361 DictionarymodelDict, 362 BOOLEAN isBatch) 363 {
364 CompareTuple ~results;
365 int i;

367 if((results = (CompareTuple~)calloc(signalDict->numberOfEntries, 368 sizeof(CompareTuple))) = =
369 N U LL) 370 DoError(" L2CompareDictToString: cannot al~ocate space.~n" ,NULL);

372 for (i = 0; i C signal Dict- > numberOfEntries; ~ + i) {
373 (~(results+i)).index = 1;
374 (~(results+i)).value = L2C~,.".~ String(i,strlng, 375 ~(charCorrelations + 1), 376 ~(blankCorrelations ~ i), Copyright 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX ;'~ge 81 2~779~9 ~7 slgnalD~ct, ~8 modelDI~t);
379 }

381 qsort(results, 382 signalDict->numberOfEntries, 383 sizeof(CompareTuple), 384 TupleLessThan);

386 if (isBatch) {
387 printf("/,d(/,f)\n",(~results).index,(~results).value);
388 }
389 else ~
390 printf("~n");
39T for(i=û;(i~S)&&(i<signalDict->numberOfEntries);+ +i) 392 printf("/Od: %f~n",('(results + I)) index,(-(results +I)).value);
393 printf("\n");
394 }

396 free(results);
397 }

399 void PrintDictStats(Dictlonarydict) 401 int i,sum = 0;
402 printf("Dictionary has r/rd entries.\n",dict->numberOfEntrles);
403 for(i =O;i<dict->numberOfEntries; + +i) 404 sum + - (~(dict->outlines + i))->numberOfLegs;
405 printf("The total length of the shape contours is %d pixels.\n",sum);
406 }

408 void main(i nt argc,char ~argv) 41û char 'unknowns,-models;
417 chars(MAX STRING LENGTH + 11;
412 Di~tionary unknownDIct, modelDict;
4i3 Intselection;
414 ~har ~rPointer;
415 300LEANdone = FALSE;
416 300LEAN batch;
417 ~har~words;
418 CorrelationSet ~charCorrelations:
419 C~ el.,li~J.,Sct ~blankCorrelations;

42t if (argc ! = 3 && argc ! = 4) t 422 printf("Usage:\n");
423 printf(" %s<unknowns><alphabet>[<bat~hwordlist>]\n",argv[O]);
424 printf(" If thebat~hfileisnotspeclfied,theprogramruns\n");
425 printf(" in interactive mode.\n");
426 exi t(- 1 );
427 }

429 unknowns = argv[ll;
430 models = argv[21;
431 If (argc = = 4) {
Copyright 31991 XeroxCorporation All Rights Reserved Section C - - APPENDIX Page82 432 batch = TRUE;
433 words = argv~3~;
434 } eise 435 batch = FALSE;
443367 unknownDict = ReadDictionary(unknowns); 2 ~ ~ r~ ~ 6 9 438 modelDIct = ReadDictionary(models);

440 PrintDiStats~unknownDict);
441 printf("Plt~.. u~ i"y.. \n");
44Z charCorrelations z PreProcessDi~li.",.,.y\l\'iLl,Chars(unknownDict,modelDict);
443 blankCorrelations = PreProcessDi~Li.s".,l~WiL1161anks(unknownDict);
444 printf("done.\n");

446 if (batch) {
447 FILE ~fp;
448 if((fp = fopen~words,"r"))= =NU-L) 449 DoError(''l 2Norm: can't open input file ,'0 s.\n" ,words);
45û while (!done) {
451 fgets(s,MAX _ STRING LENGTH,fp);
452 if ((s[01 = = '\0') 11 (s[Or= = '\n')) 453 done = TRUE;
454 else {
455 crPointer = strchr(s,'\n');
456 if (crPointer ! = NULL) 457 ~crPointer = '\0';
458 printf("%s:'',s~;

L2CompareDictToString(s,charCorrelations,blankCorrelations,unknownDict,modelDlc t,TRU E);
460 }
461 }
462 }
463 else {
464 while (!done) {
465 printf("Enter a word to search for: ");
466 fgets(s,MAX STRING ~ENGTH,stdin);
467 if ((s[o] = = ~0') 11 (s[Or= = '\n')) 468 done = TRUE;
469 else {
470 crPointer = strchr(s.'\n');
471 if(crPointer!= NULL) 472 ~crPointer = '\0';
473 printf("Comparing shape %s to the image\n",s);

L2CompareDictToString(s,charCorreiations,blankCorrelations,unknownDi,modelDlc t,FALSE);
475 }
476 }
477 }
478 }

Copyright 1991 Xero~Corporation All Rights Reserved ~ecllon C APPENDIX Page 83 n ~521:32 1991 matchc 2~7~9~9 2 match.c 3 align 2 sequences s ~ run as: match seq 1 seq2 9 1~
lû TODO: I)don'tcomputeoverpantsofarrayoutsideofconstraints I l 2) distance score for top and bottom paths 12 t 14 #include < stdio.h >
lS #include <math.h~

17 #include''boolean.h"
18 #include"types.h"
19 #include "error h"
#include"pict.h"
21 #include"dict.h"
22 #include''diff.h'' 23 #include"diff2.h"
24 #include"match.h"
26 #ifndef MAXLINE
27 #define MAXLINE 256 28 #endif #ifndef MAXNAME
31 #defineMAXNAME t28 32 #endif 34 #ifndef TRUE
#define TRU E 1 36 #endif 38 #ifndef FALSE
39 #define FALSE 0 #endif 42 int matchcntr = 1; /~ used for writing out set number of matches /

void 46 main~argc,argv) 47 int argc;
48 char ~argv[l;

51 /~
52 ~ read in multlple parameter files, write out selected fields as shorts Copyright~ 1991 Xero~(Corporatlon All Rights Reserved Section C APPENDIX Page 84 53 'I

SS int i,j;
56 int seqlength;
58 float matchvecs(); 2 ~ 7 7 9 6 9 S9 float test[MAXSEQLENGTHI;
60 float ref[MAXSEQLENGTH];
6~ ~1 62 1~
63 ' read in args 65 1~
66 debug = FALSE;

68 for (;argc > I && (argv[l l[û~ ; argc--, argv t t ) 70 switch (argv[l 1[1 ]) 72 case'd':
73 debug = TRUE;
74 break;
75 case 'h ':
76 horweight = (float)atoi(&argv[~][2~);
77 break;
78 case'v':
79 verweight = (f~oat)atoi(&argvlll[21);
break;
81 case'x':
82 diagweight = ~float)atoi(&argv[1][2]);
83 break;
84 default:
printf("match:unknownswitch~s~n'',argv[l]);
86 exit(l);
87 }
88 }

9û if(argc ! = 1) 92 printf ("Usage: match [-b<begsamp> -d(debug) -e<endsamp>\n");
93 printf ("argc: %d\n", argc);
94 exit ( I );
}
96 'I
97 /" debugging ~/
98 /~ for(i = 0; i < S; i + I ) 99 test[i~ = (float)i;
100 for(i = S; i < 10; i+ +) ~01 test[il = (float)(.5~ 4) + S);
102 for(i = 0; i < S; i + +) 103 ref[il = l.S~i;
104 matchvecs(test, 10, ref, S);

106 }
1 07 ~/
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX Page 85 ~8 1 09 /~
t 10 floatDPDiffPair~OutlinePairone, OutlineP2irtwo) ~ 1 2 If (one = = two){ 2 Q 7 ~ 9 ~ 9 1 ~3 printf~"matches\n");
1 l4 return(0.0);
1~5 }
116 else{
117 printf(''nomatch~n");
118 return(l 0);
119 }
120 }

123 floatDPDiffPair(OutlinePairone,OutlinePairtwo) 1 24 /~
125 ~question,shouldtopandbottomdistancebeforcedtobecomputedtogether?
126 ~ use another dlstance score to check how far off the two are?

129 {
130 float topscore;
131 float bottomscore;

133 if (debug) printf("top: ");
134 topscore = matchvecs~one->top,one->numberOfLegs, 135 two->t~p,two->numberOfLegs);
136 if (debug) printf(" bottom: ");
137 bo~ mi~ e = matchvecs(one->bottom,one->numberOfLegs, 138 two-~bottom,two->numberOfLegs);
139 return (topscore + bottomscore);
140 }

142 float matchvecs(float tVecl, Int lenVecl, float ~Vec2, int lenVec2) 1 43 /~
144 ^ Computes the best path between one and two.
145 ~AIIows211 expansi~"/co.,.,v,e,~ion 1 46 t/
147 {
148 float dist, mindist, hor, vert, diag;
149 float bestscore;
0 intil,i2;
int xdir, ydir;

1 s3 elt ~array~MAxsEQLENGTHl[MAxsEQLENGTH!;
1 s4 elt 'aelt;

156 /~ initialize a-ray ~/

158 for(il = 0; il < lenVecl; il + +){
159 for(i2 = 0; i2 c lenVec2; i2 + + ) ~
160 array[i 1 ][i21 = (e~t ~) malloc(sizeof (elt));
161 if(array~ [i21 = = NULL){
162 t,.""~t(,~
Copyright~ 1991 XeroxCorporation All Rights Reserved Sec+ion C APPENDIX P3ge 86 163 'Sorry,notenoughspacetomallocarrayeltsinpl matchvecs;n3YE!"), 164 exit~1);
165 }
166 }
,668 } 20~7969 ~ 69 1~
170 compute match 172 /'~ initialize ~
173 aelt = array~O][ûl;
174 aelt->cost = sq distance(Vecl[û],Vec2~ûl);
175 aelt->xptr = û;
176 aell->yptr = û;
177 /~ bottom row /
178 i2 = û;
179 forli~ = l;il <lenVec~;il+ +){
180 dist = sq distance(Vect[ill,Vec2[i21);
181 aelt = array[il~[i2~;
182 aelt-~cost = array[il - ll[i21->cost + horwelght dist;
183 aelt->xptr = -1;
184 aelt->yptr = 0;

186 /- Ieft column /
187 il =0;
188 for (i2 = 1; i2 < lenVec2; i2 + + ) {
189 dist = sq distance(Vecl[il~,Vec2[i21);
190 aelt = array[ilili2l;
191 aelt->cost = arraylillli2-11->cost + verweight-dist;
192 aelt->xptr = 0;
193 aelt->yptr = -1;
194 }
195 /- middle /
196 for(i~ = 1; il < lenVecl; il + +) {
197 for(i2 = 1; i2 < lenVec2; i2+ +){
198 dist = sq distance(Vecllill,Vec2[i21);
199 hor = array[il-11[i21->cost + horweight~dist;
200 xdir = -1;
201 ydir = 0;
202 mindist = hor;
203 vert = array[i 11[i2 - l]->cost + verweight dist;
2û4 if (vert < mindist) 205 xdir = 0;
206 ydir = -1;
207 mindist = vert;
208 }
209 diag = array[il-ll[i2-1]->cost + diagweight-dist;
210 If (diag < mindist) {
211 xdir = -1;
212 ydir = -1;
213 mindist = diag;
214 }
215 aelt = array[ill[i2i;
216 aelt-> cost = mindist;
217 aelt-> xptr = xdir;
Copyright ~1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX ' Page 87 218 aelt-> yptr = ydir;
219 }
222~o } 2~7969 222 bestscore = best _ score(array, lenVecl, lenVec2);
223 #ifdef foo 224 if (debug) {
225 print best pathlarray, lenVecl, lenVec2~;
226 /~ print array costs(array, lenVecl, lenVec2);
227 print _ array _ ~rs~array, lenVecl, lenVec2);
228 ~1 229 printf("bestscore:Y0f\n'',bestscore~;
230 }
231 #endif 233 for~i1 = 0; i1 < lenVecl; i~ + +) ~
234 for (i2 = 0; i2 c lenVec2; i2 + + ) {
235 f~ee(array[i 1 1[i21);
236 }
237 }

239 return~bestscore);
240 }

242 float 243 sq _ distance(float x 1, float x2) 244 {
245 floatdist;
246 floatepsilon = .001;

248 1~
249 ~ quanti~ation makes many values identical, use of epsilon encourages shortest path 250 '/

252 dist = xl -x2;
253 dist ~ = dist;
254 dist + = epsilon;
255 return(dist);
256 }
257 .
258 1~
2 59 f I oat paral I el _ d istance(Outl i nePai r one, Outl i nePai r two, i nt ptr 1, i nt ptr2) 260 {
26 t fl oat topdist, bottomdist;

263 topdist = one->top[ptrll-two->top[ptr21;
264 topdist ~ = topdist;

266 bottomdist = one->bottom[ptrll-two-~bottom[ptr21;
267 bottomdist ~ = bottomdist;

269 return~topdist + bottomdist);
270 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX ~age88 3 flodt 27745 best_score (elt 'array[l[MAXSEQLENG, Hl, Int lenVecl, Int lenVec2) 2 ~ 3 276 /- assume all of Vec~ and Vec2 2re used, so just take value atencd '/

278 return(arrayllenVecl - l][lenVec2 - l]->cost);
Z79 }

281 1~
282 ~ ~----,,,~, 283 ' debugging functions 284 '/
285 ~ifdef foo 286 void 287 print _ best _ path(elt 'array[I[MAXSEQLENGTHI, int lenVecl, int lenVec2) 288 {
289 char path[MAXNAME];
29û intx,y;
29~ elt 'aelt;
292 FILE 'ofp;

294 x = lenVec 1 1;
295 y = lenVec2- 1;

297 sprintf(path, "/neVpigleVpigleVspeechlfchen/pics/paths/p~,d.txt'', FileCountY):

299 of p = fopen (path, "a");
300 if(ofp = = NULL) 301 printf("Cannot open output file %s.\n '', path);

3û3 /' fprintf(ofp," %3s%3s%6s\n'', "x'', "y", "cost");
304 '/
305 while (x > û 1¦ y > û) {
306 aelt = array[xl[y];
307 fprintf(ofp, " %3d %3d %6.2f\n'', x, y, aelt->cost);
308 x + = aelt->xptr;
309 y + = delt~>yptr;
3tû }
3 ~ I /' fprintf(ofp, " \" match % d\n\n ", matchcntr + + );
312 '/
313 fprintf(ofp, " \''match %d %d\n\n", FileCountX, FileCountY);
314 fclose(ofp);
315 }
3 16 #endif 3 ~ 7 static float sqr(float x) 318 {
319 return x~x;
320 }

322 vold print_best path(elt 'array[][MAXSEQLENGTH], int lenVecl, int lenVec2, 323 char ~outFileName) 3Z4 {
325 i nt x, y;
326 elt 'aelt;
327 FILE 'outFile;
Copyright~ 1991 XeroxCorporation All Rights Resenled Sectic n C APPENDIX Page 89 328 floatdist = 0 330 x=lenVecl-1; 2~77g~9 331 y = lenVec2~ 1;

333 if ~outFile = (FILE ')fopen(outFileName,' w'')) = = NULL) 334 DoError("singie: Cannot open output file %s.\n", outFileName~;

336 while (x > û ¦¦ y > 0) {
33~ aelt = arraylx][y];
338 fprintf(outFile, '' % 3d % 3d %6.2f\n", x, y, aelt- >cost);
339 dist t = sqrt(sqr(aelt->xptr)~sqr(aelt->yptr));
340 x ~ = aelt->xptr;
341 y ~ = aelt->yptr;
342 }
343 fclose(outFile);
344 printf("distance = %f n'',dist);
345 }

348 void 349 print _ array_costs(elt ~array[][MAXSEQLENGTHI, int lenVecl, int lenVec2) 352 int x, y;

354 for (y = 0; y < lenVec2; y ~ ~ ){
355 for (x = 0; x c l~nVec t; x I ~ ){
356 printf("%7.2f ", array[x][y]->cost);
357 }
358 printf("\n");
359 }
360 }

362 void 363 print _ array_dirs(elt ~array[][MAXSEGLENGTH], int lenVecl, int lenVec2) 364 {

366 int x, y;

368 for (y = 0; y < lenVec2; y I I ){
369 for (x = 0; x < lenVec I ~ x + ~ ){
370 printf("%2d:%2d ", array[x][y]->xptr, array[x][y]->yptr~;
371 }
3~2 printf("\n");

374 }
Copyright 1991 Xerox Corporation A~l Rights Reserved Sectlon c APPENDIX i'~ge 90 ~1 714 281991 nnatchparallel.c I /' 20~7~g 2 ' matchparallel.c 3 align 2 sequenceS
' dependent on match.c 6 ~,~

9 ~ TO DO: I ) don't compute over parts of array outside of const~aints Il '/

13 $include cstdio.h>
14 #I ncl ude < math. h >
l s 46nclude "boo~ean.h"
16 ~include"types.h"
17 $include "error h"
18 $include"pict,h"
19 #include"dict.h"
#include''diff.h"
21 #include"diff2.h"
22 #include"match.h"
23 #include"matchparallel.h"

25 #ifndef MAXLINE
26 #define MAXLINE 256 27 #endif 29 #ifndef MAXNAME
30 #defineMAXNAME 128 31 ~endif 33 #ifndef TRUE
34 #define rRUE I
35 #endif 37 $ifndef FALSE
38 #define FALSE 0 39 #endif 41 #ifndef max 42 #define max(a,b) ((a) > (b) ? (a): (b)~
43 #endif ~4 45 #Ifndef min 46 ~define min(a,b) ((a) < (b) ? (a): (b)) 47 #endi f 49 1' 51 ` parallel match with full search Copyright ~1991 Xerox Corporation All Rights Reser~ed Sectlon C APPENDIX ~age 91 53 '~ ~77~6~

SS float pl_DPDiffPair(OutlinePair one, OutlinePair two, char 'pathFile) 56 1~
57 ' question, should top and bottom distance be forced to be computed together?
58 ' use another distance score to check how far off the two are?
59 ~1 6û

62 float score;

64 score = pl matchvecs(one->top,one->bottom,one->numberOfLess, two->top, two->bottom, two->numberOfLegs, 66 pathFile);
67 return (score);
68 }

floatpl matchvecs(float'Veclt,float~Veclb,lntlenVecl, 71 float 'Vec2t, float 'Vec2b, int lenVec2, 72 char 'pathFile) 73 /' 74 ' Computes the best path between one and two ' Allows 211 expd",iu"/~,r\ "~., e,~io.

77 {
78 float dist, mindist, hor, vert, diag;
7g float bestscore;
i nt i 1, i2;
81 int xdir, ydir;

83 elt 'array[MAXSEQLENGTH][MAXSEQLENGTHI;
84 elt 'aelt 86 /" initialize array '/

88 for(il = û; il < lenVec1; il + +){
89 for (i2 = 0; i2 < lenVec2; i2 + + ) {
9û array[il~[i21 = (elt~)m "c ' f(elt));
91 if(array[il¦[i2] = = NULL){
92 r,J"",r(.~d~.,, 93 "Sorry, not enough space to mal loc array elts i n pl m~ BYE! ');
94 exit( 1 );
}
96 }
97 }

100 ~ compute match 101 ~/
102 /' initiali~e '/
103 aelt = arrayt01[0~;
104 aelt->cost = sq distance(Veclt[01,Ve~2t[ûl) + sq distance(Veclb[01,Vec2b[01);
105 aelt->xptr = 0;
106 aelt->yptr = 0;
107 /- bottom row ~1 Copyright D 1991 Xerox Corporation Al~ Rights Reserved ~ . . .

Section C APPENDIX ! Page 92 ~09 for(il = l;ll<lenVec~;il+ +){ 2077~69 110 dist = sq distance(Vec~t~itl, Vec2t[i2]) + 5q_ distance(Veclb[il], Vec2bli21);
111 aelt = array[il¦li2];
112 aelt->cost = array[il - l¦[i2¦->cost + honweight'dist;
113 aelt-~%ptr = -1;
114 aelt->yptr = 0;
115 }
116 1" leftcolumn ~/
117 il - 0;
118 for(i2 = 1; i2 < lenVec2; i2 + + ) {
119 dist = sq distance(Vecltlil],Vec2t[i2]) + sq_distance(Veclb[il],Vec2b[~21);120 aelt = arraylill[i21;
121 aelt->cost = array~ill[i2- ll->cost + verwelght~dist;
122 aelt->xptr = 0;
123 aelt->yptr = -1;
124 }
125 1~ middle ~1 126 for(il = 1; il <lenVecl; 11 + +){
127 for(i2 = 1; i2 < lenVec2; i2 + + ) {
128 dist = sq distance(Veclt~il],Vec2t[i2]) + sq dlstance(veclb~ vec2b[i2]);
129 hor = arraylil -1][i2]-?Cost + horweight~dist;
130 xdir = -1;
13~ ydir = 0;
132 mindist = hor;
133 vert = arraylil][i2- l]~>cost + verweight ' dist;
134 if (vert < mindist) 135 xdir = 0;
136 ydir = -1;
137 mindist = vert;
138 }
139 diag = array[i 1- 1 1[i2 - l]->cost + diagweiqht ~ dist;
140 if (diag < mindist) {
141 xdir = -1;
142 ydir = -1;
143 mindist = diag;
144 }
145 aelt = array[il][i2];
146 aelt - > cost = mindist;
147 aelt-> xptr = xdir;
148 aelt-> yptr = ydir;
149 }
150 }

152 bestscore = best score(array, lenVecl, lenVec2);
153 if (pathFile) 154 print best path(array,lenVecl,lenVec2,pathFile);

1 57 for (i 1 = 0; i 1 < lenVec 1 ; i 1 + + ) {
158 for (i2 = 0; i2 < lenVec2; i2 + + ) {
159 free(arrayli 1 ][i2]);
160 }
161 }

Copyri ght ~ 1991 Xerox Corporati on All Rights Reserved Sectlon C APPENDIX ~ Page 93 163 return(bestscore~;
164 }

168 ''''~ "^^^^'^^^^^^ 21~77f~
169 ' faster parallel match J U a 1 Jû not optimal because warp is limited to swath of width "bw"
1 72 'I

174 float faster pl DPDiffPair~OutlinePair one, OutlinePair two, char ^pathFile~
1 75 1~ --176 ' question, should top and bottom distance be forced to be computed together?
177 ' use another distance score to check how far off the two are?
1 78 '/

180 {
181 floatscore;

183 score = faster pl matchvecs(one-~top,one->bottom,one-~numberOfLegs, 184 two->top, two->bottom, two->numberOfLegs, 1 85 pathFile);
186 return (score):
187 }

189 floatfaster pl matchvecs(float ~Veclt, float Veclb, intlenVecl 190 float ~Vec2t, flcat iVec2b, int lenVec2, 191 char 'pathFile) 1 92 /~
193 ' Computes the best path between one and two.
194 ^Allows2/1 expansio.~/.. ,.",.,~:"iononlywlthinaband 196 {
197 floatdist, nnindist, hor, vert,diag;
198 floatbestscore;
199 floatratio:
200 int i 1, i2;
201 i nt xdir, ydir;
202 int beg, end, center;
203 int b; /~ pointer to border '/
204 intborder; /~widthofborderonrightsideofswath'/

206 elt ~a. " 'r 'AXSEQ~ENGTHl[MAXSEQLENGTHI;
207 elt ~aelt;

209 floatinfinity = 1.0e30;
210 intbw = 20;

212 ratio = (float)lenVecl/(float)lenVec2;
213 border = (int)(ratio + .999999);
214 /~ if(debug) 215 pri ntf( " rati o: % f\n ", ratio);
216 'I /~ initialize array ~/

~opyright~ 1991 XeroxCorporation All Rights Reserved Secfion c APPENDIX, Page 94 ~18 for~il = O:il <lenVe~ l f +){ 2~ ~9~9 ~9 fo~(i2 = 0; i2 < lenVec2; i2 f + ) {
220 array[i 1 1[i21 = (e~t ~) malloc(sizeof (elt));
221 if(array[ill[i2] = = NULL){
222 t,L ; " ~ t(~l,J~, ., 223 "Sorry,notenoughspacetomallocarrayeltsinpl matchYecs\nayE!~
224 exit( I );
225 }
226 }
227 }

229 /~
230 ~ compute match 232 /~ initialize tl 233 aelt = array[O][OI;
234 aelt->cost = sq distance(Veclt[OI,Ve~2t[0l) + sq_distance(Veclb[O¦,Vec2b[0¦);
235 aelt->xptr = 0;
236 aelt->yptr = 0;
237 /~ bottom row /
238 i2 = 0;
239 end = bw + border + 1;
240 for (i 1 = 1 ; i 1 < end ; i 1 + + ) {
241 dist = sq distance(Veclt~il],Vec2t[i2]) + sq_distance(Veclb[ill,Vec2b[i21);242 aelt = array[ill[i21;
243 aelt->cost = arraylil-11[i2]->cost + horweight~dist;
244 aelt->xptr = -1;
245 aelt- > yptr = 0;
246 }
247 1~
248 swath 250 ~settheeltbeforebeqandatendtoinfinity,thenthecomputedistancesnormally 251 ~ for the row 2 52 ~1 253 for(i2 = 1; i2 < lenVec2; i2+ +){
254 center = i2 ~ ratio;
255 beg = max(l,center-bw);
256 end = min(lenVecl,center + bw + l);
257 1~ if (debug) 258 printf("center: %d, beg: %d, end: %d\n", center, beg, end);
259 ~ beg ~/
260 aelt = array[beg- 111i21;
261 aelt->xptr = 0;
262 aelt->yptr = -1;
263 if(beg = = 1){
264 dist = sq distance(Veclt[OI,Vec2tri2]) + sq distance~VeclblO],Vec2b[i2]);
265 aelt->cost = array[O][i2 - l]->cost + verweight ~ dist;
266 }
267 else {
268 aelt->cost = infinity;
269 }
270 /~ end ~/
271 /~ if (end < lenVecl) {
272 ~/
Copyright ~1991 Xerox Corporation All Rights Reserved Section C APPENDIX Page 95 273 for(b = end;b<mln(end~border,lenVecl);b+ +I{
274 /* If (debug) 275 printf("b: %d ", b~; r~ r~ n 276 */ aelt = arraylbl[i21; ~ V ( ( ;1 U ~1 277 aelt->cost = infinity;
278 aelt->xptr = -1;
279 aelt->yptr = 0;
280 }
281 ror(il = beg; il <end; il + +){
282 dist = sq distance~Veclt[ill,Vec2t!i21) + sq distance(Veclb[ill,Vec2b[i211;283 hor = array[i1-11[i21-~cost ~ horweight*dlst;
284 xdir = -1;
285 ydir = 0;
286 mindist = hor;
287 vent = array[i~l[i2- 11->cost + verweight*dist;
288 if (vert C mindist) {
289 xdir = 0;
290 ydir = -1;
291 mindist = vert;
292 }
293 diag = array[il -1][i2- Il->cost + diagweight*dist;
294 if (diag < mindist) {
295 xdir = -1;
296 ydir = -1;
297 mindist = diag;
298 }
299 aelt = array[il]li21;
3û0 aelt-~ cost = mindist;
301 aelt-> xptr = xdir;
302 aelt-> yptr = ydir;
303 }
304 }

306 bestscore = best score(array, lenVec 1, lenVec2~;
307 if (pathFile) 308 print_best_path(array, lenVecl, lenVec2,pathFile);

3t0 for(il = 0; il < lenVecl; i1 + +){
311 for (i2 = 0; i2 < lenVec2; i2 + + ) {
312 free(array[ill[i21);
313 }
314 }

316 retu"(b~
317 }

320 1~
321 * *****r*~****~***~***
322 * fastest parallel match 323 ~ warp limited to swath bw, plus no backtracking 324 * ^ ^ ^ ^ ^ ^ ^ ^
325 ~'1 327 floatsimple_pl_DPDiffPair(OutlinePairone,OutlinePairtwo) Copyright l 991 Xerox Corporation All Rights Reserved Sec+lon C APPENDIX Page 96 ~!8 1-~2g ~ cluestion, should top and bottom dlstance be forced to be computed together?
330 ~ use another distance s~ore to check hc,w far off the two are?

334 float score;

336 score = simple pl matchvecs(one->top,one-~bottom,one->numberOfLegs, 337 two->top, two->bottom, two->numberOfLegs);
338 return (score);
339 }

341 void PrintArrayRow(float ~array,int width) 342 {
343 int i;
344 for(i=0;i<width;+ +i) 345 printf~"%2.2f",~array+ +);
346 prlntf("~n");
347 }

349 void PrintArray(float ~artay,int helght,int width,int signalWidth) 350 {
351 int i;
352 for (i = 0; i ~ height; + + i) {
353 printf("/"d:",i);
354 PrintArrayRow(array + i~width,signalWidth);
355 }
356 }

358 floatsimple pl _ matchvecs(float~Veclt,float~Veclb,intlenVecl,float~Vec2t,float ~Vec2b, int lenVec2) 359 /'' 360 Computes the best path between one and two within a band.
361 ~ Allows 21~ expansio"/~c.-"~ ,ion only within a band.
362 ~1 363 {
364 float dist, mindist, hor, vert, diag;
365 float bestscore;
366 float ratio;
367 i nt i 1, i2;
368 int xdir, ydir;
369 int beg, end, center;
370 int b; /~ pointer to border ~/
371 int border; /~ width of border on rlght side of swath ~/

373 float array[MAXSEQLENGTHl~MAXSEQLENGTH¦;

375 floatinfinity = 1.0e30;
376 intbw = 20;

378 ratio - (float)lenVecl/(float)lenVec2;
379 border = (int) (ratio + .999999);
380 /~ if(debug) 381 printf("ratio: %f\n", ratio);
Copyright ~199~ Xerox Corporation All Rights Reserved Se~tion C APPENDIX, Page97 382 ~/ 1- initl al i ze array ~/
33884 2~7~369 385 /"
386 " compute match 387 ~1 388 1~ initialize 1 390 array[0l[01 = sq_distance(veclt[oi~vec2t[ol) + sq_distance(Veclb[oi,vec2b[0l)~
391 1~ bottom row 1 392 i2 = 0;
393 end = bw ~ border ~ 1;
394 for(il = l;il <end; il ~ +)~
395dist = sq distance(Veclt[ill,Vec2tli21) + sq distance(Veclb[il~,Vec2b[i21);396 array[i l ][~l = array[i l - l l[i21 + hor~veight - ~st;
397 }

399 swath 401 ~settheeltbeforebegandatendtoinfinity,thenthecomputedistancesnormally 402 ~ for the row 404 for (i2 = 1; i2 < lenVec2; i2 + + ) {
405 center = i2 ~ ratio;
406 beg = max~l, center - bw);
407 end = min(lenVecl,center + bw + l);
408 /' if (debug) 409 printf("center: %d, beg: %d, end ''Od\n", center, beg, end);
410 / 1- beg ~/
411 if(beg = = 1){
412 dist = sq distance(Veclt[O],Vec2t[i21) + sq distance(Veclb[Ol,Vec2b[i2~);
413 array[beg - li[i21 = array[OI[i2 - 11 + verwelght dist;
414 }
415 eise{
416 array[beg- li[i2] = ~nfinity;
417 }
418 /~ end /
4~9 for(b = end;b<min(end+border,lenVecl);b+ +){
420 /l- jf (debug) 421 printf("b: %d ", b);

423 array[bl[i21 = infinity;
424 }
425 for(il = beg; il < end; il + +) {
426dist = sq distance(Vecltlill,Vec2t[i21) + sq distance(Veclb[il~,Vec2b[i2]);427hor = array[i 1 - l~[i21 + horweight dist;
428mindist = hor;
429vert = array[i1~[i2~ verweightdist;
430if (vert ~ mindist) {
431mindist = vert;
432 }
433 diag = array[i1 - 1~[i2-1~ ~ diagweightdist;
434 if (diag < mindist) {
435 mindist = diag;
436 }
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon C - APPENDIX Page 98 7 array~ [12~ = mlndls~; 2 ~ 7 7 9 ~ 9 ~38 }
439 }

441 bestscore = array[lenVecl - I][lenVec2- ll;
442 if (debug~ ~
443 prlntf~'' best score: 9~ f\n", bestscore);
444 }

446 return(bestscore~;
447 }

Copyright ~D 1991 Xerox Corporation All Rights Reserved Sectl on C APPEN DIX I P3g e 99 ~ul 24 17.16 ~991 newL2.c #include <stdio.h>
2 #includ~ <math.h> ~) n rt ~ ~ r n 3 #include"boolean.h"
4 #include"types.h"
S #include"er~or.h"
6 #include''dict.h"

8 #define NORMAL LENGTH (lû0.0) 9 #define MAX S~PE (2.0~
#defineBlG NUM(10.0e20) 12 void ResampleOutlinePair(OutlinePair a,float newToOldFactor) 13 /~ Resample an outline pair using linear Interpolation.

int newWidth,oldWidth,i;
16 intoldLeft,oldRight;
17 float oldCenter;
18 float ~newX,~newrop,~newBottom;
19 float~xCursor,~topCursor,'bottomCursor;
21 oldWidth = a->numberOfLegs;
22 newWidth = irint(newroOldFactor~oldWidth);

24 newX = (float ~)cal loc(newWidth,si ~eof(float));
newrop = (float ~)calloc(newWidth,s zeof(float));
26 newBottom = (float~ (n~ 'iJ~l"si~eof(float));
27 if ((newX = = NULL)¦¦(newrop = = NULL~¦¦(newBottom = = NULL)) 28 DoError("ResampleOutlinePair: cannot allocate space.\n",NULL~;

xCursor = newX;
31 topCursor = newrop;
32 bottomCursor = newBottom;

34 for(i =0;i<newWidth; + +i) ~
oldCenter = il(flc.. l)"~ ';d~ll'(flc~elL)ulJ~'iJ~ll, 36 oldLeft = irint(floor(oldCenter));
3~ oldRight = irint(ceil(oldCenter));
38 if (oldLeft = = oldRight) {
39 ~xCursor + + = ~(a->x + oldLeft);
~topCursor+ + = ~(a->top+oldLeft~;
41 ~bottomCursor+ + = ~(a->bottom+oldLeft);
42 }
43 else {
44 float slope;
slope = ~(a->x+oldRight)-~(a->x+oldLeft);
46 ~xCursor+ + = ~(a->x+oldLeft) + ~oldCenter-oldLeft)~slope;
47 slope = ~(a->top+oldRight)-~(a->top+oldLeft);
48 ~topCursor+ + = ~(a->top+oldLeft~ ~ (oldCenter-oldLeft)~slope;
49 slope = ~(a->bottom +oldRight)-^(a->bottom + oldLeft);
~bottomCursor+ + = ~(a->bottom+oldLeft) + (oldCenter-oldLeft)~slope;
51 }
52 }
Copyright 1991 XeroxCorporation All Rights Reserved SertionC APPENDIX Page 100 ~4 free(a~>x);
SS free~a- >top);
56 free(a-~bottom) 2 (~ 7 7 9 6 ~

58 a->x = newX;
S9 a->top = newTop;
a->bottom = newBottom;
61 a->numberOfLegs = newWidth;
62 }

64 float L2Norm(OutlinePair signal, int startOffset, OutlinePair model,float topTo80ttom) 66 {
67 float ~topl,'top2,~bottom~,~bottom2;
68 int i,overlap;
69 float sum;
float temp;
72 if ((startOffset < ) 11 73 (startOffset + model->numberOfLegs > signal->numberOfLegs)) 74 DoError("L2Norm: themodel mustoverlaptheslgnal.\n",NULL);
76 topl = signal->top+startOfket;
77 top2 = model->top;
78 bottom~ = signal->bottom+startOffset;
79 bottom2 = modei->bottom;
81 overlap = signal->numberOfLegs-startOffset;
82 if (overlap > model->numberOfLegs) 83 overlap = model->numberOfLegs;

for(i=0,sum=0;i<overlap;+ li){
86 temp = ~topl + + - ~top2 + +;
87 sum I = temp ~ temp ~ topToBottom;
88 temp = 'bottoml + + - ~bottom2 + +;
89 sum + - temp ~ temp;
}

92 return sum;
93 }

floatL2compare(outlinepairol~outlinepairo2~floattoproBottom) 96 {
97 floatslope = (float)ol->widthl(float)o2->width;
98 if ~(slope>MAX_SLOPE)Il(l/slope>MAX SLOPE)) 99 return 31G NUM;
100 if (ol->nurnberOfLegs I = NORMAL LENGTH) 10~ ResampleOutlinePair(ol,NORMAL LENGrHlol->numberofLegs);
102 if (o2->numberOfLegs ! = NORMAr LENGrH) 103 ResampleOut inePair(o2,NORMAL=ENGrHlo2->numberOfLegs);
104 return L2Norm(ol,0,o2,toproBottom);
105 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX . Page 101 Aug 14 20:541991 newMatch c #include <stdio.h>
2 #in~lude"mylib.h"
3 #include"misc.h" ,,~
4 #include ''types.h" ~ i~J ( ( ~ U 9 S #include"dict.h"
6 #include"newMatch.h"

8 #define MAX SIGNAL LENGTH (800) 9 #define MAX SLOPE (2 0) #define 31G_NUM (lOe20) Il 12 typedefenum{NONE,LEFT,DOWN,DOWNLEFT,DlL1,D2L1,DlL2}Direction;

14 extern double sqrt(double);
extern double cos(double);
16 extern double atan(double);
17 ex~ernintirint(double);

19 /' Assumes that a represents the model and b represents the unknown.
t Weights places where the model is lower than the unknown more than 21 ' cases where the model is higher than the unknown. The idea he~e is 22 ' that val leys can be fi I led in by bleeding together, but that noise 23 ' can rarely make a contour be too tall for extended periods.
24 'I
floathillToValley = 1.0;
26 inlinefloatSquareDifference(floata,floatb) 27 {
28 floattemp = a-b:
29 if (temp<0) return temp'temp;
3 1 else 32 return temp'temp'hillToValley'hillToVa~ley;
33 /' ~eturn (a-b)'(a-b); '/
34 }
36 inilne float FMax(float a,float b) 37 {
38 i'(a>b) 39 return a;
else 41 return b;
42 }

44 inllne float FMin(float a,float b) 46 if (a<b) 47 return a;
48 else 49 return b;
}

52 inllne int IMax(int a,int b) Copyright D 1991 Xerox Corporation All Rights Reserved Section C APPENDIX Page 102 4 if(a>b) 77~9 55 return a; 2 ~1 56 else 57 return b;
58 }

6û inline int IMin(int a,int b) 61 {
62 if (a<b) 63 return a;
64 else 65 return b;
66 }

68 float NewMatch(float ~al ,float Aa2,int aLength,float ~bl,float b2,int bLength, 69 float~,l,L~,W~.~llt,800~EANlengthNormali~e,intnormalBandWidth, 7û floattopToBottom~
71 {
72 floatcostsO[MAX _ SIGNAL _ LENGTH + 11;
73 floatcostsllMAx SIGNAL LENGTH+I¦;
74 int i,j,start,end,bandWidth,shift;
int realStart,realEnd,center,oldEnd;
76 float slope,angle;
7~ float ~a1c,~a2c,~cd,~cl,~cdl,-dc;
78 floatoldCost,blv,b2v,returnVal;

if(aLength>MAX SIGNAL LENGTHI~bLength>MAX SIGNAL LENGfH) 81 DoError("NewMatch: maximum signal length exceeded.~n'',NULL);

83 slope = (float)aLength/(float)bLensth;

if ((slope>MAX SLOPE)¦¦(1/slope>MAX_SLOPE)) {
86 return 81G _ NUM;
87 }
88 angle = atan(slope);
89 bandWidth = ilil,~(nu. '~ vYid~l,/,~,s(angle));
90 center = 0;
91 realStart = center-bandWidth/2;
92 realEnd = realStart+bandWidth;
93 end = FMin(realEnd,aLength);

9S alc = al; /~alcursor~/
96 a2c = a2; /~a2cursor~/
97 blv = ~bl; /~ bl value ~/
98 b2v = ~b2; /~ b2 value ~/
99 dc = costsO;
100 ~dc + + s 31G NUM;
101 oldCost = tdc+ + =
SquareDifference(~alc + + ,blv)~topToBottom + SquareDifference(~a2c + + ,b2v);

103 for (j = l ;j <end; + + j) 104 oldCost = ~dc+ + =
oldCost+SquareDifference(~alc+ +,blv)~topTo80ttom+5quareDifference(~a2c+ +,b2v);105 Copyright~ 1991 XeroxCorporation All Rights Reserved -Sectlon C APPENDIX Page 103 106 for(i=l;i<bLength ~ +I){
107 1~ Compute new center of band /
108 center = irint(slope~i);
109 realStart = cente~-bandWidth/2, 110 realEnd = realStart + bandWidth;
t 1 2 oldEnd = end; 2 0 7 7 9 ~ 9 113 end = FMin~realEnd,aLength);
t 14 shift = end-oldEnd;
1~5 116 1~ put large numbers where bands don t overlap ~1 117 for(j =0;j<shift; ~ + j) 118 'dc+ ~ = 81G NUM;

1 2û a 1 c = a 1 ~ start; 1~ a 1 cursor 1 121 a2c = a2 + surt; /~ a2 cursor ~/
122 blv = ~bl + i); 1^ bl value ~1 123 b2v = ~b2 + i); 1~ b2 value ~1 124 if ~i&~) {
125 cd = costsl ~ start-l + 1; 1~ cursor down ??? What about -I ??? 1 126 cdl = costsO + start- I + I; /~ cursor down left 1 127 cl = cosUO + slart ~ l; I^ cursor left ~/
128 dc = costsl + start + 1; 1~ destlnation cursor 1 129 }
130 else {
13 t cd = costsO + sta rt- 1 + 1; 1~ cu rsor down ~1 132 cdl = costsl +start-l + I;l~cursordownleft'/
133 cl = costsl + start ~ cursor left ^1 134 dc = costsO + start + I; I' destination cursor 1 135 }
136 ~cd = BIG NUM;
137 for~j=start;j<end; + +j){
138 floatdown,left,downLeft,rest;
139 down = 'cd+ + + rest;
140 left = ~cl + + ~ rest;
141 downLeft = ~dl + + ~ rest~.e, L~ 'e ~l,L, 142 rest = SquareDifference~alc + +,blv)-toproaottom +
143 5quareDifference(^a2c+ +,b2v);
144 dc+ ~ = FMin(FMin(down,left),downLeft);
145 }
146 }

148 i--;
149 if (i&l) lSO dc = costs1 ~aLength-l + l;
lSl else 152 dc = costsO + aLensth-l + 1;
153 returnVal = dc;

jf(l~ J~,-",alize) 156 return returnVallsqrt(aLength~aLength ~ bLength~bLength);
1 57 else 158 returnreturnVai;
159 }

Copyright D 1991 Xerox Corporation ~11 Rights Reserved Sectlon C APPENDIX Page 104 2~!1 7 7~ i ~51 --62 floatSepMatch(float 'a~ ,IntaLength,float bl,lnt bLength, 163 floatcenterweight~BooLEANlengthNormali~e~intnormal8andwidth) t64 {
165 floatcostsO[MAX _ SIGNAL LENGTH + 11;
166 floatcostst[MAX SIGNAL_~ENGTH + 11;
167 inti,j,start,end,bandWidth,shift;
16~3 intrealStart,realEnd,center,oidEnd;
169 float slope,angle;
170 float ~a~c,'cd,'cl,'cdl,~dc;
171 floatoldCost,blv,returnval;

173 if(aLength>MAX SIGNAL LENGTHIlbLength~MAX SIGNAL LENGTH) ~74 DoError~'NewMatch: maxlrnumsignal lengthexceeded.\n ,NULL);

176 slope = (float)aLength/(float)bLength;

178 If((slope>MAX_'7LOPi-)ll(l/slope>MAX SLOPE)~{
179 return BIG _ NUM;
180 }
181 angle = dtan(slope);
182 bandWidth = irlnt(normalBandWidth/cos(angle~);
183 center = O;
184 realStart = center-bandWidth~2;
185 realEnd = realStart+bandWidth;
186 end = FMin(realEnd,aLength~;

188 alc = a~; /' al cursor '/
189 blv = 'bl; /~ bl value /
lgo dc = costsO;
191 'dc+ + = BIG NUM;
192 oldCost = 'dc+ + = SquareDifference('alct I ,blv);

194 for(j=l;jcend;~ +j) l9S oldCost = ~dc+ + = oldCost+SquareDifference(talc~ +,blv);

197 for(i = l;iCbLength; + +i) {
198 /' Compute new center of band '/
199 center = irint(slope~i);
200 realStart = center-bandWidth/2;
20t realEnd = realStart+bandWidth;
202 start = FMax(realStart,0);
203 oldEnd = end;
204 end = FMin(realEnd,aLength);
205 shift = end-oldEnd;

207 1' put large nurrlbers where bands don t overlap t 208 for(j=O;jcshift; ~
209 tdc+ + = BIG NUM;

211 alc = al ~ start; 1' al cursor '/
212 blv = t(bl +i);/~bl value'/
213 if (i&l) ~
214 cd = costsl ~ start-l + 1; /~ cursor down ~ What about -1??? ~/
215 cdl = costs0 + start- l ~ cursor down l eft ~1 Copyright~ 1991 Xero~Corporatlon All Rlghts Reserved -Section C APPENDIX Page 105 216 cl = costsO + start + ~ curso~ left 217 dc = COSISI + sta-t + 7; 1- destlnation cursor 218 }
219 else {
220 cd = costsO + start- ~ + I; 1~ cursor down / ~) n ~ 9 22t cdl = costs1 + s~art-1 + 1; /~ cursor down Ieft /
222 cl = cos41 +start+ t; /~cursorleft-/
223 dc = costsO + start + t; /- destination cursor /
224 }
225 ~cd = BIG NUM;
226 for(' =start;j<end; + + j) {
227 floatdown,left,downLeft~rest;
228 down = cd + + + rest;
229 left = i~cl + + + rest;
230 downLeft = ~cdl + + + rest-centerWeight;
231 rest = SquareDifference(-alc+ +,blv);
232 dc+ + = FMin(FMin(down,left),downLeft);
Z33 }
234 }

236 i--;
237 if (i&1) 238 dc = costs1 +aLength-1~ 1;
239 eise 240 dc = costsO+aLength-1 ~ t;
241 returnVal = ^dc;

243 if ~ "~li.~) 244 return returnVallsqrt(aLength~aLength + bLength~bLength);
245 else 246 return returnVal;
247 }

249 #define WIDTH (800) 250 #define H ~vtARGlN (20) 251 #defineV MARGIN(40) 252 #define H SPACING (20) 253 #define V _ SPACING (100)1i' Must be greater than 2i'X_HEIGHT /
254 #defineX_HEIGHT(17) 255 void DrawVLine(Picture pict,int x,int yt,lnt yb) 256 {
257 int i;
258 for (i = yt; i < yb; + + i) 259 WntePixel~pict,x,i, 1 );
260 }
26t 262 void DrawOutline(Picture pict,int numberOfLegs,float tops,float bottoms,int x,int y) 263 {
264 int i,top,bottom;
265 for (i = 0; i c numberOfLegs; + + i) {
266 top = i ri nt(- (tops + i ) ~ X H E IG H T);
267 bottom = irint(-(bottoms+i)i'X HEIGHT+X HEIGHT);
268 DrawVLine(pict,i + x,top + y,bottom + y);
269 }
270 }
Copyright ~199t Xerox Corporation All Rights Reserved Sectlon C APPENDIX Page 106 272 void PrintPath(float al,float ~a2,1ntaLength,float ~bl,float ~b2,1nt bLength, 9 273 Direction path[MAX SIGNAL LENGTHI[MAX SIGNAL_LENGrHl,int i, 274 float returnVal, 275 FILE ~pathFP) 276 {
277 Int x,y,j;
278 Intlength = 0;
279 Intindex = 0;
280 float newTop1 [MAX SIGNAL LENGTHl,new60ttom 1 [IVIAX SIGNAL LENGTHI;
281 float newrop2[MAX SIGNAL LENGTH],newBottom2[MAX_SIGNAL_LENGTHI;

283 y = i;
284 x = aLength-l;
285 while (path[yl[xl! = NONE) {
286 switch(path[yl[xl){
287 case DOWN:
28~3 x--;
289 break;
290 case LEFT:
291 y--;
292 break;
293 case D7Ll:
294 case DOWNLEFT:
295 x--;
296 y--;
297 break;
298 case D2Ll:
299 x-=2;
300 y--;
301 break;
302 case D l L2:
303 x--;
304 y-=2;
305 break;
306 default:
307 DoError("NewMatchAndPath: Internal error- bad case.\n",NULL);
308 }
309 ~ ~length;
3~0 }
3 l I
312 y = i;
313 x = aLength-1;
314 while(path[yl[x~! = NONE) ~
315 if(index>=MAX SIGNAL LENGTH) 316 DoError(" NewMatchAddPath: warped signal is too long.\n'' ,NU LL);
317 newTopl[lensth-indexl = al[xl;
3 ~8 newBottom I [length-indexl = a2[xl;
3~9 newTop2[1ength-indexl = bllyl;
320 newBottom2[1ength-indexl = b2[yl;
321 switch (path[yl[xl) {
322 case DOWN:
323 x--;
324 break;
325 case LEFT:
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX Page 107 326 y~
327 b~eak;
328 case DOWNLEFT: 2 ~ 7 ~ 9 6 9 331 y--;
332 break;
333 case D2~1:
334 x- = 2;
335 y--;
336 break;
337 case D 1 L2:
338 x--;
339 y- = 2;
340 break;
341 default:
342 DoError(" NewMatchAndPath: Internal e~ror - bad case.\n",NULL~;
343 }
344 + ~index;
345 }
346 if(index> =MAX SIGNAL LENGTH) 347 DoError(" NewMatchAddPath: warped slgnal is too long.\n",NULL);
34~3 newTopl ~length-indexl = a 1 [x];
349 newBottoml[length-indexl = a2[xl;
350 newTop2[1ength-indexl = b~[yl;
351 newBouom2[1ength-indexl = b2(yl;
352 + +index;

354 for~j = O;j<index; + ~ j) 355 fprintf(pathFP,''C/cd%f\n'',j,newrop~(jl);
356 fprintf(pathFP,"\''topl\n\n");

358 for(j=O;jcindex; + +j) 359 fprintf(pathFP,"%d %f n",j,newTop2[jl);
360 fprintf(pathFP,"\"top2\n\n");

362 for (j = O;j <index; + + j) 363 fprintf(pathFP,"%d %f~n'',j,-newBottoml[jl);
364 fprintf(pathFP,"\"bottoml\n\n");

366 for(j =O;j<index; + +j) 367 ~.,.",~r~ rP,"/cd %f\n",j,-newBottom2(jl);
368 fprintf(pathFP,"\"bottom2\n\n'');

370 {
371 Picture pict;
372 plCt =
new pict(lMax(ind~Y ~ r~gth,bLength))~2 t H SPACING +H MARGIN-2,V MARG
IM~2 +2~V SPACING,l);
373 DrawOutrne(pict,aLength,al,a2,H MARGIN,V MARGIN);
374 DrawOutline(pict,bLength,bl ,b2,H MARGIN + aLength + H SPACING,V MARGIN);

376 DrawOutline(pict,index,newTopl,new30ttoml,H MARGIN,V MARGIN ~V SPACING), CopyrightD 1991 XeroxCorporation All Rlghts Resen/ed Sec+~ion C APPENDIX . Page 108 ~7 2Q779~9 DrawOutline(pict,index,newrop2,newBottom2,H MARGIN + index + H SPA~ING,V MAR
GIN +V _ SPACING~;

i~rawOutline~pict,index,newTop2,newBottom2,H MARGIN,V MARGIN + V SPACING~2);
379 write_pict~"out.pict'',pict) 380 }

382 {
383 float checksum;
384 fprintf~pathFP,"%d /0f\n",0,checksum);
385 for~j=0,checksum=0;j~index; + +j){
386 checksu m I = squareDi fference~newTop ~ newrop2 [i ]) +
387 SquareDifference~newBottoml[jl,newBottom2[j]);
388 fprintf~pathFP,''/Od %f\n",j,checksum);

390 printf~"checksum,score = ,~6.2f,'062f`~n",checksum,returnVal);
391 }
392 }

396 float NewMatchAndPath~float ~a 1 ,float ~a2,int aLength,float ^bl ,float ~b2,int bLength, 397 floatc~-,L~!,Wei~l,L,BOOLEANl~"~Ll,~:c,-,-.al--~,intnormalBandWidth, 398 float topToBottom,FlLE 'pathFP) 399 {
400 i~irection path[MAX SIGNAL LENGTHIlMAX SIGNAL LENGrH],~pc;
401 int x,y;
402 floatcostsO[MAX SIGNAL LENGTH+ll;
403 floatcosts~[MAX SIGNAL LENGTH+ll;
404 inti,j,start,end,bandWidth,shift;
405 int realStart,realEnd,center,oldEnd;
406 float siope,angle;
407 float~alc,~a2c,~cd,~cl,~cdl,^dc;
408 floatoldCost,blv,b2v,returnVal;

410 if ~aLength>MAX SIGNAL LENGTHIlbLength>MAX SIGNAL LENGTH) 4~1 DoError~"NewMatch: maximum signal iength exceede~\n",NULL);
4~Z
4~3 slope = ~float~aLengthl(float)bLength;
4~4 415 if ~slope~MAX SLOPE)~ lslope>MAX_SLOPE)){
4~6 return BIG NUM
417 }
418 angle = atan(slope);
419 bandWidth = i-i,.L~nc."~ ànd'~RlLI,/.cs(angle));
420 center = 0;
4z1 realStart = center-bandWidth/2;
422 realEnd = realStart+bandWidth;
423 end = FMin(realEnd,aLength);

425 alc = al; l~al cursor~l 426 a2c = a2; 1~ a2 cursor 1 427 blv = ~bl; 1~ bl value ~1 428 b2v = ~b2; /~ b2 value ~1 Copyright ~199~ Xerox Corporation All Rights Reserved Sectlo n C APPEN Dl X ' Page l 09 429 dc = costsO;
430 pc = &(pathlOI[Ol); 2 0 7 7 9 6 9 431 dc + + = BIG NUM;
432 oldCost = 'dc + + =
SquareDifference(tatc + + ,b~v)~topToBottom + SquareDifference(~a2c + + ,b2v~;
433 'pc+ + = NONE;

435 for(j = l;j<end; + +j)~
436 oldCost = 'dc + + =
oldCost + SquareDifference(talc + + ,blv)-topro80ttom + SquareDifference(ta2c + + ,b2v);
437 tpC + + = DOWN;
438 }

440 #ifdef foo 441 printf("%6d",0);
442 for(j=O;j<end;+ +j) 443 prlntf("%6.2f ",costsO[j + ll);
444 #endif 446 for(i=l;i<bLensth;+ +i){
447 /- Compute new center of band t 448 center = irint(slope~
449 realStart = center-bandWidth/2;
450 realEnd = realStart+bd~.3'1V;d~
45t start = rr ~ t~t,o~;
452 oldEnd = end;
453 end = FMin(realEnd,aLength);
454 shift = end-oidEnd;

456 /~ put large numbers where bands don't overlap t~
457 for (j = O;j <shift; + + j) {
458 /~ printf("%6.2f ",BIG NUM); ~/
459 'dc+ + = 31G _ NUM, 460 }
46t It printf("\n%6d ",i); ~/

463 a I c = a ~ + start; /'' a t cu rsor ~/
464 a2c = a2 + start; /~ a2 cursor ~/
465 blv = (bl + i); /~ bl value ~/
466 b2v = t(b2 + i); /~ b2 value ~/
467 pc = &(pathli][startl);
468 if (i&l) {
469 cd = costsl +start-l + 1; /~cursordown ??~Whatabout-t???~l 470 cdl = costsO + start-l + l; /~ cursor down left /
47l cl = costsû+start+l; /~cursorleft-/
472 dc = costsl + start + l; /~ destinatlon cursor /
473 }
474 else {
475 cd = costsO+start-l + l; /~cursordown /
476 cdl = costsl + start-l + l; /~ cursor down ~eft '/
477 cl = costs l + start + 1; /~ cursor left /
478 dc = costsO + start + l; /~ desti natlon cursor /
479 }
480 tcd = BIG _ NUM;
48l for (j = start;j < end; + + j) {
Copyright l99l Xero~Corporation All Rights Reserved Sectlon C APPENDIX P~ge 110 2float down,le;t.aownLeft,rest; 2 ~ 7 7 9 ~i 9 3rest = SquareDlfference(~alc+ +,b~v)~topToBottom SquareDifference(-a2c + + ,b2v);
484down = ~cd + + + rest;
485left = ~cl + + + rest;
486 downLeft = ~cdl + + + rest~ L~lW~,yllL~

488 if (down < left) 489 if (down ~ downLeft) {
490 /~ printf("%6.2f",down); ~1 491 ~dc+ + = down;
492 ~pc + + = DOWN;
493 }
494 eise {
495 /~ printf("%6.2f ",downLeft); ~/
496 ~dc+ + = downLeft;
497 ~pc+ + = DOWNLEFT;
498 }
499 else 500 if (downLeft < left) {
501 /~ printf(''%6.2f",downLeft); ~/
502 ~dc + + - downLeft;
503 ~pc+ + = DOWNLEFT;
504 }
505 else {
506 /~ printf("%6.2f",1eft); ~1 507 dc+ + 5 left;
508 ~pc + + = LEFT;
509 }
510 }
511 }

513 i--;
514 if (i&1) 515 dc = costsl +aLength~
516 else 517 dc = costsO+aLength-l + 1;
518 returnVal = ~dc;

520 #ifdef foo 521 if (IdoPath) {
522 y = i;
523 x = aLength-1;
524 whi le (path[yl[xl I = NONE) {
525 switch (path[y~[xl) {
526 case DOWN:
527 x--;
528 break;
529 case LEFT:
530 Y--;
531 break;
532 case DOWNLEFT:
533 x--;
534 y--;
535 break;
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX Page 111 536 default 537 DoError~"NewMatchAndPath Internal error - bad case \n",NULL);
538 }
539 fprintf(pathFP,''%d %d\n",x y);
540 }
541 ~ r(,ua~llrP,"%d %d\n",x,y); 2 0 7 7 9 6 9 543 e~s- {}
544 #endif 545 PrintPath(al,a2,aLength,bl,b2,bLength,path,i,returnVal,pathFP);

547 if (le ,y~ ", ' 548 return returnVallsqrt(aLength-aLength + bLength~bLength);
549 else SSû return returnVal;
551 }

554 floatSlopeCMatch(float~al,float~a2,intaLength,float~bl,float~b2,intbLensth, 5 55 f l oat u:" ~, We; ~ , BOOLEA N l ength N orm al i ~e,f l oat topToBottom ) 556 {
sS7 floatcostsûlMAX _ SIGNAL LENGTH+21;
558 floatcostsl[MAX _ SIGNAL LENGTH+21;
559 floatcosts2[MAX SIGNAL LENGrH+2 560 floatslope,minVal;
561 inti,j;
562 int ~ ' t~r 563 float'cdlll,~cd211,~cdli2;
564 float alc,-a2c,~cd,-cl,-cdi,~dc;
565 floatblv,b2v,returnVal;

567 /~ printf("sc \n"); 1 569 if(aLength>MAX SIGNAL LENGTHIlbLength>MAX SIGNAL LENGrH) 57û DoError("SlopeCMatch maxlmum signal length e~ceecled \n",NULL);

572 slope = (float)aLength/(float)bLength;
573 if ((slope>MAX SLOPE)~ lslope>MAX SLOPE)) {
574 return BIG _ NUM
575 }

577 f~r (i = O;i <aLength + 2; + + i) {
578 costs2ti¦ = 31G NUM;
579 costsl[il = BIG NUM;
580 costsO[i] = BIG _ NUM;
581 }

583 costsO(21 = SquareDifference(-al,~bl)~topToBottom ~SquareDifference(-a2,'b2);

585 f or (i = 1; i < bLength ; + + i ) {
586 bonom = IMax(il2,2~i + aLength-2~bLength);
587 top = IMin(2~i,il2 + aLength-bLength/2) + 1;

589 alc = al + bottom; /- al cursor ~/
S90 a2c = a2 + bottom; /~ a2 cursor /
Copyright~ 1991 XeroxCorporation All Rights Reserved Sec.+ion C APPENDIX Page 112 91 blv = ~bl +~ bl value 1 92 b2v = ~(b2+1);/'b2value~1 20779~9 594 swilch (i%3) {
595 case 0:
596 dc = costsO + bottom-2 + 2;
597 cd21 l = costs2 + bottom-2 + 2;
598 cdll2 = costsl +bottom-~ +2;
S99 cd l l l = costs2 + bottom- l + 2;
600 break;
601 case 1:
602 dc = costsl + bottom-2 + 2;
603 cd211 = costsO + bottom-2 + 2;
604 cd l 12 = costs2 + bottom- 1 + 2;
605 cd 111 = costsO + bottom-1 + 2;
606 break;
607 case 2:
608 dc = costs2 + bottom-2 + 2;
609 cd211 = costsl + bottom-2 + 2;
610 cdll2 = costsO+bottom-l +2;
611 cdll 1 = costsl + bottom-l + 2;
612 break;
613 }
614 ~dc+ + = 31G NUM;
615 ~dc+ + = BIG NUM, 616 for(j=bottom,i<top;+ +j){
617 floatd211,dll2,dlll,rest;
618 rest = SquareDifference(ta1c + + ,blv)~toproBottom +
619 SquareDifference(~a2c + + ,b2v);
620 dlll = cdlll + + + rest~é"~e.v~J~.~l,L, 621 dll2 = ~cdll2+ + + rest;
622 d211 = ~cd211 + + + rest;

624 ~dc+ + = FMin(FMin(dlll,d211),dl~2);
625 }

627 switch (i%3) {
628 case 0:
629 dc = costsO;
630 break;
631 case 1:
632 dc s costsl;
633 break;
634 case 2:
635 dc = costs2;
636 break;
637 }

639 #ifdef foo 640 minVal = BIG NUM;
641 printf("%6d: ~i);
642 for (j = O;j <aLength + 2; + + j) {
643 if (~dc c = minVal) 644 minVal = ~dc;
645 if (~dc + + > = BIG_NUM) Copyright~ 1991 XeroxCorporation All Rights Reserved Se~tlc)n C APPENDIX Page 113 646 p~intf("");
647 else 648 printf("^");
64so printf(" %6.2f\n",minVal); 2 ~ ~ 7 ~ 6 9 65 ~ #end i f 655 switch (i%3) {
656 case 0:
657 dc = costsO;
658 break;
653 case 1:
660 dc = costsl;
661 break;
662 case 2:
663 dc = costs2;
664 break;
665 }
666 returnVal = ~(dc+aLength-l +2);

668 if ~ Ll,t'c""alize) 669 return returnVal/sclrt(aLength~aLength + bLength~bLength);
670 else 677 r~turn returnVal;
672 }

675 floatSepSlopeCMatch(float~al,intaLength,float-bl,intbLength, 676 float~e"~ .W~ ,800LEAN lengthNormali~e) 677 {
678 floatcostsO[MAX SIGNAL LENGTH I 21;
679 floatcostsllMAX SIGNAL LENGTH + 2];
680 float costs2[MAX SIGNAL LENGTH + 21;
681 floatslope,minVa~
682 int i,j;
683 int bottom,top;
684 float~cd111,~cd211,~cdll2;
685 float ~a 1 c,-cd,~cl,~cdl,~dc;
686 float b I v,retu~nVal;

688 if(aLength>MAX SIGNAL LENGTHIlbLength>MAX SIGNAL LENGTH) 689 DoError("SlnreGr~; ',. max~mum slgnal length excee~ed.:n",NULL);

691 slope = (float)aLength/(float)bLength;
692 if((slope>MAX SLOPE)Il(l/slope>MAX SLOPE)){
693 return BIG _ NUM;
694 }

696 for(i =O;iCaLength +2; + +i) {
697 costs2~il = BIG NUM;
698 costsl[il = BIG NUM;
699 costsOli] - BIG _ NUM;
7ûO }
Copyright ~ 1991 Xerox Corporation All Rights Reserved Section C APPENDIX, Page ~1 i ho2 costs0[2¦ = SquareDifference('al,-bl); 2 ~ 7 7 ~ ~ 9 7û4 fot(i = l;i<bLength; + +i) {
705 bottom = IMax(i/2,2~i+aLength-2-bLength);
706 top = IMin(2~i,il2 + a~ength-bLength/2) + 1;

708 alc = al +bottom; /-a1 cursor-709 blv = (bl +1) /- bl value '/

711 swit~h (i%3) {
712 caseO
713 dc = costsO + bottom-2 + 2;
714 cd211 = costs2 + bottom-2 + 2;
715 cdll2 = costsl +bottom-l +2;
716 cd 111 = costs2 + bottom-l + Z;
7t7 break;
718 case 1 719 dc = costsl + bottom-2 + 2;
720 cd211 = costsO + bottom-2 + 2;
72 1 cd l l2 = costs2 + bottom - 1+ 2 ;
722 cd 1 i I = costsO + bottom- 1 r 2;
723 break;
724 case 2 725 dc = costs2 + bottom-2 + 2;
726 cd211 = costsl +bouom-2+2;
727 cdll2 = costsO+bottom-l +2;
728 cd 11~ = costs 1 + bottom-1 + 2;
729 break;
730 }
731 ~dcf + = 31G NUM;
732 dc+ + = BiG NUM
733 for(j=bottom,j<top, r +)){
734 f~oat d211,d 112,d 111,rest;
735 rest = SquareDifference(-alc+ +,blv);
736 dlll = cdlll + + + rest-~"L~:,\A'r 4~,L, 737 dll2 = cdll2+ + + rest;
738 d211 = cd211 + + + rest;

740 dc+ + = FMin(FMin(dlll,d211),dll2);
741 }

743 switch (i~3) {
744 case O
745 dc = costsO;
746 break;
747 case 1 748 dc = costsl;
749 break;
750 case 2 751 dc = costs2;
752 break;
753 }
754 }

Copyright~ 1991 XeroxCorporation All Rights Beserved Se~tlon C APPENDIX, Page 115 757 switch (i % 3) { 2 ~ 7 7 ~ ~ 9 758 case 0:
759 dc = costsO;
760 break;
761 case 1:
762 dc = costsl;
763 break;
764 case 2:
765 dc = costs2;
766 break;
767 }
768 returnVal = ~(dc+aLength-l +2);

770 it(le.,y~ "",alize) 771 return returnVallsqrt(aLength~aLength + bLength~bLength);
772 else 773 retu m returnVal;
774 }

777 float SlopeCMatchAndPath(float ~a 1 ,float ~a2,int aLength,float 'bl ,float 'b2,int bLength, 778 float~ BooLEANl~lyLl~ ", ' ,fl^~-topro30ttom, 779 FILE ~pathFP) 780 {
781 Direction path[MAX _ SIGNAL _ LENGTH IMAX _ SIGNAL_LENGTHI,~pc;
782 floatcostsO[MAX _ SIGNAL LENGTH+2;
783 floatcosts~[MAX SIGNAL LENGTH+2;
784 float costs2[MAX SIGNAL LENGTH + 2;
785 floatslope,minVa 786 int i,j;
787 int bottom,top;
788 float~cdlll,~cd211,~cdll2;
789 float 'alc,~a2c,~cd,~cl,~cdl,~dc;
790 float bl v,b2v,returnVal;

792 /~ printf("sc:~n''); '/

794 if (aLength>MAX SIGNAL LENGTHIlbLength~MAX SIGNAL LENGTH) 795 DoError("SlopeCMatch: maxlmum slgnal length exceeTed.\n",NULL);

797 slope = ~float)aLengthl(float)bLength;
798 if ((slope>MAX SLOPE)Il(llslope>MAX SLOPE)) {
799 return 81G_NUM;

802 For(i = O;i<aLength + 2; + + i) {
803 costs2[i] = BIG NUM;
804 costsl[i] = BIG NUM;
805 costsO[il = BIG _ NUM;

808 pc = &(path[OI[O]);
809 ~pc+ + = NONE;
810 costsO[2] = SquareDifference(-al,'b1)~toproBottom+SquareDifference(~a2,7b2);
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX P~ge 116 ~2 ;or(i=l;i<bLength;+ +1)~ ~77g~
813 bouom = IMax(il2,2-i+aLength-2~bLength);
814 top = IMin(2'i,i/2 + aLength-bLengthl2) + 1;

816 alc = al +bottom; /-al cursOr-/
817 a2c = a2+bottom; I-a2cursor-1 818 blv = ~(bl + i); /- bl value ^/
819 b2v = ~(b2 + i); /- b2 value /
82û
821 switch (i%3) {
822 case 0 823 dc = costsû + bottom-2 + 2;
824 cd211 = costs2 + bottom 2 + 2;
825 cdll2 = costsl +bottom-l +2;
826 cd 111 = costs2 + bottom- 1 + 2;
827 break;
828 case 1 829 dc = costsl + bottom-2 + 2;
830 cd211 = costsû + bottorn-2 + 2;
831 cdll2 = costs2 + bottom-1+ 2;
832 cd 111 = costsO + bottom- 1 + 2;
833 break;
834 case 2 835 dc = costs2 + bottom-2 + 2;
836 cd211 = costs1 + bottom-2 + 2;
837 cdll2 = costsû+bottom-~ +2;
838 cdlll = costsl +bottom-l +2;
839 break;
84û }
841 ~dc+ + = BIG_NUM;
842 ~dc + + = 31G NUM;
843 pc = &(path~ ottoml);
844 for(j=bottom;j<top;+ +j){
845 float d211 ,d 112,d 111 ,rest;

847 rest = SquareDifference(-alc + + ,blv)-topToBottom +
848 SquareDifference(-a2c + + ,b2v);
849 dlll = cdlll + + + le~ ell~e~ 'e;~llL, 850 dll2 = cdll2+ + + rest;
851 d211 = cd211 + + + rfft;

853 if (dlll <dll2) 854 if (dlll ~d211) {
855 dc+ + = dlll;
856 pc+ + = DlLI;
857 }
858 else {
859 'dc+ + = d211;
860 ~pc+ + = D2Ll;
861 }
862 else 863 if (dll2~d211) {
864 ~dc+ + = dll2;
865 pc+ + = DlL2;
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon C APPENDIX P~ge 117 866 } 20779~9 867 else {
868 ~dc+ + = d211;
869 ~pc+ + = D2L1 871 }

873 switch (i%3) {
874 case 0:
875 dc = costsO;
876 break;
877 case 1:
878 dc = costs1;
879 break;
880 case 2:
881 dc = costs2;
882 break;
883 }
884 mlnVal = BIG NUM;
885 printf(''%6d:'',l);
886 for(j =O;jCaLength + 2;
887 if ~dc < = minVal) 888 minVal = ~dc;
889 if (~dc + + > = 81G NUM) 890 printf("");
89 1 else 892 printf("~");
893 }
894 printf(" %6.2f\n",minVal);
895 }

898 switch (i%3) {
899 case 0:
900 dc = costsO;
901 break;
902 case 1:
903 dc = costs~;
904 break;
905 case 2:
906 dc = costs2;
907 break;
908 }
909 returnVal = ~(dc + aLensth- 1 ~ 2);

91 ~ PrintPath(a ~ ,a2,aLength,b ~ ,b2,bLength,path,i ,returnVal ,pathFP);

913 ,r(lengthNormalize) 914 return returnVal/sqrt~aLength~aLength ~ bLength~bLength);
915 else 916 return returnVal;
917 }

Copyright~ 199~ Xerox~orporation All Righ~s Resers~ed SectlonC APPENDIX Pcige 118 lg 2 02:291991 recogDesc.c 2 ~ 7 ~ 9 ~i ~
#include <stdio.h~
2 #include''mylib.h"
3 #include''types.h'' 4 #inciude''dict.h"
#include''diff.h"

7 #defineBlG NUM(lOe~0) 8 #define MAX WORDS (100) 9 #define MAX FONTS ( l o) 11 extern double sqrt(double);
13 float CompareNumerlcDescriptors(float 'a,float b,int length) 14 {
Inti;
16 float sum;
17 for (i = 0,sum = 0;i clength; + + i~ {
18 sum + = (~a-~b)~'a-'b);
19 + +a;
+ +b;
21 }
22 return sqrt(sum);
23 }

float ~ComputeNumericDescriptor(int modelln~iex,Dictionary models, 26 Dictionary 'fonts,int numberOfFonts,int numberOfWords, 27 DiffDescriptor dd, 28 float ~sd,float ~avg) 29 {
float 'd;
31 Int i,j;
32 float temp;
33 float sumxx[MAX WORDSI;
34 float sdev[MAX WORDS];
3s fioat sumsdeY,sumscore;

37 if ~d = (float ~)calloc~numberOfWords.sizeof(float))) = = NULL) 38 DoError("ComputeNumericDescriptor: cannot allocate space.\nl~lNuLL);
39 for(j=0;j<numberOfWords;+ +j) sumxxi'i] = ;
41 for (i = 0; i c numberOfFonts; + + i) 42 for(j =0;jCnumberOfWords; + +j) {
43 temp=DiffPair(~(models->outlines+modellndex),~fonts[il->outlines~l),dd);
44 If (temp c BIG NUM) {
d[j] + = temp;
46 sumxx[j]+ =temp~temp;
47 }
48 }

if ~numberOfFonts ~ 1) {
51 floatsum,minsdev,maxsdev;
52 for (j = 0;j ~numberOfWords; + + j) Copyright g 199~ Xerox Corporation All Rlghts Reserved Sectlon C APPENDIX, Page 119 2~77i3~9 53 sdev[J¦ = sqrt((numberofFonts-sumxx[i]-d[li-d[i])lnumbe~ofFonls/(numbe~ofFont 54 for (j - û,sumsdev = û,sumscore = 0;j < num berOfWo~ds; + + j) {
sumsdev + = sdev~j];
56 sumscore + = d[j];
57 }
58 'sd = sumsdev/numberOfWords;
S9 ~avg = sumscorelnumberOfWords;
6û }

62 for (j = 0;j < numberOfWords; + + j) 63 di'j¦/=numberOfFonts;

return d;
66 }

68 typedef slruct {
69 float score;
int x;
71 inty;
73 } 'CompareTuple,CompareTuple30dy;
74 int TupleLessThan(CompareTupie ~x,CompareTupie 'y) {
76 if((-x)->score = = ('y)->score) 77 return 0;
78 else if ((-x)->score < (-y)->score) 79 return-1;
else 81 eturn 1;
82 }

8~
void DoDescriptors(Dictionary models,char modelName,char ~-wordNames, 86 int numberOfFonts,Dictionary fonts,char ~fontNames, 87 int numberOfWords,DiffDescrlptor dd) 88 {
89 float 'd~ ,rllAX WORDSI;
int classes[MAX WORDSI~MAX WORDSl;
91 floatsdevlMAX WORDSl,aYglMAX WORDSI;
92 CompareTuple~ody tuplfflMAX WORDS-MAX WORDSI;
93 CompareTup''iescoreslMAX WORDS-MAX WORDSI;
94 int i,x,y,j;
9S int count;
96 1~ floatthreshold = 0 22; 1 97 floatthreshold = 042;

99 for(i=0;i<numberOfWords;+ +i){
100 ~escriptors[i] =
C -outeNumericDescriptor(i ,models,fonts,m,mberOfFonts,numberOfWords,dd, 10l sdev + I,avg ~ 1);
102 iprintf(stdout,"%s %6 4f %6 4f\n",wordNames[i],avg[i],sdev[i]);
103 }
104 r~. i"~("dout,"\n\n'');

106 for(y=0;y<numberOfWords; + +y) Copyright 1991 XeroxCorporation All Rlghts F~eserved Sec+~ion C APPEND~X Pdge '~ 20 07 for(x=0:x<numberOfWords; + +Y) 2~77~i~)9 108 classeslyl[xl =
~CompareNumericDescriptors(desCriptors[yl~descrlptors(x~numberofwords) 109 < threshold);
llû

112 #ifdef foo 113 for (y = 0,i = 0;y<numberOfWords; + + y) 114 for (x = 0;xcy; + + x) {
115 CompareTuple temp;
116 /~
117 temp = (CompareTuple)calloc(l,sizeof(CompareTupleBody));
118 if (temp = = NULL~
119 Do~rror(":cannotallocatespace.'~n",NULL);
l 20 '/
121 temp = tuples+i;
122 temp->score =
CompareNumericDescriptors(descriptors(y],descrlptors[x],numberOfWords);
123 temp-~x = x;
124 temp->y = y;
125 scores~i] = temp;
126 + +i;
127 }
128 qsort(scores,i,sizeof(CompareTuple),TupleLessThan);

13û for(j =û;j<i; + +j) 131 fprintf(stdout,"(%s,%s~:
%f\n',v. ..,I.~ scoresGI->yj,wordNames[sc~reslj]-~xl,scoreslj]->score);
l 32 #endif 134 fprintf(stdout,"`~n~n"), 135 for(i=O;i<numberOfWords;++i)~
136 CompareTupie temp;
137 float 'thisDesc;
138 float junk;
139 thisDesc =
ComputeNumericDescriptor(i,models,&models, ~ ,numberOfWords,dd,&junk,&junk);
140 for (j = 0; j < numberOfWords; + + j) {
141 temp = tuples+J;
142 temp->score = CompareNumericDes~"~ l"sC)esc,descriptors[j],numberOfWords~;143 temp->y = i;
144 temp->x = j;
145 scoresGI = temp;
146 }
147 qsort(scores,numberOfWords,sizeof(CompareTuple),TupleLessrhan);

149 fprintf(stdout,"~rs:",wordNamesli]);
15û for(j=0;j<5&&j<numberOfWords;+ +I){
151 fprintf(stdout~%sl~wordNames[scores(l]->xl);
152 if(scores[jl->x = = i) l 53 break;
154 }
155 If(scoresGI->x= =i) 156 fprintf(stdout,''\n");
157 else {
Copyright 9 1991 Xerox Corporation All Rights Reserved Sectlon C APPEND~X Page 121 158 for (;j<numberOfWords; + +j) 2 0 7 7 9 ~ ~--160 break;
161 fprintf~stdout," (%dmore~\n",j-S);
162 }

164 fprintf~stdout," ");
165 count = 0;
166 for (j = 0; j < numberOfWords; + + j) 167 if ~C~ ol->x][il) {
168 fprintf(stdout,"%s",wordNames 169 + +count;
170 if(count > S) 171 break;
172 }
173 i f (j < numberOfWords) {
174 for(count=0;j<numberOfWords;+ +j) 175 if(cla~e~[~ e~[ol->x~
176 + +count;
177 fprintf(stdout," (% more)~n'',count);
1 78 ~
179 else 180 ryli~ t~\n~

182 free(thisDesc);
183 }
184 }

186 void main(int argc,char ~argv) 187 {
188 char ~listFile;
189 Dictionarymodels;
190 char ~modelName;
191 int numberOfFonts;
192 Dictionaryfonts~MAX FONTS~;
193 char ~fontNames[MAX FONTSI;
194 char~~ \X WORDS];
195 int numberOfWords;
196 float ~e. .~e, W~
197 intnormalBandWidth;
1 98 300Lr-'AN
~.-yll.~ I '' ,llc~l 7 clopeconstrain~warp~topToBottomoption~hillTovalleyoption;199 300LEANseparate;
200 floattopToBottom,hillToValleyLocal;
201 FILE ~listfp;
202 int i,x,y;
203 DiffDé,~l ,ul.. Bcld~ dd;

205 ~e.,~e,`i~o;,jl,L = 1.0;
206 normalBandWidth = 20;
207 topToBottom = 1.0;
208 hillToValleyLocal = 10;
209 DefArg("~Os","listFile",&listFile);
210 DefOption("-L2'',"-~2n,&useL2);
2t 1 DefOption~"-slopeConstrain %f","-slopeConstrain <centerweight>", Copyright 1991 XeroxCorporation All Rights Reserved Sectic~n C APPENDIX Page 122 ~12 &slopeConstraln,&centerWelghtl;
13 DefOption("-warp %f %d","-warp <centerweight> <band wldth>", 2 ~ 7 7 ~ ~ 9 214 &wa-p,&centerWeight,&no-malBandWidth);
215 DefOption("-separate","-separate",&ieparate~;
216 DefOption("-narmalize",''-normalize",~ y-l,r~ aliLe);
217 DefOption("-topToBottom %f","-topToBottom <ratio>",&topToBottomOption,&topro30ttom~;
218 DefOption(''-hiliToValley %f","-hillToValley <ratio> ",&hillToValleyOption,&hillToValleyLocal);
2 ~ 9 ScanArgs(a rgc,argv);

221 if((listfp = fopen(listFile, r ))= =NULL) 222 DoError("Erroropenlng file ~s.~n'',listFile);

224 /' Redd in the number of words in each dictionary '/
225 numberOfWords = Readlnt(listfp);
226 If (numberOfWords ~ MAX WORDS) 227 DoError(" ~s: too many words.\n",argv[ûl);

229 /' Read in the words '/
23û for(i =0;i<numberOfWords; + + i) {
231 wordNameslil = ReadString(listfp);
232 }

234 /' Read in the model dictionary '/
235 model~: n~ = ReadString(listfp);
236 models = ReadDictionary(modelName);

238 /~ Read in the number of dictionaries '/
239 numberOfFonts = R~adl"l(li,lr~);
240 if (numberOfFonts > MAX FONTS) 241 DoError("%s:toomanydictionaries.\n'',argv[0¦);

243 /' Read in the dictionaries and their names '/
244 for (i = 0;i <numberOfFonts; + + i? {
245 fontNames[il - ReadString(listfp~;
246 fontsli] = ReadDictionary(fontNames[il);
247 }

249 /'Checktoseethatalldictionarieshavethesamenumberofshapesasthespecifiednumber of words. '/
250 for(i = l;i<numberOfFonts; + +i) 25t if (fonts[i]->numberOfEntries < numberOfWords) 252 DoError("Dictionary %s has too few entries.\n",fontNames[il);
253 if(models->numberOfEnt~ies < numberOfWords) 254 DoError("Model dictionary has too few of entrles.\n" ,NULL);

257 if (useL2) {
258 Fprlntf(stdout,''Using L2 on length normalized shapes.\n );
259 dd.diffType = L2;
260 }
261 else if (slopeConstrain) {
262 fprintf(stdout,"Using dynamic time warplng wlth slope contralned to [0.5,21.\n");
263 dd.diffType = CONSTRAINED;
Copyright~ 1991 XeroxCorporation All Rlghts Reserved Sectlon C APPENDIX Page 123 2645 if fseparate) 2 0 7 7 3 ~ ~ --266 r,., il ,lr(~dout~l~Top and bottom warped separately \n");
267 else 268 fprintf(stdout,"Top and bottom warped together.\n"~;
269 }
270 else {
271 r,.lill~t(sLiout,"Usingdynamictimewarpingwithbandwidth%d.\n",normaiBandWidth);
272 dd.diffType = WARP;
273 cdd.bandWidth = normalBandWidth;
274 dd.separate = separate;
275 if (separate) 276 ryli"~r(,~Liout,"Topandbottomwarpedseparately.\n");
277 else 278 ~ r(stcout,''Top and bottom warped together.\n");
279 }
280 if (!useL2) ~
281 fprintf(stdout,''Centerweight = %f.\n",centerWeight);
282 dd.centerWeight = ~ lWe.~l,L, 283 if(It.~y~ rllldliLe){
284 dd.l~"S,~l,rJa,ll,.,l-ze = TRUE;
285 t,~,ll.. lr(i"iout,"Scoresnormali~edbyslgnallength.\n");
286 }
287 else 288 dd.lengthNormali~e = FALSE;
289 }
290 dd.hillToValley = hillToValleyLocal;
291 dd.topToBottom = topToBottom;
292 dd.pathFP = NULL;

294 (,~.. ,.. r(,l~iout,"Words:\n'');
295 for(i=0;icnumberOfWords; + +i) 296 rp-;l,Lr(~Li~,ut,",'Od: ~Os~n",i,~.c--l''!< ~-~Li~);
297 ~1 -;,, L~(~l.Jout, "~n '');
298 fprintf(stdout,"Model font Is /Os.\n'',modelName);
299 r,.";"Lr(~L iout,"Fonts:\n'');
300 for(i =0;i<numberOfFonts; + +i) 301 fprintf(stdout," %d: %s\n" ,i ,fontNames[i]);
302 fprintf(stdout,"\n");

Dor~escriptors(models,modelName,wordNames,numberOfFonts,fonts,fontNames,numberO
fWords,lLdd):
30S }
Copyright ~ 1991 Xerox Corpo~ation All Rights Reserved Section C APPENDIX Page 12~L
~n ~816:201991 resample.~
2077~9 #include <stdio.h>
2 #include ~values.h >
3 #include C string.h >
4 #include <floatingpoint.h>
#include''boolean,h"
6 #include"types.h"
7 ~include"error.h"
8 #include"dict.h"

void Resample(OutlinePair slgnal,float factor) tl {
12 int i,count;
3 float pivot;
4 float del Factor;
l s float ~oldTop,'newTop;
16 float ~oldBottom,~newaottom;
17 float ~topSPtr,~topDPtr;
18 float~bu~L~,,.,;rtr,~bottomDPtr;

delFactor = l.û - factor;
21 for(i =0,count=û,pivot=û.0;i<signal->numberOfLegs; + +i) {
22 if (pivot> = 1.0) {
23 pivot - = 1 ,o;
24 pivot + = delFactor;
}
26 else {
27 pivot + = delFactor;
28 + +count;
29 }
}

32 newTop = ~float )calloc(count,si2eof(float));
33 newBottom = (float ~calloc(count,si zeof(float~);
34 if ((newrop = = NULL)¦¦(newBottom = = NULL)) DoError("Resample: cannot allocate space.~n",NULL);

37 oldTop = signal->top;
38 oldBottom = signal->bottom;

topSF~tr = signal->top;
41 bottomSF~tr = signal->bottom;
42 topDPtr = newTop;
43 bottomDFtr = newaottom;
44 for(i - 0,pivot-0.0;i<signai->numberOfLegs; + ~ i) {
If (pivot> = 1 .û) {
46 pivot - = I .0;
47 pivot + = delFactor;
48 + + topSFtr;
49 + + bottomSF~tr;
}
Sl else {
52 pivot + = de~Factor;
Copyright'~ 1991 Xero~(Corporatlon All Rights Reserved ~ctlGn ~ APPENLJIA P~ge 125 53 'topDPtr ~ ~ = 'topSPtr I +, 54 'bottomDPtr + + = 'bottomSPtr ~ -, 2 ~ 7 ~ 9 6 9 ss }
56 }

58 signal->top = newTop;
S9 signal->bottom = new30ttom;
signal->numberOfLess = count;
62 free(oldTop);
63 frr~(ol~lRott,~
64 }
66 void main(int argc,char -argv) 67 {
68 clldr inFile,-outFile;
69 float factor;
int i;
71 Dictionary dict;

73 if (argc ! = 4) {
74 ~,.""~(,Ld_","Usage \n");
~,i"Lr(~L~"," ~Os <inputfile> ~outputfile> <.o,rlu,~";o, factor>\n",argY~O]);
76 r~n;"Lr(~L~ ""Compressesshapes horlzontally \n'');
77 exit(- I );
78 }

if ((factor> = ~ O)Il(factor<û O)) 81 DoError(",6s factor must be between O and 1 \n",argv~O]);

83 inFile = argv~
84 outFile = argv~2];
factor = atof(argv[3]);

87 dict = ReadDictionary(inFile);

89 for (i = O;i <dict->numberOfEntries; + + i) Resample(-(dict->outlines + I),factor);

92 WriteDictionary(dict,outFile);
93 }

Copyright D 1991 Xero~Corporation All Rights r~eserved Sectlon C APPENDIX ' Page 126 ul 31 16.481991 sepMatch.c 2 ~ 7 r~ ~ ~ 9 #include <stdio.h>
2 #include"mylib,h"
3 #include"misc.h"

S #define MAX SIGNAL LENGTH (800) 6 #define MAX SLOPE (2 0) 7 #defineBlG_NUM~lOe20) 9 typedefenum{NONE,LEFT,DOWN,DOWNLEFT,DlLl,D2Ll,DlL2}Direction;
11 extern double sqrt(double);
12 extern double cos~double);
13 extern double atan(double);
14 extern int irint(double);
16 /~ Assumes that a represents the model and b represents the unknown.
17 Welghts places where the model is lower than the unknown more than 18 'caseswherethemodelishigherthantheunknown. Theideaherels 19 ~thatvalleyscanbefilledinbybleedingtogether,butthatnoise ~ can rarely make a contour be too tall for extended periods.

22 floathillToValley = 1.0;
23 inline float SquareDifference(float a,float b) 24 {
floattemp = a-b;
26 i f (tem p < 0) 27 return t~,.,p~l 28 else 29 return ~ p'~m"'hillToValley~hillroValley;
/~ return (a-b)'(a-b); ~1 3~ }

33 inline float FMax(float a,float b) 34 {
i f (a > b) 36 return a;
37 else 38 return b;
39 }

41 inline float FMin(float a,float b) 42 {
43 if(a<b) 44 return a;
else 46 return b;
47 }

49 iniine Int IMax(int a,int b) {
51 if(a>b) 52 return a;
Copyright ~199 ~ Xerox Corporation All Rights Reserved Sectlon C APPENDIX Page 127 53 e!se 2~779~9 54 return b;
55 }

57 inline int IMin(int a,int b) 58 {
S9 If ~a<b) 60 return a;
61 else 62 return b;
63 }

65 floatr~ ~' ',(float~al,float-a2,intaLength,float-bt,float-b2,intbLength, 66float.~"Lt ~'v~ ,BOOLEAN l_ ,yil,r~ li.e,lntnormal3andWidth, 6~float topToBottom) 68 {
69floatcostsO[MAX SIGNAL LENGTH + 11;
70floatcostsl[MAX SIGNAL LENGTH + 11;
71Intl,J,start,end,bandWidth,shift;
72IntrealStart,realEnd,center,oldEnd;
73f~oat slope,angle;
74float 'a~c,-a2c,-cd,-cl,-cdl,^dc;
75floatoldCost,blv,b2v,returnVal;

77 if ~aLength>MAX SIGNAL LENGTH¦¦bLength>MAX SIGNAL LENGTH) 78 DoError(" NewMatch maximum signai length exceeded \n '',NULL);

slope = (float)aL~:"y~ .a~)LLength;

82 if (~slope>MAX SLOPE)¦¦(I/slope>MAX SLOPE)) {
83 return BIG _ NUM;
84 }
angle = atan(slope);
86 bandWidth = irint(no",l '~ Id~'idll,/~os(angle~);
87 center = 0;
88 realStart = center-bandWidth/2;
89 realEnd = realStart+bandWidth;
end = FMin(realEnd,aLength);

92 alc = al; l~al cursor~/
93 aZc = a2 /~ a2 cursor ~/
94 b~v = bt; /^ bl value ~/
9S b2v = ~b2; /~ b2 value ~/
96 dc = costs0;
97 dc+ + = BIG NUM;
98 oldCost = 'dc + + =
SquareDifference(ta1c + + ,blv)-topToBottom + SquareDifference(-a2c + + ,b2v);

100 for (j = I ;j <end; + + j) 101 oldCost = dc+ + =
oldCost +SquareDifference~-alc + + ,blv)-topToBottom +SquareDifference(-a2c+ + ,b2v~

103 for~i= l;i<bLength; + +i){
104 /- Compute new center of band /
105 center = irint(slope-i);
Copyriqht~ 1991 XeroxCorporation All Rights Reserved Sertlon C APPENDIX Pj~ge 128 06realStart = center-bandWidth/2, 07realEnd = realStdrt+bdndWidth;
108stdrt = FMax(redlStart,O):
109oldEnd = end; 2 o ~ 7 ~ 6 ~
110end = FMin(realEnd~aLength);
111shift = end-oldEnd;

113/~ put large numbers where bands don't overlap ~/
114for(j=O;j<shift;+ +j) llS'dc+ + = 31G _ NUM;

117alc = al +start; /~al cursor~/
118,a2c = a2 + start; /~ a2 cursor ~/
119blv= ~(bl+i);/~blvalue~/
~ 20b2v = '(b2 + i); /~ b2 value ~/
121if (i&l) {
122 cd = costs1 + start- 1 + 1; /- cursor down ??7 What about - ~ ??? ~/
123 cdl = costsO +start-l + 1; /~ cursordown left ^/
~ 24 cl = costsO + start + l; /~ cursor left ~/
125 dc--costsl +start+ 1; /~ destination ~u~sor /
126 }
127 else{
128 cd = costsO+start-l + l; /~cursordown~/
129 cdl = costs 1 + start- 1 + 1; /~ cursor down left t/
130 ~I = costs7 + start + 1; /' cursor left ~/
13t dc = costsO+start+1; /~destinationcursor~/
132 }
133 ~cd = 31G NUM;
134 for (j = start;j cend; + + j) {
135 float down,left,downLeft,rest;
136 down = ~cd + + + rest;
137 left = tcl + + + rest;
138 downLeft = ~cdl + + + est~ce"L~,We ryl,L, 139 rest = SquareDifference(^alc+ +,blv)~topTo60ttom+
140 SquareDifference(~a2c + + ,b2v);
141 ~dc + + = FMin(FMin(down,left),downLeft);
142 }
143 }

1 45 i--;
146 if (i&l) 147 dc = costsl +aLength-l + I;
148 else 149 dc = costsû + aLength- I + l;
lSO returnVal = ~dc;

152 if (lengthNormali~e) 153 eturn returnVal/sqrt(aLength~aLength + bLength'bLength);
1 54 else l SS eturn returnVal;
156 }
~57 l S9 void PrintPath(float al ,float ~a2,int aLength,float ~bl ,float ~b2,int bLength, 160 Direction path[MAX SIGNAL LENGrH]lMAX SIGNAL_LENGTH~,int i, Copyright r~ 1991 Xerox Corporation ~11 Rights Reserved Se~tlon C APPENI~IX Page 129 207796~L
161 ~loatreturnVal, 162 FILE pathFP) 164 intx,y,j;
165 intlength = 0;
166 int index = 0;
167 float newTopl [MAX SIGNAL LENGTH¦,newBottom I [MAX SIGNAL LENGTH¦;
168 float newTop2[MAX_SIGNAL_LENGTHl,newBottom2[MAX_SIGNAL_LENGTHI;

~70 y = i; -171 x = aLength-l;
172 while(path[y]lx]!=NONE){
173 switch (path[yl[xl) {
174 case DOWN:
1 75 x--;
1 76 break;
177 case LEFT:
1 78 Y--;
1 79 break;
180 caseDlLl:
181 case DOWNLEFT:
182 x--;
183 Y--;
184 break;
185 case D2Ll:
186 x-=2;
1 87 y--;
188 break;
189 case D 1 L2:
1 90 x-;
191 y-=2;
192 break;
193 default:
194 DoError("NewMatchAndPath: Interndl error - bad case.\n",NU~L);
195 }
196 ~ I length;
197 }

199 y = i;
200 x = aLength-l;
201 while (pathly~[xl! = NONE) {
202 if(ind~x>=MAX SIGNAL LENGTH) 203 DoError("~./M hrt ' '?~ : warped signal IS too long.\n",NULL);
204 newTopl[length-indexl = al[xl;
205 newBottoml[length-indexl = a2[xl;
206 newTop211ength-indexl = bl[yl;
207 newBottom2[1ength-indexl = b2[y];
208 switch (path[y][xl) {
209 case DOWN:
210 x--;
21 1 break;
212 case LEFT:
213 y._;
214 break;
215 caseDlLl:
Copyright 1991 XeroxCorporation All Rights Reserved SectionC APPENDIX Page 130 2~7~59 ~16 case DOWNLEFT:
2~7 x--;
2~8 y--;
219 break;
220 case D2LI:
221 x-=2;
222 y--;
223 break;
224 case D 1 L2:
225 x--;
226 y- = 2;
227 break;
228 default:
229 DoError("NewMatchAndPath: Internal error - bad case.\n",NULL);
230 }
231 + +index;

233 if(index>=MAX SIGNAL LENGTH) 234 DoError("NewliAatchAddPath: warped signal Is too long.\n' ,NULL);
235 newTopl[length-lndexl = al[x~;
236 new3Ottoml¦length-,ndex¦ = a2¦xl;
237 newrop2~1ength-index] = bllyl;
238 new3Ottom2[1ength-indexl = b2[yl;
239 + +index;
24û
241 for(j=0;j<index;+ +j) 242 fpnntf(pathFP,"%d %f~n",j,newrop~jJ);
243 fprintf(pathfP,"\"topl~n\n");
24~
245 for (j = 0;j<index; + + j) 246 fprintf(pathFP, " % d % f\n " ,j,newTop2~j ]);
247 fprintf(pathFP,"~"top2~n\n");

249 for(j=0;j<index;+ +j) 250 fprintf(pathFP,''%d %f\n",j,-newBottom I [il);
251 fprintf(pathFP,"\"bottoml\n\n");

253 for (j = 0;j <lndex; + + j) 254 fprintf(pathFP,"%d %f\n",j,-newBottom2[jl);
255 fprintf(pathFP,"\"bottom2\n\n");

258 float checksum;
259 t,~ r(pall,rr,~% d %f\n'',0,checksum);
260 fora =0,checksum = 0;j<index; + +J) ~
261 checksum + = SquareDifference(newrop I [j 1, newrop2~j]) +
262 SquareDlfference(newBottom 1 [jl,newBottom2[j¦);
263 fprintf(pathFP,"%d %f n",j,checksum):
264 }
265 printf(''checksum, score = %6.2f, %6.2f\n",checksum,returnVal);
266 }
267 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Se~tl o n C ~PPE N Dl X Pa g e 1 3 1 2~77~9 271 floatNewMatchAncPath~float~al~float~a2~lntaLength~float-bl,float~b2~1ntbLength~
272 floatcenterWeight,BOOLEAN lengthNormalize,lntnormalBandWidth, 273 floattopTo80ttom,FlLE ~pathFP) 274 {
275 Direction path[MAX SIGNAL_LENGTH¦[MAX_SIGNAL LENGTH],~pc:
276 int x,y;
277 floatcostsO[MAX _ SIGNAL _ LENGTH + l~;
278 floatcostsl[MAX SIGNAL LENGTH + tl;
279 int i,j,sta~t,end,bandWidth,shlft;
280 int realStart,realEnd,center,oldEnd;
281 float slope,angle;
282 float ~a~c,~a2c,~cd,~cl,'cdl,-dc;
2 83 f I oat ol dCost, b ~ v,b2Y, retu rnVal;

285 if(aLength>MAX SIGNAL LENGTH¦¦bLength>MAX SIGNAL LENGTH) 286 DoError("NewMatch: maxlmum slgnal length exceede~\n",NULL);

288 slope = (float)aLength/(float)bLength;

29û if((slope~MAX SLOPE)¦¦(llslope>MAX SLOPE)){
29~ return 81G NUM;
292 }
293 angle = atan(slope);
294 bandWidth = Irint(normalBar,d`~ (angle));
295 center = 0;
296 realStart = center-bandWidth/2;
297 realEnd = realStart+bandWidth;
298 end = FMin(realEnd,aLength);

300 alc = a~; /' a~ cursor ~/
3ûl a2c = a2; /~ a2 cursor ~/
3û2 blv = ~bl; /~ bl value ~/
303 b2v = ~b2; /- b2 value '/
304 dc = costsO;
305 pc = &(path[0][û]);
3û6 ~dc+ + = 31G NUM;
307 oldCost = ~dc + + =
SquareDifference(~a ~ c + + ,b I v)~topToBottom + SquareDifference(ta2c + + ,b2v);
308 ~pc+ ~ = NONE;

3~0 for(j = 1;j<end; + + j) {
311 oldCost = dc+ + =
oldCost+SquareDifference(~alc+ +,blv)~topToBottom+SquareDifference(~a2c+ +,b2v);312 ~pc+ + = DOWN;
313 }
3~4 315 #ifdef foo 316 printf("~66d",0);
317 for (j = 0;j Cend; + + j) 318 printf("%6,2f '',costsû[j + 11);
319 #endif 321 for(i= l;i<bLength; + +i){
322 /~ Compute new center of band ~/
323 center = irint(slope~l);
Copyright0 1991 XeroxCorporation All Rlghts Reserved Sectlon C APPENDIX, Page 132 2~ 69 4 realStart = center-panoVltldth/2 ~ZS realEnd = realStart+bandWldth, 326 start z FMax(realStart,O) 327 oldEnd = end;
328 end = FMin(realEnd,aLength);
329 shift = end-oldEnd;

331 /'putlargenumberswherebandsdon'toverlap'/
332 for(j=O;jcshift: + +j){
333 /~ printf("%6.2f",BlG NUM); ~t 334 'dc+ + = BIG _ NUM
335 }
336 /^ printf("\n%6d",i) '/

338 a 1 c = a 1 + start: 1' a t cursor 'I
339 a2c = a2 + start; /' a2 cursor '/
340 b~v = ~(bl ~ 1): /' b~ value '/
341 b2v = '~b2 ~1): /~ b2 value '/
342 pc = &(path[il[start]):
343 if (i&l) {
344 cd = costsl +start-l +1: /'cursordown?7?Whatabout-l???~/
345 cdl = costsO + start- I + 1; /~ cursor down left '/
346 cl = costsû + start + 1; /~ cursor ~eft '/
347 dc = costs~ + start + 1 /~ destination cursor '/
348 }
349 else t 350 cd = costsO + start- 1 + 1; /^ cursor down '/
351 cdl = costsl ~ start~l + 1: /~ cursordown left ~/
352 cl = costsl + start + ~; /' cursor left ~/
353 dc = costsO + start + 1; /^ destination cursor '/
354 }
3ss 'cd = BIG NUM;
356 for (j = start;l <end; + + j) {
3s7 float down,left,downLeft,rest;
358 rest = SquareDlfference(~alc+ +,b7v)~topToaottom +
SquareDifference('a2c+ +,b2v);
359 down = 'cd + + ~ rest;
360 left = 'cl + + ~ rest;
361 downLeft = 'cdl + + + rest~e.. Le,We, 363 if (down < left) 364 if (down < downLeft) {
365 /~ printf("%6.Zf'',down); 'I
366 ^dc+ + = down 367 ^pc + + = DOWN;
368 }
369 else {
370 /~ prlntf("h6.2f ",downLeft); '/
371 'dc+ ~ = downLeft;
372 'pc+ f = DOWNLEFT;

374 else 375 if (down~eft < left) {
376 /~ printf("%6.2f ",downLeft); ~/
377 'dc + ~ = downLeft;
Copyright~ 1991 Xero~Corporatlon All Rights Reserved -Sectlon C APPENDIX Page 133 3779B ~P' + + = DOWNLEFT: 2 0 7 7 9 6 9 380 else {
381 1~ printf("/'o6.2f",1eht); ~/
382 ~dc + + = left;
383 ~pc + + = LEFT;
384 }
385 }
386 }

388 i--:
389 if (i&l) 390 dc = costst +aLength-l + ~;
391 else 392 dc = costsO+aLength-t + I;
393 returnVal = ~dc;

395 #ifdef foo 396 If (!doPath) 397 y = i;
398 x = aLength-1;
399 while (path[y][xl! = NONE~ {
400 switch (path[yl[x¦) {
401 case DOWN:
402 x--;
403 break;
404 case LEFT:
405 y--;
406 break;
407 case DOWNLEFT:
408 x--;
409 y~-;
410 break;
41 1 default:
412 DoError("NewMatchAndPath: Interna~error-badcase.\n",NULL);
413 }
414 f pri ntf(pathFP, " %d ]/6 d\n " ,x,y);
415 }
416 fprintf(pathFP,"%d %d\n'',x,y);
4~7 4~8 else {}
419 #endif 420 PrintPath(al,a2,aLength,bl,b2,bLength,path,i,returnVal,pathFP);

422 if (le.,.,,Ll.rl ,alize) 423 return returnVal/sclrt(aLength'aLength + bLength~bLength);
424 else 425 return returnVal;
426 }

429 floatSlopeCMatch(float^al,float~a2,intaLength,float'b1,float~b2,intbLength,430 float ~:"~ ,g; ,~,BOOLEAN lengthNormalize,float topToBottom) 432 floatcostsO[MAX SIGNAL_LENGTH+21;
Copyright~ 1991 Xerox~orporation All Rights Resen/ed Sec+lon C APPENDIX, Page 134 33 floatcostsl[MAX SIGNAL LENGTH~21, 434 float costs2[MAX SIGNAL LENGrH + 2];
435 float slope,minVar 436 inti,j; 2V~79~
437 int bottom,top;
438 float~cdlll,'cd211,~cdll2;
439 float ~alc,~a2c,~cd,~cl,~cdl,~dc;
440 float b 1 v,b2v,returnVal;

442 /~ printf("sc:\n"); ~/

444 if(aLength>MAX SIGNAL LENGTHIlbLength>MAX SIGNAL LENGTH) 445 DoError("SlopeCMatch: maxlmum slgnal length exceeded \n",NULL~;

447 slope = (float~aLength~(float)bLength;
448 if((slope>MAX SLOPE~ /slope>MAX_SLOPE)){
449 return BIG _ NUM;
4sO }
4sl 452 for(i =O;i<aLength +2; + + i) {
453 costs2[il = BIG_NUM;
454 costsl[il = BIG_NUM;
455 costsO[il = B~G _ NUM;
456 }
4s7 458 costsO[2] = SquareDifference(~a~,-bl)~topToBottom+SquareDifference(~a2,~b2);459 460 for(i = ~;i<bLength; + + i) {
461 bottom = IMax(i~2,2~i+aLength-2~bLength);
462 top = IMin(2~i,i/2 + aLength-bLength/2) + 1;

464 a I c = a I + bottom; /~ a 1 cu rsor '~
465 a2c = a2 + bottom; /~ a2 cursor ~1 466 blv = ~(b~ + i); /~ bl value ~1 467 b2v = ~(b2 + i); /~ b2 value ''I

469 switch (i%3) {
470 case 0:
471 dc = costsO + bottom-2 + 2;
472 cd211 = costs2 + bottom-2 + 2;
473 cd~12 = costsl +bottom-l +2;
474 cd l l l = costs2 + boKom- l + 2;
475 break;
476 case 1:
477 dc = costsl + bottom-2 + 2;
478 cd211 = costsO + bottom-2 + 2;
479 cd~12 = costs2+bottom-1+2;
4~30 cd 11~ = costsO + bottom-1 + 2;
48~ break;
482 case 2:
483 dc = costs2 + bottom-2 + 2;
484 cd211 = costsl + bottom-2 + 2;
485 cdll2 = costsû+bottom-l +2;
486 cd~ll = costs~ +bottom-l +2;
487 break;
Copyright ~1991 Xerox Corporation All Rlghts Reserved Sectlon C APPENDIX PacJe 135 488 } 2 489 ~dc+ + = BIG NUM; O 7 7 9 69 490 ~dc+ + = 81G NUM;
491 for(j = bottom,l<top; + + j) {
492 ~I oat d211 ,d t 1 2,d 111, rest;
493 rest = SquareDifference(~alc+ +,btY)-topToaottom +
494 SquareDifference~a2c + + ,b2v);
495 dllt = 'cdtll + + + rest^,t"LclvVc~ L, 496 dtl2 = 'cdtl2+ + + rest;
497 d21t = ~cd21t + + + rest;

499 ~dc+ + = FMin(FMin(dtlt,d211),dtl2) 500 }

502 switch (i~03) {
503 case 0:
504 dc = costsO;
SOS break;
506 case 1:
507 dc = costst;
508 break;
SO9 case 2:
S10 dc = costs2;
Sl 1 break;
512 }

514 ~ def foo SlS minVal = alG NUM;
516 printf("%6d: 1');
517 ~or(j=O;j<aLength+2;++j){
518 if (~dc < = minVal) Sl9 minVal = ~dc;
520 if ~dc+ + ~= alG NUM) 521 printf("");
522 else 523 printf~
524 }
525 printf(" %6.2f\n",minVal);
526 #endif 527 }

530 switch (i%3) 531 caseO:
532 dc = costsO;
533 break;
534 case t:
535 dc = costsl;
536 break;
537 case 2:
538 dc = costs2;
539 break;
540 }
541 returnVal = ~(dc +aLength-l + 2);

CopYright ~ t 991 Xerox Corporation All Rlghts Reserved Sectlon C APPENDIX Page 136 543 If ~lengthNormall~e) j44 return returnVai/sqrt(aLength~aLength + bLength~bLength); 2 ~ 7 7 ~ ~ 9545 else 546 return returnVal;
547 }

550 floatSlopeCMatchAndPath(float~al,float~a2,intaLength,floattbl,float~b2,intbLength, 551 float~"~:.\Ve,~l,L,800LEANlengthNorrn7':~,flclattopToBoKom, 552 FILE ~pathFP) 553 {
554 ~irection path[MAX SIGNAL LENGTH][MAX SIGNAL LENGTH¦,~pc;
SSS floatcostsû[MAX SIGNAL LENGTH t21;
556 floatcostsl[MAX SIGNAL LENGTH t21;
557 float costs2[MAX SIGNAL LENGTH ~ 21, 558 floatslope,minVa7 559 int i,j;
560 Int bottom,top;
567 float~cdlll,-cd211,1~cd~12;
562 float ~alc,'a2c,~cd,~cl,~cdl,~dc;
563 floatblv,b2v,returnVal;

565 /t printf("sc:\n"); ~/

567 If(aLength>MAX SIGNAL LENGTHIlbLength>MAX SIGNAL LENGTH) 568 DoError("SlopeCMatch: max~mum slgnal length exceeTed.\n",NULL);

570 slope = (float)aLength/(float)bLength;
571 if ((slope>MAX_SLOPE)¦¦(l/slope>MAX_SLOPE)) {
572 return BIG _ NUM;
573 }

575 for (i = 0;i <aLength + 2; ~ + i) {
576 costs2[i'i = BIG NUM;
577 costsl[il = alG NUM;
578 costsû[il = alG _ NUM;
579 }

581 pc = &(path[~l[01);
582 pc + ~ = NONE;
583 costs0[21 = SquareDifference(~al ,~bl)~topToBottom + SquareDifference(~a2,~b2);

585 for (i = 1; i < bLength ; + + i ) {
586 boUom = IMax(i/2,2^i+aLength-2-bLength);
587 top = IMin(2~i,il2 ~ aLength-bLength/2) ~1 589 alc = al + bottom; /~ al cursor ~/
590 a2c = a2 t bottom; /~ a2 cursor ~/
S91 blv = '(b~ t i); /~ bl value ~/
592 b2v = ~(b2 ~ i); /~ b2 vaiue ~/

594 switch (i%3) S9S caseO:
596 dc = costs0 + bottom-2 + 2;
597 cd211 = costs2 ~ bottom-2 + 2;
Copyright D 1991 Xerox Corporation All Rights Reserved Sectlon C APPENDIX Page 137 598 cdll2 = ~ostsl +bottom-l +2;
600 cd l l 1 = costs2 + bottom- 1 + 2; 2 0 7 7 9 6 9 601 case 1:
602 dc = costsl + bottom-2 + 2;
603 cd211 = costsO + bottom-2 + 2;
604 cd l l 2 = costs2 + bottom- 1+ 2;
605 cd l l l = costsO + bottom- l + 2;
606 break;
607 case 2:
608 dc = costs2 + bottom-2 + 2;
609 cd211 = costsl + bottom-2 + 2:
6 t O cd l 12 = costsO + bottom- l + 2;
611 cdlll = costsl +bottom-l +2;
612 break;
613 }
614 ~dc+ + = 81G NUM;
615 ~dc+ + = 31G NUM;
616 pc = ~(path[i~ottoml);
6 ~ 7 for (j ~ bottom; j < top; + + j) {
618 ~1oatd211,dll2,dlll,rest;

620 rest = SquareDifference(~alc+ +,blv)~topToBottom +
621 SquareDifference~a2c+ +,b2v);
622 dlll = ~cdlll + + + ,.,~-.. L.,W~
623 dll2 = ~cdll2+ + + rest;
624 d211 = ~cd211 + + + rfft;

626 if (dlll <dll2~
627 if(dlll<d211){
628 ~dc+ + = dlll;
629 ~pc+ + = DlLI;
630 }
631 else {
632 ~dc+ + = d211;
633 . ~pc~ + = D2Ll;
634 }
635 else 636 if (dll2<d211) {
637 ~dc+ + = dll2;
638 ~pc+ + = DlL2;

640 else {
641 dc+ + = d211;
642 ~pc+ + = D2LI;
643 }
644 }

646 switch (i%3) {
647 case 0:
648 dc = costsO;
649 break;
650 case 1:
651 dc = costsl;
652 break;
Copyright~ 1991 XeroxCorporation All R~ghts Reserved Section C APPENDIX P~ge 138 j3case 2:
654break; 2 ~ ~ ~ 3 ~ 9 656}
657minVal = BIG NUM;
658printf~"%6d~
659for (j = O;j <aLength + 2; ~ ~ j) {
660if ('dc < = mlnVal) 66~minVa~ = ~dc;
662if(~dc~ + >= BIG NUM) 663printf(""~;
664else 665pri ntf( " " );
666}
667printf(" '06.2f\n" minVal);
668 }

670 j;
677 swltch (i%3) 672 case 0:
673 dc = costsO;
674 break;
675 case 1:
676 dc = costsl;
677 break;
6~8 ~ase 2:
679 dc = costs2;
680 bteak;
681 }
682 returnVal = ~(dc~aLength-~ ~2);

684 PrintPath(al a2 aLength bl b2 bLength path i returnVal pathFP);
68s 686 if (l~ J~ lize) 687 return returnVal/sclrt(aLength~aLength ~ bLength~bLength);
688 else 689 return returnVal;
690 }

Copyright o 199l Xerox Corporation All Rights Resen~ed Sectlon ~ APPENDIX ,' Page 139 Ju131 ~7:141991 s~ngle.c 2~7~9~9 #include <stdio.h>
2 #include"mylib.h"
3 #include"types.h'' 4 #include"dict.h"
S #include"diff h"
6 #include"match.h'' 7 #il~clude"matchparallel.h'' 9 main(argc, argv) 1 û i nt argc;
11 char argv~];
12 t 13 char ~dictFilel,-dictFile2,toutFile;
14 intshapel,shape2;
l S Dictionary dictl ,dict2;
16 floatscore;
17 char matchType;
18 float~e.. lt.We;~.L,normalBandWidth,toproBottom,hillToValleyLocal;
19 DiffDescriptorBodydd;
2û FILE pathFP;

useL2,slopeConstrain,warp,l~.,y~ olll~dl~ topToBottomoption~hillTovalleyopbon;
22 BOOLEAN separate;

24 ~tl~ = 1.0;
,~ , = 20;
26 topToBottom = 1.0;
27 hillToValleyLocal = 1.0;
28 DefArg("%s %d ~s %d %s",''dictl shapel dict2 shape2 outfile",&dictFilel ,&shapel, 29 &dictFile2,&shape2,&outFile);
DefOption("-L2","-L2",&useL2);
31 DefOption("-slopeConstrain %f","-slopeConstrain <centerweight~", 32 &slopeConstrain, ~ We~
33 DefOption("-warp %f /Of","-warp <center weight> <band wldth> ", 34 &warp,&~t.,~ ,&normalBandWidth);
DefOption(''-separate'',"-separate",&separate);
36 DefOption("-normaii2e","-normali2e",5'c ,y~l,r~ ,.al,L~);
37 DefOption(" topToBottom %f " ,"-toproBottom <ratio~",&topToBottomOption,&topToBottom);
38 DefOption("-hillToValley ~cf","-hillToValley <rabo> " ,&hillToValleyOption,&hillToValleyLocal);
39 ScanArgs(argc,argv);
41 dictl = ReadDi~iu"."J'd 'lel);
42 dict2 = ReadDictionary(dictFile2);

44 if ((shape~ > = dictl->numberOfEntries) 11 (shapel < ) (shape2 > = dict2->numberOfEntries) 11 (shape2 < 0)) 46 DoError(" /0 s: bad shape number.\n" ,argvL0]), 4B if ((pathFP = fopen(outFile,"w")) = = NULL~
49 DoError(''single: error opening output file ~'OS ~n'',outFile);
Copyright:D 1991 XeroxCorporatlon All Rights Reserved Sectlon C APPENDIX Page lao O , , ~ .
fprlntffstdout,"Using L2 on length normalized shapes `n''); 2 ~17 7 9 6 9 53 dd.diffType = L2;
54 }
SS else if (slopeConstrain) {
56 f;,",lL~(,ldo,Jt,''Usingdynamlctimewarplngwlthslope~ontrainedto~0.5,21.\n");
57 dd.diffType = ~ONSTRAINED;
58 dd.separate = separate;
S9 i f (separate) fprintf(stdout,"Top and bottom warped separately.\n");
6~ else 62 fprintf~stdout,"Top and bottom warped together.~,n");
63 }
64 else {
fprintf(stdout,''Usingdynamictimewarp~ngwith b~ndwidth %d.\n",normalBandWidth);
66 dd.diffType = WARP;
67 dd.bandWidth = normal8andWidth;
68 dd.separate = separate;
69 if (separate) fprintf(stdout,"Top and bottom warped separately.\n ");
71 else 72 fprintf(stdout,"Top and bottom warped together.\n");
73 }
74 if (!useL2) {
fprintf(stdout,"Centerweight = %f.~n",centerWeight);
76 dd.~e~ llL = cr-"eDt~
77 if'1 ~yLl~t. .lll ,{
78 dd.lengthNormalize = TRUE;
79 fprintf(stdout,"Scores normalized by signal length.~n");
}
81 else 82 dd.l.. ~yll~ alize = FALSE;
83 }
84 dd.hillToValley = hillToValleyLocal;
dd.topro80ttom = topTo30ttom;
86 dd.pathFP = pathFP;
87 fprintf(stdout,"Top to bottom ratio = %6 2f.~n~,toproBottcm);
88 fprintf(stdout,"HilltoValleyratio = %6.2f.~n',hl11ToValleyLocal);

score- DiffPair(-(dil-~outlines+shapel), 91 ~(dict2->outlines + shape2), 92 ~dd);

94 fclose(pathFP);
96 printf("Score = %f~n",score);
97 }
Copyright ~ ~ 991 )<erox Corporation All Rights Reserved Sectlon C APPENDIX Page 14t Jul 23 2~ 241991 slopeMatch.c 2 0 7 7 floatSlopeCo~ t~h~float ~al,float ~a2,intaLength, 2 float ~bt,float ~b2,int bLength, 3 float maxSlope~
4 {
S float costs[MAX SIGNAL LENGTHI[MAX SIGNAL LENGTH~;
6 chardown[MAX SIGNAL LENGTH][MAX SIGNAL LENGTHI;
7 char left[MAX_S~GNAL LENGTH][MAX_SIGNAL LENGTHI;
8 }

Copyright~D 1991 XeroxCorporation All Rights Reserved - -Section C APPENDIX Page 142 ~ul 12 14:36 1991 sortMatrlx.~ 2 0 7 7 9 ~ 9 #include <stdio.h>
2 #include"error.h'' 3 #include''pict.h'' S #define MAX_ENTRIES SûO0 7 typedef struct 8 float score;
g intx;
inty;
11 } 'Comp2reTuple,Compareruple30dy;

13 int TupleLessThan(CompareTuple ~x,Comp2reTuple ~y) 14 {
if((~x)->score = = (~y)->score) ~6 return 0;
17 else if ((~x)->score < (-y) >score) 18 return-1;
19 else return 1 21 }

23 void PrintTuple(CompareTuple a,FlLE ~fp) 24 {
fprintf(fp,"(%d,%d): /Of\n",a->x,a->y,a->score);
26 }

28 void main(int argc,char '^argv) 29 {
Picture pict;
31 Intl,j;
32 int x,y;
33 char ~infile;
34 CompareTup~escores~MAX_ENTRIES];
36 if (argc ! = 2) 37 DoError("Usage: %sinfile.\n",argv[0]);
38 infile ~ argv[11;

pict = load pict(infile);
41 if (pict->wi~th-pict->height > MAX ENTRIES) 42 DoError( " %s: matrix has too manyt enuies.\n " ,argv~01);

44 for(y-O,i=O;y<pict->height; ~ +y) for (x = O;x<pict->width; + + x) {
46 CompareTupletemp;
47 temp = (CompareTuple)calloc(1,sl~eof(CompareTuple30dy)) 48 if (temp = = NULL) 49 DoError(''~6s: cannot allocate space.~n'',argv~01);
S0 temp->score = ~((float~)(pict->data) +x+y~pict->width);
51 temp->x = x;
52 temp->y - y;
Copyright ~199~ Xerox Corporatlon All Rlghts Reserved Se~tlon C APPENDIX Page 143 53 scores[il = temp;
ss }++i; 2~779~9 56 qiort(scores,i,sizeof(CompareTuple),TupleLessThan);
57 for (j = O; j < i; + + j) 58 PrintTuple(scoresljl,stdout);
59 }

, Copyright~1991 XeroxCorporation All Rights Reserved Se~tlon D APPENDIX Page 144 g2617:541991 Makefile 20779S~
CCFLAGS = -9 -c-I/neVpigleVpiglet-~c hopcrofVnewlinclude 3 OFUNS = blobify.o orient.o lines.o ,~ B."~ s.o newMain.o types.o 4 newBlobify.o boxes.o newContour.o numbers.o fontNorm.o \
S dict.o 7 ALPHAOFUNS = orient.o lines.o baselines.o newMain.o types.o\
8 b~obify.o boxes.o newContour.o numbers.o alphaNofm.o \
9 dl.o 1û

12 SOURCES = Makefile baselines.c b~oblfy c boxes.c dict.c dmain.c getAll.c~
13 getOutline.c lines.c newContou~.c newDiff2.c newMaln.c\
14 numbers.co~lent.coverlay.cfontNorm cteslFine.ctypes.c 16 EXTRNS = /neVpigleVpiglet~ uu,,urU~,ù-/e,-u,.o~
17 /n~,,gl~Up;g!~L~ o,u ,urU"~/ plCVpict.o~
18 Ir,~ ,;glet-l~ ou .u~U~ /lists.o 2û INCLUDE = In~J~,;.J~ t,~,.g et lc/hopcrofVnewlincludel 21 M~SC = S(~NCLUDE)misc.h 22 BOOLEAN = S(lNCLUDE)boolean.h 23 LINES = S(lNCLUDE)lines.h 24 LISTS = S(~NCLUDE)lists.h PICT = S(lNCLUDE)pict.h 26 TYPES = S(lNCLUDE)types.h 27 MYL~B = S(lNCLUDE)mylib.h 28 ORIENT = S(lNCLUDE)orient.h 29 BASEL~NES = S(~NCLUDE)baselines.h 3û 8LOBIFY = S(lNCLUDE)blobify.h 31 BOXES = S(~NCLUDE)boxes.h 32 CONTOUR = S(lNCLUDE~newContour.h 33 D~FF = S(lNCLUDE)diff.h 34 DICT = S(lNCLUDE)dict.h ERROR = S(lNCLUDE)error.h 36 FONTNORM = S(lNCLUDE)fontNorm.h 38 orient: S(OFUNS) 39 gccS(OFUNS)S(HOME)/.,~. I;i~l",~llb.alusrllibldebug/malloc.o-lm-oS@

41 newBlobify: newBlobify.o 42 gcc newBlobify.o .. llib/mylib.a -Im -o S@

44 makeAlphabet: S(ALPHAOFUNS) gccS(ALPHAOFUNS)/usr/lib/debuglmalloc o$(EXTRNS)-~m-oS@

47 overlay overlay.o 48 3cc overlay.o S(EXTRNS) -o S@

Sû testFine: testFine.o lines.o guassian.o types.o 51 gcc testFine.o lines.o guassian.o types o S(EXTRNS) -~m -o S@

Copyright~ 1991 XeroxCorporation A~l Rights Reserved SectLon D APPENDIX Page 145 53 boxes: boxes o llnes.o types.o 554S 9Cc boxes.o lines,o types.o $~HOME)/new/lib/mylib.a -Im -o S@ 2 0 ~ ~ ~ 6 9 56 getOutline: dict.o getOutline.o 57 gcc getOutl i ne. o d i ct.o S(EXTR NS) - I m -o S~?

59 getAII: dict.ogetAll.o gcc setAll.o dict.o S(EXTRNS) -Im -o S@

62 maxFilter: maxFilter,o 63 gcc maxFilter.o S(HOME)I"~. 'I;L./",~lib a -lm -o S@

myWc: myWc,o 66 gcc myWc.o S(EXTRNS) -o S~

68 printCode: S(SOURCES) 69 lusr/Sbinlpr -n3 S~SOURCES) ¦ Ipr -PWeeklyWorldNews 71 ,~ 3aiel;.~L;,o~ 3~ .. c S(BOOLEAN) S(PICT) S(TYPES) S(LISTS) S(LINES)\
72 S(BASELINES) 73 gccS(CCFLAGS) newaaselines.c blobify,o: blobify.c S(BOOLEAN) S(PICT) S(BLOBIFY) 76 gcc S(CCFLAGS) blobify.c 78 boxes.o: boxes,c S(BOOLEAN) S(PlcT) S(TYPES) S(BOXES~
79 gcc S(CCFLAGS) boxes.c B1 dict.o: dict.c S(BOOLEAN) S(TYPES) S(ERROR) S(PICT) S(DICT) 82 gcc S(CCFLAGS) dict.c 84 dmain.o: dmain.c S(BOOLEAN) S(PICT) S(DIFF) gcc S(CCFLAGS) dmain.c 87 getAI l .o: getAII ,c 5(300LEAN) S(TYPES) S(PICT) S(DICT) 88 gccS(CCFLAGS) getAll.c getOutline.o: getOutline.c S(BOOLEAN) S(TYPES) S(PICT) S(DICT) 91 gcc S(CCFLAGS) getOutline.c 93 guassian.o: guassian.c 94 gcc S(CCFLAGS) guassian.c 96 lines,o: lines.cS(BO~LEAN)S(PlCT)S(LlNES) 97 gccS(CCFLAGS) lines.c 99 maxFilter.o: maxFilter.cS(MYLiB) 100 gccS(CCFLAGS)maxFilter,c ~02 myWc.o: myWc.cS(BOOLEAN)S(ERROR) 103 gccS(CCFLAGS) myWc.c 105 newBlobify.o: newBlobify.cS(MYLlB)S(BLOBlFY) 106 gccS(CCFLAGS)newBlobi~y.c 10~
Copyright 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX ! Pa~e 1~6 ~t8 newContour.o: newContour.c S(BOOLEAN) S(PICT) S(TYPES) $(LI N ES) \
109 $(LISTS) S(CONTOUR) S(FONTNORM) 0 gcc S(CCFLAGS) newContour.c 2 ~ 7 ~12 newDiff2.o: newDiff2.c S(BOOLEAN) S(TYPES~ 5(Plcn S(DIFF) ~13 gcc$(CCFLAGS) newDiff2.c I ~ S newMain o: newMa~n c $(BOOLEAN) S(PlCT) S(LISTS) S(LINES) \
116 S(ORIENT) S~BASELINES) S(BLOBIFY) S~BOXES) S(CONTOUR) S(ORIENT) 1~ 7 gcc S(C~FLAGS) newMai n.c 119 numbers.o: numbers,c S(BOOLEAN) S(PlcT) S(LINES) 120 gcc $(CCFLAGS) numbers.c ~21 122 orient.o: orient.c S(BOOLEAN) S(TYPES) S(PICT) S(ORIENT) S(LINES) 123 gcc S(CCFLAGS) orient.c 125 overlayo: overlay.cS(BOOLEAN)$(PlCT) 126 gcc S(CCFLAGS) overlay.c 128 postproc.o: postproc.c S(BOOLEAl`i) S(TYPES) S(ERROR) S(PICT) S(DICT) 129 gcc S(CCFLAGS) postproc.c 131 alphaNorm.o:alphaNorm.cS(BOOLEAN)S(TYPES)S(ERROR)S(PlCT)S(DlCT)S(FONTNORM) 132 gcc S(CCFLAGS) alphaNorm,c ~ 34 fontNorm.o: fontNorm.c $(BOOLEAN) $(TYPES) S(ERROR) S(PICT) S(DICT) $(FONTNORM) 135 gcc$(CCFLAGS) fontNorm.c 137 testFine.o: testFine.c 138 gcc S(CCFLAGS) testFine.c 140 types.o: types.cS(TYPES)S(ERROR) 141 gcc S(CCFLAGS) types.c ~42 Copyright 199~ XeroxCorporation All Rlghts Reserved Sectlon D APPENDIX ,' Page 147 Aug 515:451991 alphaNorm.c 207~96~
#include Cstdio.h>
2 #tnclude Cmath.h>
3 #include"boolean.h"
4 #include''types.h'' S #incl ude ''error h "
6 #include''pict.h"
7 #include''dict.h"
8 #include"fontNorm.h"

lo ~ThisfileisjustlikefontNorm.c,butassumesthattheinputisdataforanalphabet dicti onary.
1 l t rhj5 data IS
12 t 13 ta-z tAZ
16 t 17 tû~9 18 t 19 ~ #S%`&-()~ }[I;:I<>?

21 ~ ~-23 ~, The x height will be measured from the x(23). The ascender height will be measured 26 from the 1(11) 29 #defineX HEIGHT SHAPE23 1Ydefi ne ASC_H ElGHr_SHAPE 11 32 extern double cell(double);
33 extern Int Irint(double);

36 #defineUPO
37 #define DOWN 1 38 t~lpedef int Direction extern Picture thePict;

42 void StoreRawOut~inePair(Dictionary dict, int dictEntry, 43 Box box,int bothX,lnt topY, int tbaseY, 44 intnumberOfLegs) 45 {
46 RawOutlinePair temp 47 int i;
48 int ^xCursor,ttopCursor,-bottomCursor;

SO temp = (RawOutline' ' )~llo;(l,sizeof(RawOutlinePair60dy~);
sl if (temp = = NULL) Copyright~ 1991 XeroxCorporation All Rights Reser~ed Sectlon D APPENDIX P~ge 1'18 2 DoError( "StoreRav~OutlinePalr: cannot allocate space~n ' ,NULL);
54 temp->box = box 56 temp->numberOfLegs = numberOfLegs; 2 ~ 7 7 9 57 temp->x = (int ')calloc(temp->numberOfLegs,sizeof(int));
58 temp->top = (int~)calloc(temp->numberOfLegs,si2eof(inl)1, S9 temp->bottom = (int~)calloc(temp->numberOfLegs,sl2eof(int));
If((temp->x = = NULL)¦¦
61 (temp->top = = NULL)¦¦
62 (temp->bottom = = NULL)) 63 DoError("StoreRawOutlinePair: cannot allocate space\n",NULL);

xCursor = temp-~x;
66 topCursor = temp->top;
67 bottomCursor = temp->bottom;

69 for (i = 0:i <numberOfLegs; + + i) {
txCursor + + = ~bothX ~ +;
71 ~topCursor+ + = ttopY + +;
72 ~bottomCursor + + = ~baseY + ~;
73 }
74 ~(dict-~rawOutlinestdictEntry) = temp;
}

77 int RawOutlineWidth(RawOutlinePair a,int middleLine) 78 {
79 int i,numberOfLegs,right,left;
8û int ~topCursor,~bottomCursor;
81 int topValue,bottomValue;

83 numberOfLegs = a-~numberOfLegs;

topCursor = a-~top;
86 bottomCursor = a->bottom;
87 for (i = 0;i <numberOfLegs; + + i) {
88 topValue = ~topCursor+ +;
89 bottomValue = ~bottomCursor ~ +;

91 if (topValue I = HIT THE 80X) {
92 topValue = middleLine-topValue;
93 if (topValue<0) 94 topValue = 0;
}
96 else 97 topValue = 0;

99 If (bottomValue ! = HIT rHE 80X) ~
100 bottomValue = bottomValue-middleLine;
7û~ if (bottomValue < 0) 702 bottomValue = 0;
703 }
7 04 else 705 bottomValue = 0;

Copyright~ 1991 XeroxCorporation All Rights Reserved Section D APPENDIX Page 149 107 If ((bottomY~ ~e ! = O)¦¦~topValue ! = O)) 108 break; 2 0 7 7 9 6 9 110 left=i;
1~1 112 topCursor = a->top + numberOfLegs-1;
~13 bottomCursor = a-~bottom + numberOfLegs-l;
1 14 for ~i = numberOfLegs- 1; i > = 0; --i) {
115 topValue = ~topCursor--;
1 16 bottomValue = ~bottomCursor--;

118 if (topValue ! = HIT rHE_30X) ~
119 topValue = middleLine-topValue;
1 2û i f (topVal ue ~ O) 121 topValue = O;
122 }
1 23 else 124 topValue = O;

126 If(bottomValue!= HIT ,HE 30X)~
127 bottomValue = bottom Val ue - middleLine;
128 if (bottomValue < O) 129 bottomValue = û;
13û }
131 elsebottomValue = O;

133 if ((topValue ! = ~ ' "Value ! = O)) 1 34 break;
135 }
136 right = i + 1;

138 return right-left 139 }
14û
141 YoidResampleOu1' ,~P~.;,(OutlinePa~ra,floatnewroOldFactor) 142 /~ Resample an outline pair using linear interpolation. ~/

144 int newWidth,oldWidth,i;
145 IntoldLeft,oldRight;
146 float oldCenter;
147 float ~newX,~newTop,-n~Y.~
148 float ~xCursor,~topCursor,~bottomCursor;

150 oldWidth = a->numbetOfLegs;
151 newWidth = irint(newToOldFactor~oldWidth);

153 newX = (float~)calloc(newWidth,si2eof(flodt));
154 newTop = (float~)calloc(newWidth,sizeof(float));
SS new30ttom = (float~)calloc(newWidth,sizeof(float));
156 if ((newX = = NULL)¦¦(newTop = = NULL)¦¦(newBottom = = NULL)) 157 DoError("ResdmpleOutlinePair: cannotallocatespace.'n'',NULL);

159 xCursor = newX;
160 topCursor = newTop;
161 bottomCursor = new30ttom;
Copyright 1991 Xerox Corporation All Rights Reserved Sectlon ~ APPENDIX Page 1SO
632 for(i =0;i<newWidth; + + I) {
164 old~enter = i~(float~newWidth~(float)oldWidth; r~ Q
165 oldLeft = irint(floor(oldCenter)); ~ O ( ~ J
166 oldRight = irint(ceil~oldCenter));
167 if(oldLeft= zoldRight){
168 ~xCursor + ~ = ~(a- >x + oldLeh);
169 ~topCursor+ + = ~(a->top+oldLeft);
170 ~bottomCursor+ + = t(a->bottom+oldLeft);
171 }
172 else ~
173 float slope;
174 slope = ~(a->x ~oldRight)-~(a->x +oldLeft);
175 ~xCursor+ + = ~(a->x+oldLeft) ~ (oldCenter-oldLeft)-slope;
176 slope = ~(a->top+oldRight)-~(a->top+oldLeft);
177 ~topCufsorf + = '(a->top+oldLeft) ~ (oldCenter-oldLeft)'slope;
178 slope = ~(a->bottom+oldRight)-~(a->bottom~oldLeft);
179 'bottomCursor+ ~ = ~(a->bottom+oldLeft) + (oldCenter-oldLeft)~slope;
180 }
181 }

183 free~a->x);
184 free(a-~top);
185 free(a->bottom);

187 a->x = newX;
188 a->top = newrop;
189 a->bottom = newBottom;
190 a->numberOfLegs = newWidth;
191 }

193 void StoreOutlinePair(Dictlonarydict, intdictEntry, 194 int mlddleLine,int fontXHelght, 195 int .ls~e~d~ H~;.Jl,t) 196 /~ThisroutinenormalizestherawoutlinepalrstoredindictatdictEntryusingthefollowlng 197 ~ operations:
198 l)Forthetopcontour,shiftsothatthemlddlelineisaty=0andnegatesothatthe 199 ~ higherpointsaregreaterthanO. Forthebottom,shlftsothatmiddlellnelsaty=0, 200 ~ butdon'tflip. Thus,lowerpointshaveycoordlnatesgreaterthan0.
201 '~ ConsiderpointswhosevalueisHlT THE BOXtobeaty=0. Thesecorrespondtogaps 202 ~ between the letters.
203 ~ 2) Compress top and bottom y coordinates by l/fontXHeight so that the coordinates at the 204 ~ distance of the fontXHeight have value 1 Note that 1 is an arbitrary number. It is 205 ~ unlikelythatasignalwillhavepartsthatarethexheightabovethecenterline 206 ~ anyvvay.
207 ~ FOR TOP CONTOUR, 208 t IF HEIGHT IS GREATER THAN XHEIGHT, SCALE DIFFERENCE Br 1 .S/ASCENDER HEIGHT
209 ~ ELSE SCALE DIFFERENCE BY 1/XHEIGHT.
210 ~ FORBOTTOMCONTOUR, 211 ~ SCALE BY l.S/ASCENDER HEIGHT.
212 ~ 3)Compressthexcoordinatesbythesame~actorasinstep2. Notethatthlsdoesnot 213 ~ actually resample the contour. NOW DO THIS WITH RESAMPLE. USE SCALE FACTOR OF
214 ~ 20/XHEIGHT.
215 ~ 4)Removeleftandrightendsofthecontourthathaveyvaluesofzero. Thisissothe Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APP~NDIX Page 151 2~6 ~ contou~ starts where tne word slarts rather than at the edge of its boudlng box 217 t S)ResamplethecontourtostretchbyfirstFontX~i~ /rJ~ idth KILLTHIS
OPERATION 2 ~ 7 7 3 6 9 2t8 1 21g {
220 RawOutlinePair raw;
221 OutlinePairtemp;
222 int i,numberOfLegs;
223 i nt y;
224 int offset;
225 int txSCursor,-topSCursor,tbottomSCursor;
226 float xDCursor,ttopDCursor,tbottomDCursor;
227 f~oat txCursor,ttopCursor,-bottomCursor;
228 int left,right;
229 f~oat foffset;
23û
231 raw = t(dict->rawOutlines~dictEntry);

233 temp = (Ou~ r~a;~ lloc[l,si~eof(OutlinePairBody));
234 if(temp = = NULL) 235 DoError("StoreOutlinePair cannotallocatespace~n',NULL);

237 temp-~x = (float-)calloc(raw->numberOfLegs,si~eof(float));
238 temp->top = (float-)calloc(raw->numberOfLegs,si2eof(float~);
239 temp->bottom = (float )calioc(raw->numberOfLegs,si2eof(float));
240 if t~temP->x = = NULL)¦¦
241 (t~mp->top = = NULL)¦¦
242 (temp->bottom = = NULL)) 243 DoError("StoreOutlinePair cannotallocatespace\n",NULL);

245 temp->box = ~aw->box;
246 temp->blackoutHeight = û;
247 temp->numberOfLegs = raw->numberOfLegs;
248 offset = temp->offset = '(raw->x);
249 temp->width = (raw->x I raw->numberOfLegs-l)-temp->offset;

251 xDCursor = temp->x;
252 topDCursor = temp->top;
253 bottomDCursor = temp->bottom;
254 xSCursor = raw->x;
255 topSCursor = raw->top;
256 bottomSCursor = raw->bottom;

258 numberOfLegs = raw->numberOfLegs 259 for(i=0;i<numberOfLegs;+ li){
260 /~ xDCursor + + = (float)(-xSCursor ~ ~ - offset)/fontXHeight; /
261 if (-topSCursor = = HIT _ THE _ BOX) 252 y=0;
263 topSCursor + +;
264 }
265 else {
266 y = middleLine- topSCursor ~ +;
267 if (y<0) 268 Y=0;
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX P~ge 152 ~70 If(y>fontXHeighV2) 20779~9 271 ~topDCursor+ + = (float~y~l S/ascenderHeight;
272 else 273 ~topDCursor + + = (float)y / fontXHeight;

275 if (~bottomSCursor = = HIT_THE 30X) 276 y=0;
277 bottomSCursor+ +;
278 }
279 else {
280 y = ~bottomSCursor+ + -middleLine;
281 if (y<0) 282 y=0;
283 }
284 i f (y > fontX HeighV2) 285 bottomDCursor+ + = (float)y/fontXHeight;
286 else 287 'bottomDCursor~ + = (float)y~1 S/d,L~,~d~ ,ght;
288 }

290 /~ Now try to remove parts of the contour on to the left and right of the 291 ~wordshapethatareatheightO~/

293 It Find left edge ~/
294 topDCursor = temp >top;
295 bottomDCursor = temp->bonom;
296 for(i=0;i<numberOfLegs;++i){
297 if ((~topDCursor + + ! = 0)~ bottomDCursor + + ! = 0)) 298 break;
299 }
300 ieft = i;

302 /~ Find right edge ~/
303 topDCursor = temp->top+numberOfLegs l;
3 04 bottom DCu rsor = tem p- > bottom + n u m berOf Legs- !;
305 for(i=numberOfLegs-l;i~=0;--i){
306 if ((~topDCursor-- ! = 0)¦¦(~bottomOCursor-- ! = 0)) 307 break;
308 }
309 right = i + 1;
3~0 3 i 1 /~ Clip the ends of the contour at left and right ~/
312 xDCursor = temp->x;
313 topDCursor = temp->top;
314 boUomDCursor = temp->bottom;
315 xCursor = temp->x + left;
316 topCursor = temp-~top I left;
317 bottomCursor = temp- > bottom + left;
3~8 foffset = ~xSCursor;
319 for (i = left;i <right; + + i) {
320 ~xDCursor + + = ~xCursor+ + -foffset;
321 ~topDCursor+ + = ~topCursor+ +;
322 'boUomDCursor+ + = ~bottomCursor+ i;
323 }
Copyright~ 1991 Xerox ~orporation All Rights Reserved Section D APPENDIX Page 153 324 temp->numberOfLegs = right-left;

326 '~dict->outlines+dictEntry) = temp;
327 R^~rleOutlinepair(~(dict- >outlines + dictEntry),~float)20/(float~fontXHeight);
328 }

330 static int li,~ S~
331 Int OrderOutlinePair(OutlinePair 'ol,OutlinePair o2) 333 intyDistance;
334 int xDistance;
335 yDistance = (-ol)->box->pageY-(-o2)->box->pageY;
336 if (yDistance<lineSpacing && yDistance > -lineSpaclng) {
337 xDistance = (-ol)->box->pageX-(~o2)->box->pageX;
338 return xDistance;
339 }
340 return yDistance;
341 }

343 Yold SortDictionary(Dictionary dict) 344 {
345 lineSpacing = 2û;
346 qsort(dict->rawoutlines~dict->numberofEntries~si~eof(Rawoutlinepair)~
347 OrderOutlinePair);
348 }

350 1- WARNI NG - assumes at least on entry is not equal to HIT TH E _ 80X l 351 float MaxTopValue(RawOutlinePair o) 352 {
353 inti;
354 float maxValue;
355 m3xValue = (o->top);
356 for(i=O;i<o->numberOfLegs;+ +i) 357 i~(-(o->top+i)>maxValue&&(-o->top+i)!=HlT THE_~30X) 358 maxValue = ~(o->top+i);
359 return maxValue;
360 }
36~
362 I- WARN I NG - assumes at least on entry is not equal to HIT THE ~30X /
363 float MinTopValue(RawOutlinePair o) 364 {
365 inti;
366 float minValue;
367 minValue = ~(o->top);
368 for(i=û,i<o->numberOfLegs, + +i) 369 if(-(o->top+i)<minvalue&&(~o->top+i)!=HlT THE BOX) 370 minValue = (o->top+i);
371 return m~nValue;
372 }

374 #define HIST SIZE 100 375 void I I ~tcl~la ~ (int data,int dataLength,int offset,int sign,int histogram) 376 {
377 int i,bin;

Copyright ~ l991 Xerox Corporation All Righ~s R~served Ser+~lon D APPENDIX Page 15 ~79 !f (sign>0) {
38i Int maxVaiue; 2 ~ ~ ~ 9 ~ ~
382 maxValue = ~data;
383 for(i=0;i<dataLength;+ +i) 384 if ~data[il! = HIT THE BOX) {
385 maxValu~ -- data 386 break;
387 }
388 for (;i <dataLength; + + i) 389 If (data[i~! = HIT THE BOX && data[il>maxVa~ue) 390 maxValue = data~
391 if(maxValue ! = HIT THE BOX) {
392 bin = maxValue-of~et;
393 if ((bin> = 0)&&(bin< HIST SIZE)) 394 histogram[bin¦ + +;
395 }
396 }
397 else {
398 int minValue;
399 mlnValue = ~data;
400 for (i = 0;i <dataLensth; + + i) 401 if (datali]! = HIT THE BOX) {
402 minValue =~ata[i~
403 break;
404 }
405 for (; i <dataLength; + + i) 406 if (data[il! = HIT THE BOX && data[il<minValue~
407 minVa!ue = data[iT;-408 if (minValue ! = HIT THE 30X) {
409 bin = minValue-of~et;
410 if((bin>=0)&&(bin<HlST SIZE~) 411 !~ uylalll[billl + +;
412 }
413 }

416 void Histogram(int data,inl dataLength, Int offset, int 'histogram) 417 {
418 inti,bin;

420 for (i = 0;i CdataLength; I + i) {
421 if (~data ! = HIT THE BOX) {
422 bin = ~data-of~et;
423 if (lbin > = 0)&&(bin< HIST SIZE)) 4Z4 1 -,Lo ,~, ."r.[L; I 1l + +;

426 data~ +;
427 }
428 }

430 int MaxBin(int ~histogram) 431 {
432 i nt i;
433 int maxVa!ue;
Copyright ~1991 Xerox Corporation All Rights Reserved Sectlon D APPENDIX Page 155 434 Int maxlndex;
435 2~77969 436 maxValue = histogram[0¦;
437 maxlndex = 0;
438 for (i = 0;i ~ HIST_SIZE; + + i) 439 if (hi~uyla~ >maxvalue) {
440 maxValue = h~stogram[i];
441 maxlndex = i;
442 }
443 return maxlndex;
444 }

446 int MaxBinAbove(int ~histogrdm,int line) 447 {
448 Inti;
449 Int maxValue;
450 int maxlndex;
451 Inttop,bottom;

453 for(i=û;i<HlST SIZE;+ +i) 454 If ~histogram[i] r=
455 break;

457 top = i;
458 bottom = (line + top)l2;

46û maxValue = l~ uy~cn~ pl;
461 maxlndex = top;
462 for(i =top;i< =boUom; + +i) 463 if (histogram[i]>maxValue) {
464 maxValue = histogram[il;
465 maxlndex = i:
466 }
467 return maxlndex;
468 }

470 void DrawTextLines(Picture thePict,Dictionany dict,int topLine,int bottomLine) 471 {
472 int maxLength;
473 int halfWidth;
474 int x,y;
475 fioat x2,x3,yi,y3;
476 floatangle;
4~7 478 angle = (~(dict->rawOutlines))->box->angie;
479 maxLength = thePict->width+thePict->helght;
480 halfWidth = thePict->widthl2;
U1 x = topLine ' -sln(angle) + halfWidth ' cos~angle);
482 ~1 = topLine ' cos(ang~e) + halfWidth ' sin(angle);
483 ~2 = x+maxLength-cos(angle);
484 ~12 = y + maxLength~sin(ar 485 ~3 = x-maxLength-cos(anl 486 y3 = y-maxLength~sin(anr 487 DrawLine(thePict,x,y,(int)x~,~.nt)y2,5);
488 DrawLine(thePict,x,y,(int)x3,(int)y3,5);
Copyright ~ 1991 Xerox Corporation All Rights Reserved Sertion D APPENDIX Page 156 ~39 490 x = bottomLlne~-sin(angle) + halfWidth~cos~ang~e~;
491 y = bottomLine ~ cos~angie) + halfWidth ' sln(angle);
492 x2 = x + maxLength~cos(angle);
493 y2 = y + maxLength~sin(angle); 2 Q ~ 7 9 6 9 494 x3 = x-maxLength-cos(angle);
495 y3 = y-maxLength~sin(angle);
496 DrawLine(thePict,x,y,(int)x2,(int)y2,5);
497 DrawLine(thePict,x,y,(int)x3,(int~y3,~);
498 }

sao void PageStatistics(Dictionary dict,char ~fileName) 501 /~ WARNING - this must be run befo-e PostProcess since PostProcess changes the raw 502 shape data, ~/
503 {
so4 int index;
505 inttemp;
506 int i,startlndex,firstY,minY,endlndex,shape;
s07 inttops[HlST SIZEI;
508 int bottoms[HIST SIZEI;
509 intascenders[HlS~ SIZE];
510 intdescenders[HlST SIZEI;
Sl l int middleLine,top~ine,bottomLine,ascenderLine,descenderLine;
512 int~el~d-~He~ d~ d~H~ lineNumber;
513 int fontXHeight,fontXWidth,xlndex;
514 RawOutlinePairthisShape;
S I S FILE ~fp;
516 BOOLEANII.. ~_';,,LFo,,~XWidth = FALSE;
sl7 intfirstFontXWidth;

sl9 if ((fp = fopen(fileName,"w'')) = = NULL) 520 DoError("PageStatistics: error openlng output file %s.\n'',fileName);

522 SortDictionary(dict);

524 index = 0;
525 lineNumber = 0;
526 while (index < dict- >numberOfEntries) {
527 startlndex = index;
s28 firstY = (~(dict-~rawOutlines~index))->box->pageY;
529 minY = firstY;
530 while((~(dict->rawOutlines+index))->box~>pageY-firsty < 20&&
531 (-(dict->rawOutlines + index))->box->pageY - firstY > -20) {
532 if(miny>((~(dict >rawOutlines+index))->box->pageY)) 533 minY = ('(dict->rawOutlines+index))->box->pageY;
s34 + +index;
535 if(index = = dict->numberOfEntries) 536 break;
537 }
538 endlndex = index;

541 1~ shapes from start index through endindex are all on 542 1- the same text line ~1 543 /- minY has the top of the highest box on the line. ~1 Copyright ~ 1991 Xerox Corporation All Rights Reserved Sectlon D APPENDIX Page 157 544 2ort~969 545 /" Find the base and toplines by taking the mode of the heights of the 546 ''valleysofthebottomcontoursandthepeaksofthetopcontours-l 547 for(i=0;i<H~ST SlZE;i+ +){
548 bottoms[il = 0;
549 }

551 for(shape=startlnd~x;shape<endlndex; + +shape){
552 thisShape = ~(dict-~rawOut~ines+shape);
553 Histogram(thisShape-~bottom,thisShape-~numberOfLegs,minY,bottoms);
554 }
SSS bottomLine = MaxBin(bottoms) + minY;
SSb if(X HEIGHT _ SHAPE~=startlndex&&X HE~GHT SHAPE<endlndex){
557 top~ne = MinTopValue(-(dict-~rawOut~nes + X=EIGHT SHAPE));
558 fontXHeight = bottom Ll ne - topLi ne;
559 }
560 if(ASC HEIGHT SHAPE~=startlndex&&ASC HEIGHT SHAPE<endlndex){
561 ascenderLine = MinTopValue~(dict->rawOul~nes+ASC_HEIGHT_SHAPE));
562 d~elld~ = bottomLine-ascenderLine;
563 }
564 middleLine = bottomLlne-fontXHeightl2;
565 topLine = bottomLlne-fontXHeight;

567 if (thePict) 568 DrawTextLines(thePict,dict,topLine,bottomLine);

571 fprintf(fp,''%d: %d %d %2 6f~n~ ineNumber~fontxHeight~ds~ ,l ' He: ~I,L, 572 (~I~,aL)ascend~.He:~l,L/(float)fontXHeight);

574 for(shape=,L~,Ll"d~A"l,ap~<endlndex;+ +shape) 575 StoreOut~inePair(dict~sh~r~ dl~ e~fontxHeight~as~e"d-~ He~ L);

577 + +lineNumber;
578 } /~ Do another line of text ~/
579 fclose(fp);
580 }

Copyright~ t991 XeroxCorporatlon All Rights Reser\~ed Se~tlon D APPENDIX Page 158 21 19:50199~ basellnesc 2077g~9 #include <stdio.h>
2 #include <values.h>
3 #include <math.h>
4 #include"boolean.h'' S #include"pict.h"
6 #include"types.h'' 7 #include"lists.h"
8 #include"lines.h"
9 #include''baselines.h"
1~ extern double sqrt(double):
12 extern Int irintldouble);

14 /^inline^/ int NewReadPixel(UCHAR 'base,int w/dth,float x,float y~
{
16 intxi;
17 intyi; .
18 UCHARmask;
~9 xi = irint(x);
2~ yi = irint(y);
22 mask = Ox80 > > (xi & Ox7);
23 return ~(base + yi~width + (xi > >3)) & mask;
24 }
26 voidNewCountLine~Bit(Picturepict,intxl,intyl,intx2,inty2,int^black,int^blackEdge~
27 {
28 float x,y;
29 float xinc,yinc;
float xupinc,yupinc;
31 floatden;
32 int b,be;
33 int width,ucharWidth,height;
34 UCHAR ~data;
36 width = pict->width;
37 ucharWidth = pict->uchar_width;
38 height = pict->height;
39 data = pict->data;
4~ den = sc1rt((y2-y~)^(y2-yl) + (x2-x~)^(x2-x~));
42 xinc = (x2-xl)lden;
43 yinc = (y2-yl)/den;
44 xupinc = -yinc;
yupinc = ~inc:
46 x = xl;
47 y = yl;

49 b=0;
be = 0;

52 while (x <width&&x > = O&&y< height&&y > = 0) {
Copyright'3 199~ XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 159 54 if (NewReadpixel(ddta ucha~widthlxly)) { 2 0 7 7 9 6 if (!(NewReadFiA ~dAtA JcharWidth,x + xuplnc,y + yupinc) &&
56 ~ iAe (data,ucharWidth,x-xuplnc,y-yupinc~)) 57 + +be;
58 }
59 x + = xinc;
y + = yinc;

62 }
63 Iblack = b;
64 ~blackEdge = be;
}

68 #define MIN BLACK 5 69 floatNewCountLIne(Picturepict,intxl,lntyl,lntx2,inty2 {
7t inth ~ck hlafkFf'fJfr;
72 black = 0;
73 blackEdge = O;
74 NewCountLinel3it(pict,x1,y1,x2,y2,&black,A,hlackFrlfJ-);
NewCountLinelBit(pict,x1,y1,x1.(x2-x1),y~-(y2-y1),~h ~ck~8Ll~ckFfl~AJ~) 76 if (black < MIN_BLACK~
77 return 0;
78 else 79 return(floot)h'? ~F~Ig~/L~ld.l;
}

82 static float x20ffset;
83 static float y20ffset;
84 staticintp,U,~ d~A;
static float ~projection;
86 static int coordx;
87 static int ~coordy;
88 BOOLEAN 8aseLinePiston(Picture pict, Int x, int y, BOOLEAN test, UCHAR color) if (test~ {
91 /~ if(!(~ d~A~olO)) 92 DrawLine(~`ict,x,y,(int)(x + x20ffset),(int)~y + y20ffset),0xffl; ~1 93 /~ WritePixe~(pict,x,y,Oxffl; ~1 94 projectionll.,u~ ,J~Al = NewCountLine(pict,x,y,(int)(x+x20ffset), (int)(y + y20ffset~);
96 .cu-JA[~,.o,e~ll,. 1.~1 = x;
97 cc,u-ùy[,u-o,~ ~d~A+ +l = Y;
98 return test;
99 ~ e!se 100 return test;
101 }

103 static int lastX;
104 static int lastY;
105 EOOLEAN ~nd~ui. ,lristo,~(Picture pict, int x, int y, BOOLEAN test, UCHAR color) 1û6 Copyright0 1991 Xerox Corporation Al I Rl ghts Reserved Section D APPENDIX, P~ge 160 ~7 If (test) {
108 lastX = x;
~L~9 lastY = y;
llo } ~977~9 1~1 return test;
~12 }

114 void EndPoints~Picture pict,double angle,int ~tx, int 'ty,int ~bx, int ~by) 115 {
116 int xc,yc;
~17 int maxLength;
118 floatnormal;
119 float x2,y2,x3,y3;
12û
121 ~ Make normal to text point in quadrants I and 11~/
122 /~ Assume 0 ~ = angle C 2~M Pl ~/
~23 normal = fmod(angle f M Pr2,2~M Pl);
124 if (normal ~ M_Pl) 125 normal-= M _ Pl;

127 xc = pict->width/2;
128 yc = pict-~heighU2;

130 maxLength = pict->width+pict->helght;
131 x2 = xc + maxLength~cos(normal); /~ At bottom of picture 'I
132 y2 = yc I maxL.~ Ll,',i,~(nu.".al);
133 x3 = xc-maxLength-cos(normal); /~Attopofpicture~l 134 y3 = yc-maxLength~sin(normal);

136 LineEngine(pict,xc,yc,(int)x2,(int)y2,0,EndPointPiston);
137 ~bx = lastX;
~38 ~by = lastY;
~39 LlneEngine(pict,xc,yc,(int)x3,(int)y3,0,EndPolntPiston);
140 'tx = lastX;
41 ~ty = lastY;
142 }

~44 doubledistance(intxl,intyl,intx2,inty2) ~45 {
~46 return sqrt((double)((xl-x2)~(xl-x2) + ~y~ -y2)-~yl-y2)));
~47 ~48 149 #defineBASE PERCENTlLEû.20 150 #defineMlN LINE HEIGHT FRACTION0 50 15~ ListBaseLinesTPicturepict,dou~;ieangie,char~plotFile) 152 #ifdef foo 153 ,int ~count, 154 int ~returnCoordx, int '~returnCoordy) lSS #endif 156 {
1 s7 float ~topProjection;
158 int ~topCoordx,~topCoordy;
~S9 int 'finalCoordx,~finalCoordy,~finallndex, 160 inttoplndex,buLlu,l,~;ieA, 16~ inttopCount,botCount,finalCount;
Copyright0 1991 XeroxCorporation All Rlghts Reserved Sectlon D APPENDIX . Page 161 162 int maxLength; 2 ~ ~ 7 9 6 9 163 in~ xc,yc;
164 float x2,y2,x3,y3;
165 floatmaxValue,lastValue;
166 inti,j;
t67 float b2seThresh;
168 inttopx~topy~h~ottorlly~hottnr~A~y;
169 BOOLEAN onTextLine 1 7û List xList,yList,result;
171 doubletotalDistance,averageDistance;
172 FILE ~outfile;

174 printf("dngle = %3.3f~n",angle~;

176 maxLength = pict-~width+pict->helght;

178 topProjection = ~float~)calloc~maxLength,sizeof(float));
179 topCoordx = (int~)calloc(maxLength,sizeof(int));
18û topCoordy = (int ~)calloc(maxLength,slzeof(int));
181 finalCoordx = (int~)calloc(maxLength,slzeof(int));
182 finalCoordy = ~int~)calloc~maxLength,sizeof(int));
183 finallndex = (int~)calloc~maxLength,slzeof~int));

185 if ((Lu~ ion = = NULL)¦¦
186 (topCoordx = = NULL)¦
187 (topCoordy = = NULL)¦
188 ~finallndex = = NULL)¦
189 (finalCoordx = = NULLI¦¦
190 (finalCoordy = = NULLI){
191 printf~"BaseLines: cannot allocate memory~n");
192 exi t(- 1 );
193 }

l9S EndPoints~pict,angle,&topX,&topY,&bottomX,&bottomY);

197 printf("Main Line: (%d,%d)-~%d,%d)~n'',topX,topV,bottomX,bottomY);
198 /- DrawLine~pict,topX,topY,bottomX,bottomY,Oxffl; ~/

2û0 x20ffset = maxLength~cos(angle);
201 y20ffset = maxLength~sin(angle);
2û2 r,~ d~A = ;
203 projection = ~c"~r~ lR.";
2û4 coordx = topCoordx;
205 coordy = topCoordy;
206 Li.~C~,y;~(p;.t,topX,topY,bottomX,bottomY,û,8aseLinePiston);
2û7 topCount = ~o;e~l.,u~A, 2û9 maxValue = topProjection[0];
210 for(i=0;i~topCount;+ +i){
211 if (topr~ lion[;]>maxValue) 212 maxValue = to,oPIu,e~iu--[i];
213 }

215 baseThresh = maxValue~8ASE PERCENTILE:
216 printf("baseThresh = %3.3f~n",baserhresh);
Copyright 1991 XeroxCorporation All Rights Reserved Section D APPENOIX . Page 162 ~t7 218 /~ Plot the baseline contour If requested / 2 ~ 7 ~ ~ v~ 9 219 if (plotfile! = NULL~ {
22û printf("Openlng baselines plot file\n ');
221 if ((outfile = fopen(plotFile,"w")) = = NULL) {
222 printf("Error opening baseline plot file.~n");
223 exit(-1);
224 }
225 for (i = 0;i <topCount; + + i) 226 fprintf(outfile,"%d /0f\n",i,topProjection[il);
227 fprintf(outfile,"~''P.v,~Liv.. \.~\n");
228 fprintf(outfile, 229 '' 0 Ai f\n~fi d % f%\n~" Basel i ne Threshold\n ", 230 baseThresh,topCount,baseThresh);
231 }

233 finalCount = 0;
234 lastValue = topProjection[topCount~
235 onTextLine = FALSE;
236 for ~i = 1; i c topCou nt; + + i ) {
237 if (onTextLine) {
238 If(lastValue>baseThresh&&topProjection[i~c =baseThresh){
239 finalCoordx[finalCountl = topCoordxli];
240 finalCoordy[finalCount~ = topCoordy~i];
241 finallndex[finalCountl = i;
242 finaiCount+ +;
243 onTextLine = FALSE;
244 }
245 } else 1 246 If(lastValueC=baseThresh&&~u;~rlv, ~iv"[il>baseThresh~{
247 finalCoordx[finalCountl = topCoordx[il;
248 finalCoordy[finalCountl = topCoordy[il;
249 fina~lndex[finalCountl = i;
2s0 finalCount+ +;
251 onTextLine = TRUE;
252 }
253 }

255 lastValue = ~vpr~ ivl~[;l;
256 }
257 if (finalCount&1) 2s8 --hnalCount; /- Only take an even number of llnes '/
259 for(totalDistance=0,i=0,j=0;icfinalCount;l+=2){
260 topX = finalCoordxli];
261 topY = finalCoordyli];
262 bottomX = finalCoordx[i + ~];
263 bottomY = finalCoordy[i + I];
26~L totalDistance + = distance(topX,topY,bottomX,bottomY);
265 j ~ = 2;
266 }
267 ~verageDistance = totalDistancel(finalCounV2)'MlN ~INE HEIGHT_FRACTICIN;
268 for(i=0,j=0;icfinalCount;i+=2){
269 topX = finalCoordx[il;
270 topY = finalCoordy[il;
27~ toplndex = finallndex[i1;
Copyrlght ~1991 Xerox Corporation All Rights Reserved Sectlon D APPENDIX Page 163 272 oottomX = finalCoordx~ ; 2 0 ~ ~ 9 6 9 273 bottomY = finalCoordyli t ~
274 i~ oml"ueA = finallndexli + 11;
275 finalCoordx j] = ~opX;
276 finalCoordy jl = tPY:
2~ finallndexlj' = toplndex;
2~8 finalCoordx'j t 11 = bottomX;
2~9 finaiCoordyj~11 = bottomY;
280 Finallndex[j + 11 = L~J~Lull.llld~A, 281 If (d;~ e(Lu,~x~topy~bottomx~bottomy)>averageDistznce) 282 j ~ = 2;
283 }
284 #ifdef foo 285 ~count = j;
286 ~returnCoordx = finalCoordx;
28~ ~returnCoordy = finalCoordy;
Z88 #endif 289 result = nil;
290 for(i = j-l;i> =û;--i) {
291 push(MakePoint(fina~Coordxli],finalCoordy[ll),result);
292 }

294 iF (piotFile ! = NULL~ {
295 fprintf(outfile,"\nO %f\n",-baserhresh);
296 for(i =û;i<j;i ~ =2) {
297 fprintf(outfile,"%d %f~n%d %f\n%d %f\n%d %f\n", 298 finallndex il,-baseThresh, 299 finallndex il,-2~baseThresh, 3ûO finallndex i + 11,-2~baseThresh, 301 finallndex i + Il,-baseThresh);
302 }
3û3 fprintf(outfile,"\"Baselines");
3û4 fclose(outfile);
305 prlntf("Donewritingbaselineplotfile.~n'');
306 }
30~
3û8 return result;
3û9 }
31û
311 void DrawBaseLines(Picture pict, List point~ist, double angle) 312 #ifdef foo 313 intcount,int^coordx,int~coordy,doubleang~e) 314 #endif 315 {
316 i nt maxLength;
317 float x2,y2,x3,y3;
318 ~nt x,y;
319 Polnttemp;
32û maxLength = pict->width ~ pict->height;
321 whlle (lendp(pointList)) {
322 temp = pop(pointList);
323 x = temp->x;
324 y = temp->y;
325 x2 = x ~ maxLength ~cos(angle);
326 y2 = y~maxLength~sin(angle);
Copyright ~1991 Xerox Corporation All Rights Reserved Section D APPENDIX, Pa-~e 16d, ~27 x3 = x-maxLength~os(angle~:
328 y3 = y-maxLength~sin(angle);
329 DrawLine(pict,x,y,(int)x2,(int)y2,0xffl; 2 ~ 7 330 3rawLine(pict~xly~(int~x3~(int)y3~oxffl;
33t }
332 }

Copyright9 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX ,' Page 165 Jul ~ 13:441991 bloblfy.c 2 0 7 ~ 9 6 9 #include <stdio.h>
2 #include <math.h>
3 #include"boolean.h"
4 #include "pict.h'' #include"blobify.h"

7 staticUCHARbitmasks[] = {0x80,0x40,ûx20,0x1û,0x8,ûx4,0x2,0x1};

9 Picture 810bify(Picture old,int half mask size,double threshold) {
11 Picture new;
~ 2 i nt x,y;
13 inttval;
14 int left,right,top,bottom;
intwidth;
16 int ^counters;
17 int tcountptr;
18 intmask size;
19 UCHAR xptr,'xyptr;
int tleftptr;
21 int trightptr;
22 UCHAR ^topptr;
23 UCHAR ~bottomptr;
24 int uchar width /t UCHAR~itmask;'l 26 intcount;
27 int inside;
28 i nt thold;
29 /t Added the following forspeedup hack 1/14/91 t/
UCHAR bltMask;
31 UCHAR newCursor;
32 UCHAR newValue;
33 UCHAR topPixels;
34 UCHARbottomPixels;

37 mask size = 2 ' half mask size + 1;
38 /t uchar width = ROUND8(old->width) > > 3; ~/
39 uchar width = old->uchar width;
-- _ 41 left = half _ mask size;
42 right = old->widT- half_mask_size - 1;

44 top = half mask size;
bottom = old->helght-half_mask_size-~;

48 tval = floor(4~half mask sizethalf mask size-threshold) 49 new = new pict(oTd->w~th,old->~eight,old->depth);

51 counters = (intt)calloc(old->width,sizeof(int));

Copyright ~ 1991 Xerox Corporation All Rlghts Reserved Sec+ion D APPENDIX Pa~e 166 53 width = old->wldth;
54 countpt~ = counters;
xptr = old->data;
56 bitMask = Ox80;
57 for (x = O; x < width; + + x) { 2 ~ 7 7 58 1' bitmask = bitmasks[x%81; '/
59 xyptr = xptr;
for ~count = 0 y = O;y<mask si2e; ~ + y) {
61 If (-xyptr & bltMask) 62 + +count;
63 xyptr + = uchar _ width;
64 }
~cou ntptr + + ~ = count;
66 ~ if (x,68 = = 7) 67 ' + + xptr; ~/
68 if(bitMask = = OxO~){
69 bitMask = Ox80;
7û + + xptr;
71 }
72 else 73 bitMask = bitMask >> 1;

76 for (y = top;y~ = bottom; + + y) {
77 countptr = counters;
78 for (inside = 0,x = O;xCmask _ size; + + x) 79 inside + = 'countptr+ +;
81 leftptr = counters;
82 rightptr = counters + mask size;
83 newCursor = new->data + y~uchar_vvidth + (left> >3);
84 bitMask = bitmasks[left%81;
newValue = 0;
86 fo~ (x = left;x c = right; + + x) {
87 if (inside>tval) 88 /' set pixel '/
89 newValue ¦ = bitMask 90 /~ ~(new->data+y~uchar width+(x>>3))¦= bitmaskslx%81;~/
91 if(bitMask = = ûxO1~{
92 bitMask = Ox8û;
93 'n~wCursor + + = newValue;
94 newValue = 0;
96 else 97 bitMask = bitMask > > l;
98 inside + = 'rightptr+ +;
99 inside - = 'leftptr + +;
100 }
101 if ~bitMask I = Ox80) {
102 'newCursor = newValue;
lû3 }

105 topptr = old->data+(y-half mask si~e)'uchar_width;
106 bottomptr = topptr + mask size~uchar width;
107 countptr = counters;
Copyright01991 XeroxCorporation All Rights Reserved Sectio n D APPEN DIX, Pag e 167 108 bltMask = OxO1 109 for(x=O;x<wicith;++x){ 2~7rlg6g 110 1~ bltmask = bitmaskslx%81; 'I
111 if(bitMask = = OxOI){
112 topPixels = 'topptr+ +;
113 bottomPixels= ^bottomptr+ +;
1 ~ 4 bitMask = Ox80;
115 }
1 16 else 1 17 bitMask = bitMask > > 1;
118 if (topPixels & bitMask) {
119 if (!(bottc,."~ l, b bitMask~
1 20 --('countptr);
121 }
122 elseif(b~,lL.,"-F;~_l,&bitMask~
123 + +('countptr~;

125 + ~countptr;
126 }
127 }

129 return new;
130 }

132 #ifdef foo 133 void main(argc,argv~
134 ir1targc;
135 char ''argv;

137 char'infile,'outfile;
138 Picture old,new;
139 inthalf mask size;
140 float threshold, 14t 142 malloc _ debug(2);

144 if (argc I = S) {
145 printf("Usage: %sinfileoutfilehalf mask sizethreshold\n",argv[01);
146 exit(0);
147 }
148 infile = argv[ll;
149 outfiie = 2rgv[2l;
150 llalf m~sk si~ toi(argv[31);
151 thre~Fiold = atof-~rgv~41);

153 I~rintf(''Loading%s.. '',infile);
154 old = load pict(infile);
155 new = CO~pC"1~,. ' ' I,half mask _ size,thresho~d);
156 write _ pict(outfile,new);

tS8 }
1 59 #endif Copyright 1 ~erox Corporation All Rights Resi Section D APPENDIX Page 168 Aug26 18:1û 1991 boxes.c 2~779~9 #include <stdio.h>
2 #includ~ <valuff.h>
3 #i ncl ude ~ math . h >
4 #include''boolean.h"
s #include"pict.h"
6 #include"types.h"
7 #include"lists.h'' 9 extern int irint(double);
11 #defineMAX QUEUE SIZE 10000 12 #defi ne BLACK 1 13 #define WHITE 0 #defineA85(a)((a)<0?-(d):(a)) ~6 17 typedef Point PointArray;

t9 typedef struct {
PointBody ulc,lrc;
21 } ~ ~r 1~YR~y 23 typedef struct {
24 Point30dy xwitness,yvvitness;
} Witness80x;

27 typedef struct {
28 PointArray data;
29 int first,last;
intsize;
31 } QueueBody,~Queue;

33 Queue MakeQueue(size) 34 intsize;
{
36 Queue q;
37 if ((q = (Que~J~)ralloc(l~sizeof(QueueBody))) = = NULL) {
38 pri ntf(" Cannot alloc space for queue bod y\n " );
39 exit(0);
}
41 if((q->data=(PolntA.-_,` " c(ci~e~ of(pointBody)))= = NULL){
42 printf("Cannotallocatespaceforqueuea~ray~n");
43 eYit(0);
44 }
q- > first = q- > last = 0;
46 q->size=size;
47 return q;
48 }

void InsertPoint(x,y,q) 51 int x,y;
52 Queue q;
Copyright~ 1991 XeroxCorporation All Rights Reserved Section D APPENDIX Page 169 53 ~ 2û7'~96~ ~
54 q~>data[q->last].x = x;
q->data[q->lastl.y=y;
56 q->last = (q->last + 1)%q->size;
57 if(q->last= =q->first){
58 printf~"Maximum q size exceeded\n''~;
S9 exit(0);
}
61 }

63 void GetFirst(x,y,q) 64 int ~x,-y;
Queue q;
66 {
67 if(q->first= =q->last){
68 prl ntf ( " Error: tri ed top pop em pty qu eue~n " );
69 exit(0):
}
71 `'x = q->data[q->firstl.x;
72 ~y=q->data[q->firstl.y;
73 q->first = (q->first + 1)%q->size;
74 }
76 800LEAN Empty(q) 77 alueue q;
78 {
79 return q->fi-st= = q->last;
}

82 void InsertP' !~ ,. ,(rlctur~ pict,int x,int y,Queue queue) 83 {
84 i f (RedCIriA~. (?ict,x + 1 ,y)) {
\lUIit~iA_:;piCt,x+ I,y,WHlTE);
86 InsertPoi nt(x + t ,y,queue);
87 ~
88 if (ReadPixel(pict,x-1,y)) {
89 WritePixel(pict,x-1,y,WHlTE);
InsertPoint(x-l,y,queue);
gl }
92 i f (ReadPixel(pict,x,y + I )) {
93 ~',it~r; I¦, rt,Y,y+1,WHlTE);
94 1. ,~. ~P~.;. .`~ ,y + 1 ,queue);
}
96 if (".~ ' . '(, t,Y.y-l)) ~
97 ~ ";;t,x,y-1,WHlTE);
98 InsertPoint~x,y-1,queue);
99 }
100 }

102 void PointFromTheta(theta,x,y) 103 f~oat th~ta;
104 f~oat ~x,~y;
105 {
106 ~x = cos(theta);
107 ~y = sin(theta);
Copyright 1991 XeroxCorporation All Rights Reserved Section D APPENDIX Page '70 08 }
~09 0 void Normal(x,y,nx,ny) 2 ~ 7 7 ~ 6 9 ~12 float ~nx,~ny;
113 {
1 14 nx = -y;
115 ~ny = x;
116 }
~ ~ 7 11 8 i nt DotFl(fx, fy,ix,iy) ~19 float fx,fy;
120 intix,iy;
121 {
122 return irint(fx~ix ~ fy~iy);
123 }

125 static float pox,poy,pnx,pny;

127 voidMinMax(boundingBox,oldFrame30x,px,py) 128 MinMaxBox ~boundingBox;
129 WitnessBox ~oldFrameBox;
13û int px,py;
13~ {
132 /~ IGNORE THETA fOR THE TIME 3EING /
133 if (boundingBox->lrc.x < DotFl(pox,poy,px.py)) {
134 boundingBox->lrc.x = DotFl(pox,poy,px,py);
~35 }
~36 if (boundingBox-~lrc.y < DotFi(pnx,pny,px,py)) 137 boundingBox->lrc.y = DotFl(pnx,pny,px,py);
138 }
139 if (boundingBox->ulc.x > DotFl(pox,poy,px,py)) {
140 boundingBox->ulc.x s DotFl(pox,poy,px,py);
14~ oldr, ^ >xwitness.x = px;
142 oldr,~,neC~,A >xwitness.y = py;
143 }
144 if (bOU~ )9C ~A->UIC.Y > DotFl(pnx,pny,px,py)) {
145 bounding80x->ulc.y = DotFl(pnx,pny,px,py);
146 oldr,~,neCoA->ywitness.x = px;
147 oldr. -rr, ~oA->ywitness.y = py;
~48 }
~49 }
~50 ~S~ /~SetthepixelsontheborderoftheimagetothecolorWHlTEsothat 152 ~ the paint routine need never worry about going off the edge of the 153 ^~ image. ~1 154 void FramePicture(pict) 155 Picture pict;
~56 {
157 int i;
158 for (i s O;i Cpict->height; + I i) {
S9 WritePixel(pict,O,i,WHlTE);
~60 WritePixel(pict,pict->width-~,i,WH~TE);
~6~ }
162 for(i=O;i<pict->width; I ~i){
Copyright ~ 1991 Xerox Corporation A~l Rights Reserved Section D APPENDIX Page 171 163 WritePIxel(plct,i,0,WHlTE~; 7 g 6 164 WrltePixel(plct,i,pict->height-l,WHlTE), 2 0 7 i65 }
166 }

1 68 /' 169 'Givenasinputall,~ ldc~image,findthebordersoftheconnected 170 ~ pon~ ,. Assumes imag~ is thresholded to O and 1.

172 void PaintComponent~pict,x,y,queue,boundingBox,ol.lr,~
173 Picture pict;
174 int x,y;
175 Queue queue;
176 MinMaxBox ~bounding80x;
177 Witness8Ox~oR~r,a,n~3Ox;
~78 179 boundingBox->ulc.x = boundingBox-~lrc.x = DotFl(pox,poy,x,y);
18û boundingBox->ul~.y = boundingBox- >Irc y = DotFl(pnx,pny,x,y);
181 oldFrame80x->xwitness.x = oldFrame80x->ywitness.x = x;
182 old,.dm_~oA->xwitness.y = oldFrameBox->ywitness.y = y;

184 InsertPoint(x,y,queue);
185 ~,it~r; '~, t,Y y,WHITE);
186 1- p~intf(''Queuestatus: q~s\n",(Empty(queue))?"empty'':"notempty"); '/
187 while(lEmpty(queue)){
188 GetFirst(&x,&y,queue);
189 ~ rr~y(ho~ ding8ox~oldF~ UoA,x,y);
190 InsertP~7ck'' ',',i.~",(pict,x,y,qu~ue);
191 }
192 }

194 i nt iabs(int x) 196 if (x<0) 197 return-x;
1 98 else 199 return x;
200 }

202 BOOLEAN P~ 1"3OJl.;rlcture pict,int x,int y) 203 {
204 return x> s O &IL x~pict->width && y> = û li~L y<pict->height;
205 }

2û7 208 BOOLEAN3~ ,ûvY~d,~ Lurepict,intx,inty,intwidth,inth~ight, 209 double angle) 211 int rightX,rightY,downX,downY;
212 rightX = width'cos(angle);
213 rightY = width'sin(angie);
214 downX = height'cos(angle+M P~/2);
215 downY = height~sin(dngle+M Pl/2);
216 return (PointlnBounds(pict,x,y) i~Y
217 PointlnBounds(pict,x + rightX,y + rightV) &&
~opyright 1991 XeroxCorpordtion All Rights Reserved Section D APPENDIX ! Page 172 218 PolntlnBounds(pict,x + rlghtX + downX,y + rlghtY + downY~ &&
219 PointlnBounds~pict,x + downX,y + downY));
220 }
2222 void GetCorner(Witness30x 'box,int 'ulcx,int ~ulcy) 2 0 7 r~ 9 ~j 9 223 {
224 double c2;
225 c2 = (-pny'(box->ywitness.x-box->xwitnffs,x) +
226 pnx~(box->ywitness.y-box->xwitness.y) )I
227 (pox'pny - pnx'poy);
228 ulcx = c2'pox+box->ywitness.x;
229 'ulcy = ~2'poy + box->ywitness.y;
230 }

232 List Find80rders(Picture pict,double theta) 234 int x,y;
235 int ulcx,ulcy;
236 Queue queue;
237 MinMaxBox boundingBox;
238 WitnessBox oldFrameBox;
239 Llst boxList;
240 intwidth,height;

242 queue = MakeQueue(MAX_QUEUE_SIZE);

244 PcintFromrheta(thet~.~rOY,~r ~Y);
245 Norm7~(poY,roy,&pnx,&pny);

247 printf("Framing picture~n");
2413 FramePicture(pict); 1~ Put a ''visi ted " color border 249 ~ around the image ~1 250 boxList = nil;
25~ for(y= I:y<pict->height-1; + +y) 252 for (x = 1; x<pict- >width-1; + + x) 253 if (ReadPi xel(pict,x,y)) t 254 1~ printf("Found component at (%d,%d)\n",x,y); 'I
255 Pa i ntcc l~l po. ,_ . ,t~p; c t,x,y,queue, &bou nd i ng Br~Y, 9:r' 1 ' ~ ._ 3VA~;
256 1' printf("Making box: %d %d ~d %d\n'', 257 oldr,_.. , - ul~ Y, 258 oldr, ~ l~lc y, 259 oldr. - I~c.x, 260 oldrr; ~~ l~c.y~;
26 1 ~/
262 GetCorner(~ ,J .I~Y~ CY);
263 width = boundingBox.lrc.x-boundingBox ulc.x;
264 height = bounding80x.1-c.y-boundingBox.ulc.y;
265 1~ if(iabs(height)>10)~/
266 if (BoxlnBour~ (r~ y ~llcy~
267 width,height,theta)) 268 push(~ k~R~ (ul~Y.~Icy, 269 width,height,theta), 270 boxList);
271 }
272 printf("Found %d boxes completely on the page\n",ListLength(boxList)l;
Copyright~1991 XeroxCorporation All Rlghts Reserved Sectlon D APPENDIX Page 173 273return boxL,st;
274}

276void DrawBox(Picture pict,Box box) 2 ~ 7 7 9 6 9 278 int rightX,rightY,downX,downY;
279 rightX = box-~width-cos(box->angle);
28û rightY = box->~ ',i"(l~A->angie);
281 downX = box->height-cos(box->angie+M Pl/2);
282 downY = box->height-sin(box->angle+M Pl/2);
283 /~' printf("DrawBox %d %d %d %d\n",box->x,box->y,box->width<,box->height); /
284 DrawLine(pict,box->x,box->y,box->x+rightX,box->y+rightY,Oxffl;
285 DrawLine(pict,box->x+rightX,box->y+rightY, 286 box->x+rightX+downX,box->y+rightY+downY,Oxffl 287 DrawLine(pict,box->x+rightX+downX,box->y+rightY+downY, 288 box->x + downX,box->y + downY,Oxffl;
289 DrawLine(pict,box->x +downX,box->y + downY,box->x,box->y,Oxffl;
290 }

292 void DrawColor80x(Picture pict,Box box,int color) 293 {
294 Int rightX,rightY,downX,downY;
295 rightX = box->width-cos(box->angle);
296 riqhtY = box->width'sin(box->angle);
297 downX = box->height-cos(box->angle+M Pl/2);
298 downY = box->l,L"l,~ (LoA->angle+M Pl/2);
299 /~ printf("DrawBox %d %d %d %d~n",box->x,box->y,box >width<,box->height); '/
300 DrawLine(pia~box->xlbox->y~box->x+rightx~box->y+righty~color!;
301 DrawLine(pict,box-~x + rightX,box >y + rightY, 302 box-~x+rightX+downX,box-~y+rightY+downY,co~or);
303 DrawLine(pict,box-~x+rightX+downX,box-~y+rightY+downY, 304 box-~x + downX,box->y + downY,color);
305 DrawLine(pict,box->x + downX,box->y + downY,box->x,box->y,color);
306 }

309 void Draw30xList(Picture pict,List boxList) 310 {
3t 1 while (!er-~lr(h~ t)) {
312 D, ''~ ~ ' t,(R~Y)pr~(h,~YI i~t));
313 }
314}

317#ifdef TRYMAIN
318 /~WARNlNG-b~suretoreplacetheheightcheckinFindBorders-/
319~endif 320void main(argc,argv) 321intargc;
322char 'argv;
323{
324char infileName,-outfileName;
325List boxList;
326intwidth,height;
327floattheta;
Copyright 1991 XeroxCorporation All Rights Reserved Sectiorl D APPENDIX ' Page 174 i3229 FILE'outfié, 2~79~9 331 if (argc ! = 4) {
332 printf("Usage:%sinfileoutfilepage o,i~ tio,~n",argv[o~);
333 exitlO);
334 }
335 infileName = argv[~l;
336 outfileName = argv[2¦;
337 theta = atoflargv[31);

339 printf("Loading%s. .',infileName);
340 pict = load _ pict(infileName);

342 printf("~nFinding boxes.\n'');

344 finalPict = new pict(pict->width,pict->height,pict-~depth);
345 1~ CopyPicture(finaiPict,pict); ~/
34iS boxLlst = r,.ld30-cl~,(pict,theta);

348 DrawBoxList(finalPict,boxList);
349 write _ plct(OU '''e~ ,finalPict);
350 }

Copyright 199t XeroxCorporation All Rlghts Reserved Section D APPENDIX / Page 1~5 ~an 1615:521991 dict.c 20~7~9 #include <stdio.h>
2 #include"boolean.h"
3 ~includ~"types.h"
4 #include "error.h"
S #include"pict.h"
6 #include"dict.h"
8 void WriteOutlinePair(OutlinePair o, FILE 'fp) 9 {
~0 fwrite~o->box,sizeof(BoxBody),l,fp);
I I fwrite~&(o->blackoutHeight),sizeof(float),l,fp);
12 fwrite~&(o->numberOfLegs),slzeof(int),~,fp);
13 fwrite~&(o->offset),sizeof(int),l,fp);
14 fwrite~&(o->width),si2eof(int),1,fp);
16 fwrite(o->x,sizeof(float),o->numberOfLegs,fp);
17 fwrite(o->top,sizeof(float),o->numberOfLegs,fp);
18 fwrite(o->bottom,sizeof(float),o->numberOfLegs,fp);
19 }
21 void WriteDictionary(Dictionary dict, char ~filename) 22 {
23 FILE ~fp;
24 inttemp;
inti;
26 if ((fp = ~ .,(f;' ,. ~e,"w")) = = NULL) 27 DoError("WriteDictionary: Erroropening output file.\n",NULL);
28 temp = 1234567;
29 f~Nrite(&temp,sizeof(int),l,fp);
f~rvrite(&(dict->numberOfEntries),sizeof(int),l,fp);

32 if (dict->infoString = = NULL) {
33 temp = 0;
34 f~lvrite(&ten~p,s '~ ,fp);
}
36 else{
37 temp = strlen(dict->infoString)+ l;
38 ~ .l.fP);
39 fv~rite(dict->infoString,siz~of~char),temp,fp);
4û }

42 for(i=0;i<dict->numberOfEntries;+ +i) 43 WriteOutlinePainl~(dict->outlinff+i),fp);
44 fclose(fp);
}

48 /~ Reads a Box from a binary stream. the type Box is defined in box.h ~1 49 Box ReadBox(FlLE ~fp) {
Sl Boxtemp;
52 temp = (Box)calloc(1, '(F "- ~y)), Copyright 1991 Xerox Corporation All Rights Reserved Sectlc~n D APPENDiX P~se 176 53 If (temp = = NUL-) 54 DoError('ReadBox cannotallocatespace\n",NULL);
sS if (fread(temp,sizeof(Box90dy),1,fp)1 = 1) 2 ~ 7 7 51' n 56 DoE-ro-("Read80x errorreadinsboundingbox~n",NULL);
57 return temp;
58 }

/tReadsanOutlinePairfromabinarystream ~heformatofanOutlinePair 61 ' follows 62 ' 30xBody - shape bou ndi ng box 63 ' float - blackoutbarheight 64 ' int - numberoflegsinthecontour ' int - x coordinate of left edge of contour 66 ' int - width in pixels of edge contour 67 ^ float[numberOfLegsl x coordinates of contours 68 ~ float[numberOfLegs] ~ y coordinates of top contour 69 ' float[numberOfLegs~ ycoordinatesofbototmcontour 7û '/
71 OutlinePair ReadOutlinePair(FlLE ~fp) 72 {
73 OutlinePairtemp;
74 temp = (OutlinePair)calloc(l,sizeof(OutlinePair30dy)~;
if (temp = = NULL) 76 DoError("ReadOutlinePair cannotallocatespace~n",NULL) 77 temp->box = ReadBox(fp);

79 if (fread(&(temp-~blackoutHeight),sizeof(float),1~fp)! = t) 8û DoError("ReadOutlinePair errorreadingblackoutHeight~n",NULL);

82 if (fread(&(temp->numberOfL~gs),sizeof(int),l,fp)! = I) 83 DoError("ReadOutlinePair errorreadinglength~n",NULL);

if (fread(&(temp->offset),sizeof(int),',fp)! = 1) 86 DoError("ReadOutlinePair erroreadingoffset~n",NULL);
87 if (fread(&(temp-~width),sizeof(int), I ,fp)! = 1 ) 88 DoError("ReadOutlinePair errorreadingwidth~n",NULL);

temp- ~ x = (float '')~alloc(temp- ~ numberOfLegs,sizeof(float));
91 if(temp->x = = NULL) 92 DoError("ReadOutlinePair cannotallocatespace~n",NULL);
93 if (fread(temp-~x 94 sizeof(float),temp-~numberOfLegs,fp)!=temp-~numberOfLegs) DoError(' I ' 9u~linePair error reading x coords~n",NULL);

97 temp->top = (float~ (t~ , -~numberOfLegs,sizeof(float));
98 if(temp-~top = = NULL) 99 DoError("ReadOutlinePair cannotallocatespace~n",NULL);
!00 if (fread(temp-~top,sizeof~float), 101 temp-~numberOfLegs,fp)!=temp->numberOfLegs) ~02 DoError("ReadOutlinePair error reading topY coords~n",NULL);
!03 104 temp->bottom = (float ~)~ " ;t~ "~,-~numberOfLegs,sizeof(float));
lOs if(temp-~bottom = = NULL) 106 DoError("ReadOutlinePair:cannotallocatespace~n",NULL);
107 if (fread(temp-~bottom, Copyright~l991 XeroxCorporation All Rights Reserved Section D APPE~IDIX Page 177 ~08sizeof(float),temp->numberOfLegs,fp)!=temp->numberOfLegs) ?
109DoError~"ReadOutlinePalr errorreadingbottomYcoords\n'',NULL);
~1û
111return temp;
112 }
4/- Create a new Dictionary structure with space allocated for the Z 0 7 7 9 6 9 1~5'entries. /
116Dictionary NewDict(int numberOfEntries) 117 {
118Dictionary temp;
119temp = (Di~N~n~ry~ ";t(l, "Dictionary8Ody));
120if(temp = = NULL) 121DoError("NewDict:cannotallocat~space\n",NULL);
122temp->numberOfEntries = numb~rOfEntries;
123temp->infoString = NULL;
124temp->rawOutlines = (RawOutlinePair-)calloc(numberOfEntries, 125 sizeof(RawOutlinePair));
126temp->outlines = (OutlinePair-)calloc(numberOfEntries, 127 sizeof(OutlinePalr)):
128if ((temp->outlines = = NULL)¦¦(temp->rawOutlines = = NULL)) 129DoError(''NewDict:cannotallocatespace\n",NULL);
130return temp;
131 }

133 /-Readadictionaryfromabinaryformatfile. Thefilec" ~ Lion 134 follows:
135 int -numberofentriesinthedictionary 136 OutlinePair[numberOfEntriesl - outlines of each shape in the dictionary 137 When a dictionary is read in, the shapes are sorted such that they fall 138' i n the order of words on te~ttl i nes. /
139Dictionary ReadDictionary(char 'filename) 140 {
141 FILE fp;
142 Dictionarydict;
143 inti;
144 inttemp;
145 intinfoStringLength;
146 intnumberOfEntries;
147 intmag.;~

149 if((fp=i~, ,(i" ,"r"))= =NULL) 150 DoError("Erroropeninginputfile\n",NULL);
15~
~52 jf (f~ ~tr 3'.r!~ ~ ,sizeof(int),1,fp)! = 1) 153 DoError("Errorreadingdictionany\n",NULL);
154 if (magicNumber ! = 1234567) 155 DoError(" ReadDictionary: input file %s is not a dictionary file.\n", 156 filename);
~57 158 ~f(fread(&numberOfEntri~,s - r('.~),1,fp)!=1) 159 DoError("Errorreadingdictionary\n",NULL);
160 dict = NewDict(numberOfEnUies);

162 ~f (fread(&infoStringLength,sizeof(int),1,fp)! = 1) Copyright0 1991 Xero~Corporation All Riqhts Resen~ed Sec~ion D APPENDIX P~ge 178 163 DoErrot("Error reading dict~onary`n",NULL): ~ ~ 9 164 if (infoStringLength) { 2 165 i f ((dict- ~ infoStri ng = (char t)calloc(i nfoStri ngLength,si zeof(char))~ = =
~ 66 NU LL~
167 DoError('ReadDictionary:cannotallocatespaceforinfostring.\n",NULL);
168 fread(dict->infoString,infoStringLength,sizeof(char),fp);
169 '(dict->infoString+infoStringLength-l) = '\0'; /~SetlastchartoO justincase'/
170 }
17~
172 for(i=0;i~numberOfEntries:~ +i) 173 '(dict->outlinesti) = ReadOutlinePalr(fp);
1 74 fclos~(fP);
175 returndict;
176 }

178 char ~ArgListToString~int argc, char ' argv) 179 {
180 int i;
~81 inttotalLength;
182 char'theStrlng;
183 char 'destCursor,~srcCursor;
~84 185 for (i = 0,totalLength = û;i Cargc; + + i) 186 totalLength + = strlen(argv[i~) + l; /'Roomforeachargandonespace~/
187 totalLength + +; /~ Room for thee EOS character ~/

189 if ((theString = (char ~)c~llo~(Lut~lLength,sizeof(char))) = = NULL) 190 DoErrort"ArgListToString: cannot allocatee space.\n" ,NULL);

192 for (i = 0,destCu rsor = theStri ng; i < argc; +
193 srcCursor = argv[il;
194 while ('srcCursor ! = '\o~) l9S ~destCursor+ ~ = 'srcCursor+ ~;
196 ''destCursor~ ~ ='';
197 }
198 ~destCursor = '\0';

200 return theString;
20t }

Copyright 1991 Xero~Corporation All Rights Reserved Sectlon D APPENDIX Page 179 ~an 11 17:061991 dmdln c 2 ~ 7 7 3 6 9 #includ~ <stdio.h~
2 ~include <math.h>
3 #include <values.h>
4 #include"boolean.h"
S #include''types.h"
6 #include''pict.h"
7 #include"diff.h"

lû void main(int argc,char '~argv) 11 {
12 Plcture pict 13 char~infile;,-infile2,~outfile;

if (argc ! = 4) {
16 printf("Usage:\n"l;
17 printf(" ~slnfilel infile20utfile~n",argv[01);
18 exit(-l) 19 }

21 infilel = argv~
22 infile2 = argvl21;
23 outfile = argvl31;
24 pict = CompareDi.~i.ana~ l,infile2) 25 WritePict~"-As~5~; (r~t,0u !.
26 }
,.. .

Copyright~ 1991 XeroxCorporation All Rishts Reserved - -Section D APPENDIX, Page 180 213~79iD9 ~un 21 15:54 ~997 fft.c /~Copyright ~991 byMichael Hopcroft.
2 ~ Right is hearby granted to Xerox Corporation to make use of this 3 ~ code free of charge. ^/
4 #include < stdio.h >
S #include cmath.h~
6 #include"fft.h"

8 /~ Applies bit reversal permutation matrix to array a. Iength must be a power 9 ~of2.~/
void BitReverse(float a, int n) 11 {
12 int i,j,k;
13 floattemp;
~4 j = 1;
16 for(i = ~;icn; + + i) {
17 if (i<i) ~8 temp = a[i~
~9 a[i-~] = a[j-11;
a[j~11 = t~mp;
21 }
22 k=n/2;
23 while (k<j) 24 j = j-k;
k = k/2;
26 }
27 j = j + k;
28 }
29 }
31 #define~WOPl(M_P1~2) 33 void fft(float ~real,float ~imag,int logn,lnt mode) 34 {
int n;
36 inti~t~r~ a~hot~
37 int ~9~ c~ ~hp7~tLen9th;
38 fioat tempr,tempi,temp2r,temp2i,ar,ai,wr,wi,angle;

n = irir~t(~p7((rlo-~l-'c)1,~-.));

42 for (stage = 1, subpartLength = n;
43 stagec = logn;
44 + + stage, subpartLength/ = 2) {
angle = rWOPI/subpartLength;
46 ar = 1.0;
47 ai = 0.0;
48 if (mode = = REVERSE) 49 wr = cos(angle);
so wi = sin(angle);
Sl }else~
52 wr = cos(angle);
Copyright~991 XeroxCorporation All Rights Reserved Sec~lon D APPENDIX Page 181 53 wi =-sin(angle);
forU=O;j<subp2rtLength/2;+ +j){ /~foreachoffsetinapart~/ 2(~7~96 56 for(top=j;top~n;top+ =subpartLength~{ l~foreachpart~/
57 bottom = top+subpartLength/2;
58 tempr = ,6dl[Lvtlor~ temp = x[id 59 tempi = ;~"~g[~vtlv~
~ vLLv.~.~ = real[topl-real[bottom~ x[idl = x[i] -X[idl ~/
61 imag~bottoml = imag[topl-imag[bottoml;
62 temp2r = real[bottoml~ar-imag[bottom~^ai; /~ temp2 = x[id]~a 'J
63 temp2i = reallbottoml~ai + imag[bouoml~ar;
64 real[bottom] = temp2r; /~ x[idl = temp2 ~/
;~ [bv~tv~l = temp2i;
66 real[topl + = tempr; 1~ x[il + = temp ~/
67 imagltop] + = tempi;
68 }
69 temp2r = ar~wr-ai~wi; /~ a = w ~1 temp2i = ai-wr+ar~wi;
71 ar = temp2r;
72 ai = temp2i;
73 }
74 }
BitRevene(real,n);
76 8ilR~ nag,n);

78 #ifd~f foo 79 if ~mode = = MAGNITUDE) for (i = 0;i <n; + + i) 81 reai[i] = sqrt(real[il~real[il + imag[i]~imag[i]);
82 #endif 84 if (mode = = MAGNITUDE~
for (i =0;i<n; + + i) 86 real[i] = sqrt(real[i]^real[i] + imag[i]~imag[i]);
87 }

89 #ifdef TRYMAIN
void main(i nt argc,char ~"argv) 91 {
92 #define POWER 8 93 #define LENGTH 256 94 float r~al[LENGTH];
float imag[LENGTH];
96 int i;
9~ #ifdef fOO
98 for (i = 0;i<LENGTH; + + i){
99 if (i < LENGTH/2) lû0 real[i] = 1.0;
101 else 102 real[i] = 0.0;
103 imag[i] = û.0;
104 }
~05 #endif l o7 for (i = 0; i < LENGTH; + + i) {
Copyrig11t~ t991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 182 09 real~ sin(3~1W0Pl~i/(LENGTH-l)); 2 ~ ~ 7 ~ 6 9 110 }
11 ~ fft(real,imag,POWER,MAGNlTUDE);
1~2 for(i =O;iCLENGTH; + + i) 113 printf("%d /6f~n",i,real[il);
114 }
11 5 #endif Copyright 0 ~99~ Xerox Corporation All RlghtsReserved Section D AppENDlx ' Page 183 AuglS21:191991 fontNormc 2~7~969 --#include <stdio.h>
2 #include <math.h~
3 #includ~"boolean.h"
4 #include''types.h"
S #include"error.h"
6 #include"pict.h"
7 #include"dict.h"
8 #include"fontNorm.h"

11 ettern double ceil(double);
12 extern int irint(double);

#define UPO
16 #defi ne DOW N 1 17 typedef int Direction;

19 e~ctern Picture thePict;
21 void StoreRawOutl i nePai r(Dictionary dict, int dictEntry, 22 30x box,int ~bothX,int ~topY, int ~baseY, 23 int numberOfLegs) 24 {
RawOutlinePairtemp;
26 int i;
27 int ~xCursor,^topCursor,-boUomCursor;

29 temp = (RawOu~l;ncF).dlloc(l,sii~eof~RawO~ eræ:,Body));
if (temp = = NULL~
31 DoError("StoreRawOutlinePair: cannotallocatespace\n",NULL~;

33 temp->box = box;
34 temp->numberOfLegs = numberOfLegs;
36 temp->x=(int~)cdllo~(t~",u->numberoflDg~ci '( ,~));
37 temp->top = (int~ " ;t~ >numberOfl~g~,s ~ " ,~
38 temp->bottom = (int~) " i r->numberOfLeg~i~- '(;.. )), 39 if((temp->x = - NULV¦¦
(temp-~top = = NULL)¦¦
41 (temp->bottom = = NULL~
42 DoError("StoreRawOutlinePai-: cannot allocate space\n",NULL~;

44 xCursor = temp->x;
topCursor = temp->top;
46 bottomCursor = temp->bottom;

48 for (i = O;i <numberOfLegs; + + i) {
49 ~xCursor + + = tbothX + +;
SO ~topCursor + + = ~topY + +;
51 ~bottomCursor+ + = ~baseY + +;
52 }
Copyright 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 184 3 '~di~t- >rawOutlines t dictEntry) = temp;
,4 }
5567 int RawOutlineWidth(RawOutlinePair a,int midd!eLine) 2 ~ 7 7 3 ~ 9 58 int i,numberOfLegs,right,left;
59 int topCursor,^bottomCursor;
int topValue,bottomValue;
6~
62 numberOfLegs = a->numberOfLegs;

64 topCursor = a->top;
bottomCursor = a->bottom;
66 for(i=0;i<numberOfLegs;~ +i){
67 topValue = ~topCursor ~ +;
68 bottomValue = ^bottomCursor~ +;

if(topValue ! = H~T THE 30X){
71 topValue = middleLine-topValue;
72 if (topVa~ue<0) 73 topValue = 0;
74 }
else 776 topValue = 0;
78 if (bottomValue ! = HIT _ rHE _ BOX) {
79 bottomValue = bottomVa!ue-middleLine;
if (bottomValue < 0) 81 bottomValue = 0;
82 }
83 e!se 84 bottomValue = 0;
86 if ((bottomValue ! = 0)¦¦(topValue ! = û)) 87 break;
88 }
89 left = i;
91 topCursor = a->top+numberOfLegs-~;
92 bottomCursor = a->bottom+numberOfLegs-~;
93 for (i = numberOfL~gs-1 ;i > = 0;-i) {
94 topValue =- ^topCursor--;
bottomValue = ~bottomCursor--;

97 if (topValue ! = HIT THE _ 80X) {
98 topValue = middleLine-topValue;
99 if (topValue<0) 100 topValue = 0;
101 }
1 02 else 103 topValue = 0;

105 if(bottomValue!= HIT THE BOX){
106 bottomValue = bottomValue-middleLine;
107 if (bottomValue < 0) Copyright~ 1991 Xerox Corpor~tion Al! Rights Reserved SectlonD APPENDlx ~ Page 185 ~08 bottomValue = 0, 109 }
1 1 1 else bottorrlVal ue = 0; 2 ~ 7 7 ~ i6 9 112 if ((topValue ! = ~¦¦(bottomValue ! = 0)) I l 3 break;
114 }
~15 right = i I l;

117 return right-left;
118 }

120 ~oid ResampleOutl inePai~(Outl i nePair a,float newroold Factor) 121 /' Resampleanoutlinepairusinglinearinterpolation. '/
lZ2 {
123 intnewWidth,oldWidth,i;
124 int oldLeft,oldRight;
125 float oldCenter;
126 float'newX,~newTop,'newBottom;
127 float'xCursor,'topCursor,~bottomCursor;

129 oldWidth = a->numberOfLegs;
130 newWidth = irint(newToOldFa~tor'oldWidth);

132 n~wX = (float~)calloc(newWidth,si~eof(float));
133 newTop = (float ~)calloc(newWidth,sizeof(float));
134 newBottom = (float ~)calloc(newWidth,si~eof(float));
135 if ((n~wX = = NULL)¦¦(n~wTop = = NULL)¦¦(newBottom = = NULL)) 136 DoError("ResampleOutlinePair: cannotallocatespace.\n",NULL);

138 xCunor = newX;
139 topCunor = newTop;
140 bottomCursor = ne.
14t 142 for(i=0;i<newWidth; I I i)~
143 oldCenter = i/(fl~ .. ~';J~ll'(flo~)oR~';d~l"
144 oldLeft = irint(floor(oldCenter));
145 oldRight = irirt(- 1~ nter));
146 if(oldLeft= =oldRight){
147 'xCursor+ t = ~(a->x I oldLeft);
148 'topCunor ~ (a->top ~ oldLeft);
149 ~bottornCunor I + = ~(a->bottom +oldLeft);
150 }
151 els-{
152 float slope;
153 slope = ~(a->x~oldRight~(a->x+oldLeft);
154 ~xCursor I I = ~(a->x I oldLeft) + (oldCenter-oldLeft)-slope;
155 slope = ~(a->top I oldRight)--(a->top I oldLeft);
156 'topCursor+ I = ~(a->top I oldLeft) ~ (oldCenter-oldLeft)~slope;
157 slope = (a->bottom+oldRight)-^(a->bottom~oldLeft);
158 ~bottomCursor~ (a->bottom ~oldLeft) ~ (oldCenter-oldLeft)~slope;
159 }
160 }

162 free(a->x);
Copyright 1991 Xerox Corporation All Rights Res~rved Section D APPENDIX, Page 186 ~64 free(a >top) 2 ~ 7 7 g ~ ~

166 a-~:c = newX;
167 a-~top = newTop;
168 a->bottom = newBottom;
169 a->numberOfLegs = newWidth;
17û }

172 voidStoreOutlinePair(Dictionarydict,intdictEntry, 173 int middleLine,int fontXHeight, 74 int as~t,~ccl h'~:~l,l,NormalizationDescriptor ~nd) 175 /~rhisroutinenormali2estherawoutlinepairstoredlndictatdictEntryusingthefollowlng 176 ' operations:
t 1 ) For the top contour, shift so that the mlddle line IS at y s 0 and negate so that the 178 ' higherpointsaregreaterthanO. Forthebottom,shlftsothatmiddlelineisaty=0, 179 ~ butdon'tflip. Thus,lowerpointshaveycoordinatesgreaterthanO.
180 ConsiderpointswhosevalueisHlT THE_30Xtobeaty=û Thesecorrespondtogaps 181 ~ betweentheletters.
182 ~ 2) Compress top and bottom y coordinates by ~/fontXHeight so that the coordinates at the 183 ' distanceofthefontXHeighthavevaluel. Notethattlsanarbitrarynumber. Itis 184 ~ unlikelythatasignalwillhavepartsthatarethe1~heightabovethecenterline 185 ~ anyway.
186 ~ FORTOPCONTOUR, 187 ' IF HEIGHT IS GREATER THAN XHEIGHT, SCALE DlfFERENCE 3Y l.S/ASCENDER HEIGHT.
188 ' ELSE SCALE DIFFERENCE 3Y lIXHEIGHT.
189 ' FORBOTTOMCONTOUR, 190 ' SCALE3Y l.S/ASCENDER HEIGHT.
19~ ' 3)Compressthexcoordinatesbythesamefactorasinstep2. Notethatthisdoesnot 192 ' actually resample the contour. NOW DO THIS WITH RESAMPLE. USE SCALE FACTOR OF
193 ~ 2û/XHElGHT.
194 ~ 4) Remove left and right ends of the contour that have y values of 2ero. This is so the l 9S ' contour starts where the word starts, rather than at the edge of its bouding boY.
196 ~ S)Resamplethecontourtostretchbyr;,Fv.,lX . ' ~/rv~ Width. KILLTHIS
OPERATION.
197 ~/
198 {
199 RawOutlinePairraw;
2ûû OutlinePair temp;
2û ~ int i,numberOfLegs;
2û2 int y;
203 int offset;
204 int ~%SCursor,~topSCursor,~bottomSCursor;
205 float ~YDCursor,^topDCursor,~bottomDCursor;
206 float ~l~Cursor,~topCursor,~bottomCursor;
207 int left,right;
208 float foffset;
2û9 float ascenderFactor,~(l I.:~l . ~Fa~v, ,widthFactor;

271 raw = ~dict->rawOutlines~dictEntry);

213 temp = (Ou~ llo~(t,si~eof(OutlinePair3Ody));
214 if(temp = = NULL) 215 DoError("StoreOutlinePair:cannotallocatespace\n",NULL);
Copyright 1991 Xero~tCorporation All Rights Reserved Section D 29'7~qNP~; Page 187 217 temp->x = (float')calloc(raw->numberOfLegs,si~eof(float));
218 temp->top = (float~)calloc(raw~>numberOfLegs,sizeof(float)) 219 temp->bottom = (float~)calloc(raw->numberOfLegs,sizeof(float~;
220 if((temp->x = = NULL)¦¦
221 (temp->top = ~ NULL)¦¦
222 (temp->bottom = = NULL)) 223 DoError("StoreOutlinePair: cannot allocate space~n",NULL);

225 temp->box = raw->box;
226 temp->blackoutHeight = 0;
227 temp->numberOfLegs = raw->numberOfLegs;
228 offset = temp->offset = ~(raw->x~;
229 temp->width = ~(raw->x+raw->numberOfLegs-l)-temp->offset;

231 xDCursor = temp->x;
232 topDCursor = temp->top;
233 bottomDCursor = temp->bottom;
234 xSCursor = raw->x;
235 topSCursor = raw->top;
236 bottomSCursor = raw->bottom;

238 ascenderFactor = l.S/as~nrJo~H '~
239 xHeightFactor = 1.0/fontXHeight;
240 widthFactor = 20.01fontXHeight;
241 if (nd->noXI ~ r: .,alize) 242 xHeightFactor = 1.0;
243 ascend~rFactor = 1.0;
244 }
245 if (nd->noAs~:"
246 ascend~rFactor = xH~','.tFa.

248 numberOfLegs = raw->numberOfLegs;
249 for(i =C;i<numberOfL~gs; + +i) 250 i f (~topSCursor = = HIT _ THE _ 80X) 251 y=0;
252 topSCursor+ +;
253 }
254 else ~
255 y = middleLine-~topSCursor+ +;
256 if (Y<0) 257 y = 0;
ZS8 }
259 if ~y>fontXHeighV2) {
260 float templ = (float~y ~ ascenderFactor;
261 floattemp2=(r~ tXHeighV2~xHeightFactor;
262 if (templ <temp2) 263 ~topDCursor + + = temp2;
264 else 265 ~topDCursor+ + = templ;
266 1~
267 topDCursor + + = (floatly ~ ascenderFactor;
268 ''I
269 }
270 else Copyright~ 1991 XeroxCorporation All RightsReserved Sectlon D APPEN~X Page 188 271'topD~ursor ~ i = (flo2t)y ~ ~HelghtFactor;
_272 --273 if(~bottomSCu-so-= =HIT_rHE_30X){
27745 bottomSCursor ~ , 9 7 ~ 3 1~ 9 276}
277else {
278y = ~bottomSCursor~ + -middleLine;
279if (y<0) 280Y = ;
28~}
282if (y<fontXHeighV2) 283'bottomDCursor~ I = (flOat)y-xHe;~l,LFaLtL~, 284else {
285floattempl = (float~y~ascenderFactor;
286floattemp2 = (float)fontXHeighV2~H~ Fdct~, 287if (templ <temp2) 288tbottomDCursor~ ~ = temp2;
289else 290~bottomDCursor~ ~ = temp~;
291 /' ~bottomDCursor ~ + = (float)y ~ ascenderFactor; ~/
292 }
293 }
25~4 295 /~ Now try to remove parts of the contour on to the left and right of the 296 ~ word shape that are at height 0 ~/

298 /~ Find left edge ~/
299 topDCursor = temp->top;
3ûû bottomDCursor = temp->bottom;
3ûl for(i=0;i<numberOfLegs;f +i){
302 if ((~topDCursor ~ f ! = 0)~ bottomDCursor ~ ~ ! = 0)) 3û3 break;
304 }
305 left = i;

307 /~ Find right edge /
308 topDCursor = temp->top+numberOfLegs-l;
3û9 boKomDCursor = temp->bottom ~ numberOfLegs-l;
310 for(i=numberOfLegs^1;i>=0;--i){
311 if ((~topDCursor-- ! = 0)~ bottomDCursor-- ! = 0)) 3 12 break;
313 }
314 right = i ~ ~;

316 /~Cliptheendsofthecontou-atleftandright~t 317 xDCursor = temp->x;
318 topDCursor = temp->top;
319 bottomDCursor = temp->boKom;
320 xCursor = temp->x~left;
321 topCursor = temp->top~left;
322 bottomCursor = temp->boKom + left;
323 foffset = ~xSCursor;
324 for(i=left;i<right;~i){
325 ~xDCursor ~ xCursor ~ ~ - foffset;
Copyright~ 1991 XeroxCorporation All Rights Reserved Se~tlon D APPENDI~, Page 189 2~77969 326 'topDCursor ~ + = 'topCursor + +;
327 tbottomDCursor+ + = 'bottomCursor+ +;
328 }
329 temp->numb~rOfLegs = right-left;

33t (dict->outlinff~dictEntry) = temp;
332 ~ , ?~utlirepair(~(dict~>outlines+diaEntry)~widthFactor);
333 }

335 static int lineSpa~ing;
336 int OrderOutlinePair(OutlinePair 'ol,OutlinePair o2) 337 {
338 intyDistance;
339 intxDIstance;
340 yDistance = ~'ol)->box->pageY ('o2)->box->p2geY;
341 if (yDistance<lineSpacing && yDistance > -lineSpscing) ~
342 xDistance = (~ol)->box->pageX-('o2)->box->pageX;
343 return xDistance;
344 }
345 return yDistance;
346 }

348 void SortDictionary(Dictionary dict) 350 lineSpacing = 2û;
351 qsort(dict->rawOutlines,dict->numberOfEntries,si~eof~RawOutlinePair~, 352 OrderOutlinePair);
353 }

355 #define HlST _ SIZE 100 356 void ~ Y(i nt 'data,i nt dataLength,i nt offset,i nt sign,i nt 'histogram) 357 {
358 int i,bin;

360 if (sign>0) {
361 intmaxValue;

363 maxValue = 'data;
364 for (i = 0; i ~dataLength; + ~ i) 365 if (data[il! = HIT THE BOX) {
366 maxValue -- data~;~
367 br~ak;
368 }
369 for(;i<dataLength; I +i~
370 if (d~talil! s HIT THE BOX ~L& data~il >maxValue) 371 maxValue = data[~J~
372 if(maxValue!= HIT THE BOX){
373 bin = maxValue-of~et;
374 if((bin>=0)&&(bin<HlST SIZE)) 375 I~.stc.~.O,r,[L-nl+ +;
376 }
377 }
378 else {
379 int minValue;
380 mlnValue = 'data;
Copyright~ 199~ XeroxCorporation All F~ights F~eserved Section D APPENDIX ' Page 190 381 for (i = 0;i CdataLength; + + I) 382 if (data[il! = HIT THE 30X~ {
3884 break; 2 ~ ~ ~ 9 6 9 385 }
386 for(;i<dataLength;+ +i) 387 if (data[il! = HIT THE BOX && data[i~<minValue) 388 minValue = data[i~
389 if (minValue ! = HIT THE BOX~ {
390 bin = minValue-of~et;
391 if ((bin> =0)&&(bin<HlST_'ilZE)) 392 histogramlbi nl + +;
393 }
394 }
395 }

397 void Histogram(int tdata,int dataLength, int offset, int 'histogram) 398 {
399 int i,bin:

401 for (i = 0;i <dataLength; + + ,) {
402 if (~data ! = HIT THE_BOX) {
403 bin = ~data-of~et;
404 i f ((bi n > = 0) &&(bi n < H I ST_SIZ E)) 405 I1;,toy.a" ' )~ + +;
406 }
407 data + +;
408 }
409 }
4t0 417 int MaxBin(int ^histogram) 412 {
413 inti;
414 int maxValue;
415 int maxlnde~;

4t7 maxValue = IStOylJ,,.[01;
418 maxlndex = 0;
419 for(i=0;i<HlST _ SIZE;+ +i) 420 i f (histogram[il > maxValue) {
421 maxValue s histogram[il;
422 maxlndex = i;
423 }
424 return maxlndex;
425 }

427 int MaxBinAbove(int ~histogram,int line) 428 {
429 int i;
43û int maxValue;
431 intmaxlndex;
432 int top,boKom;

434 for(i=û;i<HlST SIZE;+ +i) 435 if (histogram[i] I = 0) Copyright 1991 XeroxCorporation All Rights Reserved Section D AppENolx . Page 191 2~77g~9 436 break;

438 top = i;
439 bottom = (line~top)/2;

441 maxValue = h,s~ù~.a.,,[~o~l;
442 maxlndex = top;
443 for (i = top;i < = bottom; ~
444 if (histogram[i] >maxValue~ {
445 maxValue = histogramlil;
446 maxlndex = i;
447 }
448 return maxlndex;
449 }

4s~ vold DrawrextLines(Picture thePict,Dictionary dict,int topLine,int bottomLIne) 452 {
453 Int maxLength;
454 int halfWidth;
455 i nt x,y;
456 float x2,x3,y2,y3;
457 fioat angle;

459 angl ~ di ct- > rawOutl i nes))- > box - > angl e;
460 maxLength = thePict->width I thePict->height;
46t halfWidth = thePict->width/2;
462 x = topLine ~ -sin(angle) ~ halfWidth ~ cos(angle);
463 y = topLine ~ cos(angle) I halflNidth sin(angle~;
464 x2 = x I maxLength~cos(angle);
465 y2 = y I maxLength~sin(angle);
466 x3 = x-maxLength~cos(angle);
467 y3 = y-maxLength sin(angle);
468 DrawLine(thePict,x,y,(int)x2,(int)y2,5);
469 DrawLine(thePict,x,y,(int)x3,(intly3~s);

471 x = bottomLine ~ -sin(angle) + halfWidth ~ cos(angle);
472 y = bottomLine ~ cos(angle) ~ halfWidth ~ sin(angle);
473 x2 = x+maxLength~cos(angl );
474 y2 = y I maxLength~sin(angle);
475 x3 = x-maxLength~cos(angle);
476 y3 = y-m~xL ngth~sin(angle);
477 Dl Li. ~ r l,x,y,(intlx2,(int)y2,5~;
478 DrawLine(thePict,x,y,(int)x3,(int)y3,5);
479 }

481 voidF,~c~ (Dictionarydict,char~fileName,~ ".aliL~liu--Descriptor~nd) 482 /t WARNING - this must be run before PostProcess since PostProcess changes the raw 483 shape data. ~/
484 {
485 intindex;
486 inttemp;
487 inti,startlndex,firstY,minY,endlndex,shape;
488 inttops[HlST SIZE¦;
489 int bottoms[HlST SIZEI;
490 int ascenders[HlS~ SIZE];
Copyright 1991 XeroxCorporation All Rights Reserved Section D APPENDI / Pa e 192 ~7'~g 491 intdescenders[HlST SIZE¦;
492 intmiddleLine,topLlne,bottomLine,ascenderLlne,desCenderLine;
493 int~s~nJ~ ,des~e,lJ~.h~.nl,l,lineNumber;
494 int fontXHeight,fontXWidth,xlndex;
495 RawOutlinePairthisShape;
496 FIL~ ~fp;
497 BOOLEAN haveFirstFontXWidth = FALS~;
498 int firstFontXWidth;

500 if ((fp = fopen(fileName,"w")) S = NULL) 501 DoError("PageStatlstlcs:erroropeningoutputfile%s.\n",fileName);

503 SortDictionary(dict);

505 index = 0;
506 #ifdef foo 507 malloc verify();
508 #endif 509 lineNumber = 0;
510 while (index c dict->numberOfEntries) {
S ~ 1 startlndex = index;
SIZ firstY = (~(dict->rawOutlines I index))->box->pageY;
513 minY = firstY;
514 while ( (-(dict->rawOutlines ~ index))~>box->pageY - firstY c 20 8~&
S~ S (~(dict->rawOutlines ~ index~)->box->pageY - firstY ~ -2û) {
516 i f ( mi nY > ( (~(dict- >rawOutlin~s + i ndex))- >box- > pageY )) 517 minY = (~(dict->rawOutlines~index))->box->pageY;
518 + ~index;
s19 if (index = = dict->numberOfEntries) 52û break;
52t 522 endlndex = index;

524 #ifdef foo 525 malloc verify();
526 #endif 528 /~ shapes from start i ndex through endi ndex are all on '/
529 1~ the same text line ~/
530 /~ minY has the top of the highest box on the line. ~/

532 /~ Find the base and toplines by taki ng the mode of the heights of the 533 ~ valleys of the bottom contours and the peaks of the top contours ~/
534 for(i=O;iCHlST _ SlZE;i~ ~){
535 tops[i] = 0;
536 bottoms[i] = 0;
537 ascendersti] = 0;
538 descendersli] = 0;
539 }

541 for(shape=~la~ deA~ apecendlndex; ~ ~shape){
542 thisShape = ~(dict->tawOutlines I shape);
543 1' ir, .,.. ,(~I.;,Shape->top,thisShape->numberOf~egs,minY,tops);
s44 H.,lo~ l.;cShape->bottom,thisShape->numberOfLegs,minY,bottoms);

Copyright~ 1991 XetoxCorporation All Rights Reserved Sectlon D APPEN~ ,'g~ge 193 546 ll;Jtoy~ 12x(thisshape->toplthisshdpe->numberofLegs~mlny~ ~ascenders);
547 H;.~ou,~"~ Y(thlsShape->bottom,thisShape->numberOfLegs,minY,l,descenders); --548 }
549 topLine = M~ (LupS) + m~nY;
550 bottomLine = Max8in(bottoms) ~ minY;
SS t ascenderLi ne = Max3in(ascenders) + mi nY;
552 descenderLi ne = ~' E' ~d_i~el 1~. 7) t m i nY;

554 if (thePict) 555 DrawrextLines(thePict,-~ict,tr~rLine,bottomLine~;
556 #ifdef foo ss7 malloc verify();
558 #endif 560 middleLine = (bottomLine~topLine)12;
561 fontXHeight = bottomLine-topLine;
562 d~.~l,d~ = bottomLine-ascenderLine;
563 if((float)as~lld~.He;.~l,U(float)fontXHei3ht c 1.1) {
s64 ~,u.il,~(,L.1~.,,''3adascenderhelghtonline%d.\n'',1ineNumbe~);
565 ascenderLine = Max8inAbove(ascenders,ascenderLine-minY)+minY;
566 ~ I)dQ,~h'e.Jll~ = bottomLine-ascenderLine;
567 r~u~ ld~ "Newascenderhei9ht = %d.~nNewxheight =
%d \n~ s~elldQ:Hr~ fontxHeight);
568 }

570 fprintf(fp,'' %d: %d %d Ai2.6f~n",1ineNumber,fontXHeight,~ . .d.. H~
571 (floa~)..... ,cend~,H '~hU(ll~ )rull~XHeight);

573 ~ifdef foo 574 /~ Assume that the first shape in the image is the letter x.
575 ~ Use this shape to compute the fontXWidth val ue. ~1 576 if(lineNumber= =0) 577 fontXWidth = RawOutlineWidth(~dict->rawOutlines),middleLine);
578 ~endif 580 ~ +lineNumber;
581 if ~fontXHeight < 0) {
582 r,."i"Lr(S~d~ p~ct~ tcs negativefontXHeightinline%d.\n",lineNumber);
583 fontXHeight ~ = -1;
584 }
585 for(shape=,LJ,Il., ' '-dpecendlndex; + +shape) 586 StoreOull;.. _'' ' (di,shape,middleLine,fontXHeight,dsc6,~d~,H~.gl!~,nd);
587 } /~ Do another I i ne of text ~1 588 fclose(fp);
589 }
Copyright 1991 Xerox Corporation All RightsReserved Section D APPENDIX, Page 194 ~Jan ~2 17:35 199~ getAll.c #include <stdio.h ~ 2 (1 7 7 9 G 9 2 #i ncl ude < math. h 3 #include <Yalues.h~
4 #include"boolean.h"
S #include"types.h"
6 #include''pict.h"
7 #include"dict.h"

9 #deFine MAX STRING LEN 256 lû -- _ 11 voidWriteShiftedAsciiOutline(FlLE'fp,OutlinePairoutline,floatx,floaty) 12 {
13 int i;
14 for(i=0;i<outline->numberOfLegs;+ +I) l S Fp~intf(fp,"%f %f n",i + x,'(outline-~top + i) ~ y);
16 fprintf(fp,"~"top\n\n');

78 for(i=0;i<outline->numberOfLegs;+ +i) 19 fprintf(fp,"%f'~f\n'',i+x,y-(~(outline->bottom+i)));
fprintf(fp,"\"bottom\n\n");

23 void WriteOutlines(char "filename,Dictionary dict~

float maxWidth,maxHeight;
26 int i,j,count;
27 int width,height;
28 float x,y;
29 OutlinePairoutline;
FILE ~fp;
37 if ((fp = fopen(filename,"w")) = = NULL) {
32 printf("Erroropening %s.",filename~;
33 exit(- 1 );
34 }
36 maxWidth = 0;
37 maxHeight = û;
38 fo-(i =0;i<dict-~numberOfEntries; + +i) {
39 outline = ~(dict-~outlinff + i);
if (outline-~numberOfLegs ~ maxWidth) 41 maxWidth = outlin~numberOfLegs;
42 for a = O;i <outline-~numberOfLegs; + + j) {
d3 if (~(outline-~bottom + j)~maxHeight) 44 maxHeight = ~(outline-~bottom+l)>maxHeight;
if (~(outline-~top + j)~maxHeight) 46 maxHeight = ~(outline->bottom +J)>maxHeight;
47 }
48 };

printf("maxWidth,maxHeight = ~6f,%f\n",maxWidth,maxHeight);

52 width = irint(sc~rt((d~,hl~)(dict-~numberOfEntries)));
Copyright ~ 1991 Xerox Corporation All Rights Reserved Section D AppENDlx P~ge 195 53 helght = Irint(ldouble)(dict->numbe~OfEntries) / wldth): 2 ~ 7 7 ~ ~ 9 printf("n,width,height = %d,~,'od,%d~n",dict-~numberOfEntries,width,height);

57 for (i = 0; i < height; ~ + i) 58 for(j=û;j<width;~+j)~
S9 count = i~width ~ j;
if ((count < 16) && (count < dict->numberOfEntries)) {
61 x = j~maxWidth~l.S;
62 y = (height-i ~ maxHeight-3;
63 pri n tf( " (% f, % f) ", x,y);
64 WriteShiftedAsciiOutline(fp,'(dict->outlines ~ count~,x,y);
}
66 }
67 fclose(fp);


71 Yoid main(int argc,char ~argv) 72 {
73 char~infile,~outfile;
74 Dictionary dict;
76 if (argc ! = 3) ~
77 printf(''Usage:\n");
78 printf('' %s infile outfile\n'',argvlûl);
79 exit(-1);
}

82 infile = argv[~l;
83 outfile = argv[21;
84 dict = ReadDictionary(infile);
86 WriteOutlines(outfile,dict);

88 printf("\n");
89 }

Copyright ~1991 Xerox Corporation All RightsReserved Sectlon D APPENDIX P~ge 196 Jul 814:251991 getOutlinec 20779~
#include <stdio.h>
2 #include <math.h>
3 #include <values.h>
4 #include <strings.h>
s #include"boolean.h'' 6 #include"types.h'' 7 #include''pict.h'' 8 #include"dict.h"

extern char ~strchr(char ~s,int c);
I~
12 #define MAX_STRING_LEN 256 14 void WriteAsciiOutline(char~filename, OutlinePairoutline~
{
16 FILE ~fp:
17 Inti;
18 if ((fp = fopen(filename,"w")) = = NULL~ {
19 printf("Erroropening ~s.",filename~;
exit(~
21 }
22 for(i =0;i<outline->numberOfLegs;
23 fprintf(fp,"%d%f\n",i,~(outline->top 24 fprintf(fp,"\"top\n~n"~;
26 for(i=0;i<outline->numberOfLegs;~
27 fprintf(fp,"%d ~Of\n",i,-('(outline-~bottom 28 fprintf(fp,"\''bottom\n~n");
29 fclose(fp);

33 void main(intargc,char ~argv) char ~infile;
36 chars[MAX STRING_LEN1,ou'''~el'r~X_STRING_LENI;
37 Dictionary dlct;
38 int selection;
39 char ~crPointer;
BOOLEAN done = FALSE;

42 i f (argc ! = 2) {
43 printf("Usage \n");
44 printf(" %sinfile\n",ar5v[01);
exit(-l);
46 }

48 infile = argv[11;
49 dict = ReadDictionary(infile);
51 while (!done) 52 printf("Shapenumber[0.. 96dl:",dict->numberOfEntries~
Copyright ~ 1991 Xerox Corporation All Rights Reserved Section D APPENDIX .' P~ge 197 53 fgets(s,MAX STRING LEN,stdin);
54 if (sscanf(s, '%d ,&selectlon) = = 1) { r.~ r~ ~ 6 9 if (selection < O ¦¦ selection > = dict- > num berOfEntries) 56 printf("Shape numbers must be between 0 and %d, inclusive.\n", 57 dict->numberOfEntries-l);
58 else {
59 printf~"Output file: ");
fgets(outfile,MAX_STRING LEN,stdin);
61 crPointer = strchr(outfile,'\n~;
62 if (crPointer ! = NULL) 63 crPointer = '\0';
64 printf("Writing shape %d to file %s\n",selection,outfile);
WriteAsciiOutline(outfile,-(dict->outlines ~ selection));
66 }

68 else if ((s[01 = = '\') 11 (s[ûl = = '\n')) 69 done = TRUE;
else {
71 printf("Enteranintegertoselectashapeorablankline\n");
72 printf(''toquit.\n'');
73 }
74 }
75 }

Copyright~ 1991 Xero~tCorporation All Rights Reserved Se~tion D APPENDIX i Page 198 ~lanll ~7.06199~ guasslan.c 2~7 ~ 9~9 #include ~stdio.h>
2 ~Yinclude Cmath h>
3 #include Cvaiues.h>
float square(float x) 6 {
7 return x~x;
8 }

float gaussian(a, s"~ return A~GAUSS(SIGMA, X) ~/
11 floata,s,x;
12 {
13 return(a~exp(-square(Yls)/2.0))/(s-sqrt(2.0'M Pl)):
14 }
~6 float'~ak~ b(i~thalfMasksize~floata) 17 {
18 intmask size;
19 int x;
20 float s;
21 float ~mask, sum;

23 mask size = 2~hdlr~ + t;
24 s = h.-li"" ' i7P/2;
mask = (float ~) calloc(halfMaskSize ~ ~, sizeof(float));
26 if (mask = = NULL) {
27 pri ntf("MakeMask: cannot allocate space~n " ) 28 exit(- I );
29 }
31 for(x = 0; x ~ = I,.,l'r'`-'tSi.-. x + I ) {
32 masklxl = saussian(a, s, (float) x);
33 /~ printf("%e\n",mask[xl); ~/
34 }
36 for (sum = fabs(mask~01), x = 1; x < = 1~1 r~ 'Si7p X ~ ~ ) 37 sum I = 2.0~fl' k YI) 39 for(x=0;x~=h~ LSj~ x~) mask[xll= sum;

42 return mask;
43 }

45 voidGuasslDFloat(float~data,intn,inthalfMaskSize) 46 {
47 floata;
48 float ~mask;
49 float 'newData;
S0 float ~leftFtr,~rightFtr;
S l fl oat sum;
52 int i,j,left,right;
Copyright3 1991 XeroxCorporation All RightsReserved Sectlc1n D APPENDD~ P~ge 199 s3 -- 54 a=l;
56if (n < halfMaskSize~2 ~1) 2 ~ 7 ~ 9 5 9 57return;

S9 newData = (float~)calloc(n,sizeof~float));
if(newData = = NULL){
6~ printf( GuasslDFloat: cannota~locatespace~n );
62 exi t(- ~ ) 63 }

mask = MakeMask(halfMaskSize,a);

67 for (i = halfMaskSize;i <n-halfMaskSize; ~ + i) {
68 sum = ~(data ~ i) ' mask[OI;
69 leftF'tr = rightF'tr = data ~ i;
for(j = t;j<halfMaskSize; ~ +j) 71 sum ~ = mask[j~ leftF'tr) + ~(+ ~rishtFtr));
72 newData[il = sum;
73 }

for(i=O;i<halfMaskSi2e;~ ~i){
76 sum = data[i]~masklOI;
77 left = i;
78 right = i;
79 for(j = l;j<halfMaskSize; + +j) {
if (--left < O) 81 left + = n;
82 i f ~ + ~ right > = n) 83 right - = n;
84 sum + = maskljl ~ ( datalleft¦ + datalrlghtl );
}
86 newData[il = sum;
87 }

89 for (i = n-h~ Ci ~r~: i < n; + + i ) {
sum = data~il'mask[O1;
91 left = j;
92 right = i;
93 for(j = 1 ;j<I,dlI , + +j) {
94 if ~ left ~ O) 9S left + = n;
96 if ( + + right ~ = n) 97 right-= n;
98 sum + = masklj] ~ ( datalleftl + datalrightl );
99 }
100 newDatalil = sum;
101 }
~02 tO3 leftPtr = data;
104 rightF'tr = newData;
for (i = O;i <n; + + i) 706 'leftF'tr~ + = 'rightF'tr+ +;
707 free(newData);
Copyright 1991 XeroxCorporation All Rights Reserved -Sectlon D APPENDIX Page 200 ~08 } 2~7796~ ~
J

Copyright 1991 Xerox Corporation All Rlghts Reserved Sectlo~ D APP~NDIX P2ge 201 .~Aug23 19:21 1991 lines.c #include <stdio.h> 2 0 7 7 ~ 6 ~
2 #include <values h>
3 #include <math.h>
4 #include"boolean.h"
s #include"pict.h"
6 #include"lines.h"

8 void LineEngine(Picture pict, g int xl, lû intyl, 1l intx2, 12 intyz, 13 UCHAR color, 14 pistFunc PerPixel) {
16 staticintinside = 0;
17 int xinc,yinc;
18 intdistance;
19 intleft,rlght,top,bottom;
21 + ~inside;
22 left = 0;
23 rlght = pict->width-l;
24 top = 0;
bottom = pict->height-l;
26 /' printf("Draw line: (q6d,%d)-(%d,%d)\n",xl,yl,x2,y2); ~/
27 /~ CASE VERTICAL ~/
28 yinc z y2-yl;
29 xinc = x2-xl;
if (xinc > 0) {
31 if (yinc > 0) {
32 /~ Line goes up to the right ~l 33 if (yinc>xinc) 34 distance = -yinc;
else 36 -distance = xinc;
37 while((~PerPixel)(pict,xl,y~, 38 ((xl c x2) II(Y1 C y2))&&(xl< = right)&&(yl ~ =bottom), 39 color)) if (distance ~ û) 41 1~ move right ~1 42 xl++;
43 distance-= yinc;
44 } else {
/~ move up ~/
46 Yl~+;
47 distance + = xinc;
48 }
49 }
} else {
51 if (-yinc>xinc) 52 distance = yinc;
Copyright ~ 1 9g1 Xerox Corporation All Rights Reserved ~ectlon D APP~NDIX Page 202 53 else 2077969 54 distance = xinc;
while ((~ PerPi xel~(pict,x I ,y I, 56 ((xl < x2) ¦¦ (yl > y2))&&(x 1 < = right~&&(y1~ = top), 57 COlOr)) t 58 if (distance > 0) t sg /- move right ~/
xl ~ ~;
61 distance ~ = yinc;
62 } else t 63 /~ mclve down /
64 yl--;
distance + = xinc;
66 }
67 }
68 }
69 } else {
if (yinc > 0) t 71 /~ Line goes up to the left ~/
72 if (yinc>-xinc) 73 distance = -yinc;
74 else distance = -xinc;
76 while((~PerPixel)(pict,xl,yl, 77 ((xl >x2)11(yl <y2))&&(xl>=ieft)&&(yl<=bottom), 78 color)) t 79 if (distance > 0) t 1~ move left 81 xl--;
82 distance - = yi nc;
83 } else t 84 /~ move up ~1 yl~ ~;
86 distance-= xinc;
87 }
88 }
89 }elset if (-yinc>-xinc) 91 distance = yinc;
92 else 93 distance = -xinc;
94 whi~e (( ,", F;~:)(p.;t,xl ,yl, ((x1 >x2)11(yl >y2))&&(xl>=left)&&(yl>=top), 96 color)) t 97 if (distance ~ 0) {
98 /~ move l~ft ~/
99 x 1 --;
100 distance ~ = yinc;
101 }else{
102 1~ move down ~/
103 yl--;
104 distance-= xinc;
105 }
106 }
107 }
Copyright5' 1991 XeroxCorporation All Rights Reserved Sectlo n D APPEN DIX P~ge 203 108 ~ 2~'; ri~3~9 109 --inside;
110 }

112 BOOLEAN DrawPiston(Picture pict, int x, int y, BOOLEAN test, UCHAR color) 113 {
l l 4 if (tfft~
115 Write~l', f ~ piCt,X,y,color);
116 return test;
117 }

1 l 9 stati c U ~HAR bi tmasks[] = { 0x80,0x40,0x20,0x l o, o Y~ nv 1 nv 7 nv l };

121 void CountLine18it(Picture pict, 122 intxl, 123 inty~, 124 int x2, 125 inty2, 126 int 'totalSet, 127 int ~total) 128 {
129 staticintinside = 0;
130 intxinc,yinc;
131 int distance;
132 intleft,right,tnr,hottr~

134 int uchar width;
135 UCHAR ~cursor;
136 UCHAR mask;
~37 intcount = 0;
138 intpixels = 0;

140 1 + insid~:
141 leht = 0;
142 right = pict->width-l;
143 top = 0;
144 bottom = pict->height-1;

146 if (pict->depth ! = l) 147 DoError("CountLinel8it: Only depth 1 is supported.\n",NULL);
~ 4~3 149 uchar width = pict->uchar width;
150 cursor = pict->data ~ yl~uchar_width~(x~>>3);
lS~ mask = bitmaskslxl%8~;

1 s3 1~ printf~Draw line: (%d,%d)-(%d,%d)~n",xl ,yl,x2,y2); ~/
154 /~ CASE VERTICAL /
~SS yinc = y2-y1;
156 xinc = x2-x1;
157 if (xinc > 0) {
158 if ~yinc > 0) {
S9 1~ Line goes up to the right ~/
~60 if (yinc>xinc) 161 distance = -yinc;
162 else Copyright l991 XeroxCorporation All Rights Reservved 5ectlon L~ APPENDIX Page 2~4 163 distance = xinc; 2 ~ 7 7 ~ 6 9 164 while(((x~ < x2)¦¦(yl < y2))&&(xl< =right~&&(yl< =bottom~){
165 if ('cursor & mask) 166 1 ~count;
167 ~ ~pixels;
168 if ~distance > 0) {
169 /' move right ~/
170 if ~mask = = Oxl){
~71 mask = Ox80;
1 72 ~ + cursor;
173 }
1 74 else 175 mask = mask >> 1;
176 xl ~ 1;
177 distance = yinc;
178 } else {
179 /' move up ~/
180 cursor + = uchar width;
181 yl ~ ~;
182 distance t = xinc;
183 }
184 }
185 } else {
186 if ~-yinc>xinc) 187 distance = yinc;
188 else 189 distance = xinc;
190 while~xl <x2)¦¦~yl >y2))&~xl<=right)&&~yl>=top)){
197 if (~cursor & mask) 192 , ~count;
193 + I pixels;
194 if (distance > 0) {
195 /- move right ~/
196 if(mask = = Oxl){
197 mask = Ox80;
198 ~ +cursor;
199 }
200 else 201 mask = mask >> 1;
202 xl,,;
203 distance + = yin~;
204 } else {
205 1~ moYe down ~/
206 cursor - = uchar_width;
207 yl-;
208 distance ~ = xinc;
209 }
210 }
211 }
212 }else{
2.13 if (yinc > 0) {
214 /~Linegoesuptotheleft'/
215 if(yinc>-xinc) 216 distance = -yinc;
217 else Copyright 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 205 218 distance = -xinc:
22209 while~((xi >~2)1i(yi <y2))&&(xl>=left)&&(y~<=bottom)~{ 20~796 221 + +count;
222 + + pixels;
223 if (distance ~ 0) t 224 /~ move left ~/
225 if (mask = = Ox80) {
226 mask = Oxl;
227 --cu rso~;
228 }
229 else 230 mask = mask < < 1;
231 xl--;
~32 distance-= yinc;
233 } else {
234 /t move up '/
235 cursor + = uchar_width;
236 yl + ~;
237 distance - = %inc;
238 }
239 }
240 } else {
241 if(-yinc>-xinc) 242 distance = yinc;
243 else 244 distance = -xinc;
245 while(((~l >x2)¦¦(yl >y2))&&(xl>=left)&&(yl>=top)){
246 if (~cursor & mask) 247 + + count;
248 + ~pixeis;
249 if (distance > o) {
250 /~ move left t 251 if (mask = = Ox80) {
252 mask = Oxl;
253 --cursor;
254 }
255 e~se 256 mask = mask ~ < 1;
257 x~-;
258 distance + = yinc;
259 } else {
260 /~ move down ~/
261 cursor - = uchar_width;
262 y1.. ;
263 distance-= xinc;
264 }
265 }
266 }
267 }
268 --inside;
269 ~totalSet + = count;
270 ~total + = pixels;
271 }

Copyright 1991 XeroxCorporation All RishtsReserved Sectlon D APPENDIX Page 206 273 voldDrawLlne(PICturepict,intxl,inty~,lntx2,1nty2~ucHARcolor) 275 I.ineEnginelpict,xl,yl,x2,y2,color,DrawPiston);
276 } 2~779~9 278 static int pixelCounter;
279 static intsetCounter;
28û BOOLEANCo-,-,lr;.tc,-,(,.~lurepict,intx,inty,BOOLEANtest,UCHARcolor) 281 {
282 if (test) {
283 + + pixelCounter;
284 if (ReadPixellpict,x,y)) 285 + + setCounter;
286 }
287 return test;
288 }

290 #ifdef foo 291 float CountLine(Picture pict, int xl, int yl, Int x2, int y2) 292 {
293 pixelCounter = 0;
294 setCounter = 0;
295 LineEngine(pict,xl,yl,x2,y2,0,CountPiston);
296 LineEngine~pict,xl,yl,xt-(x2-xl),yl-(y2-y~),0,CountPiston);
297 return (float)setCounter/pixelCounter;
298 }
299 #endif 3ûû
301 float CountLine(Picture pict, int xl, int yl, int x2, int y2) 303 pixelCounter = 0;
304 setCounter = 0;
305 CountLinelBit(pict,xl,yl,x2,y2,&setCounter,&pixelCounter);
306 CountLinelBit(pict,xl,yl,xl-(x2-xl),yl-(y2-yl),&setCounter,&pixelCounter);
307 return (float)setCounter/pixelCounter;
308 }

310 staticintstartx;
311 static int starty;
312 static int endx;
313 staticintendy 314 BOOLEANDi~t.. ~r;~ Lurepict,intx,inty,BOOLEANtest,UCHARcolor) 315 {
3 1 6 if (test) {
317 if(R ': '~ri~.Y.Y)){
318 if((x= =startx)~y= =starty)) 319 return test;
320 else {
321 endx = x;
322 endy = y;
323 return FALSE;
324 }
325 }
326 else 327 return test;
Copyright ~ 1991 Xerox Corporation All ^ ~hts Reserved Sectic)n D APPENDIX, Page 207 328 } else 329 return test;
3331 } 2077~69 333 intDistanceLine~Picturepict,intxl,inty~,intx2,inty2) 334 {
335 double dx,dy;
336 startx = xl;
337 starty = y~;
338 endx = xZ;
339 endy = y2;
34û LineEngine(pict,xl,yl,x2,y2,û,Di~ Pi, 341 dx = endx-x7;
342 dy = endy-yl;
343 return sqrt(dx-dx ~ dy~dy);
344 }

347 #i~def TEST
348 void draw(pict) 349 Picture pict;
350 {
351 floatangle;
352 float step;
353 floatxl,yl,x2,y2;
354 float rl,r2;
355 int xc,yc;

357 xc = 320;
358 yc = 250 359 rl = S0;
360 r2 = 400;
361 step = M_Pl-2/S0;

363 for(angle = O;angle < 2~M Pl; angle ~ = step) {
364 xl = xc ~ rl~cos(angle);
365 yl = yc ~ rl~sin(angle);
366 x2 = xc I r2'cos(angle);
367 y2 = yc ~ r2-sin(angle);
368 DrawLine(pi,(int)xl,(int)yl,(int)x2,(int)y2,0xff);
369 printf("%3 2f %d %d~n",angle, 370 CountLine(pict,(int)xl,(int~yl,(int)x2,(int)y2), 371 DistanceLine(pict,(int)xl,(int)yl,(int)x2,~int)y2));
372 }
373 }

375 void main(argc,argv) 376 int argc;
377 char '~argv;
378 {
379 char ~outfile;
380 Picture pict;

382 if (argc I = 2) {
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon L~ - APPEND!X Page 208 383 prlntf( Usage ~fis outfile~n ,arcJv[0~); 2 ~ 7 7 9 6 9 384 exit(0);
385 }
386 outfile = argv[ll;

388 pict 5 new_pict(~i40,50û,1);

390 draw(pict);

392 write pict(outfile,pict);
393 printf~done~n");
394 }
395 #endif Copyright ~199~ Xerox Corporation All Rights Reserved Sectlon D APPENDIX Page 209 ug 23 16 43 1991 maxfilter c ~A 2 ~ 7 7 ~ 6 ~
t #include Cstdio h>
2 #include ''mylib h'' 4 extern int irint(doublet;
6 #defineMAX SIGNAL LENGrH(lûûûû) 7 #defi ne Ml N MODE (Sr/- MIN MODE must be less than MAX HIST SIZE ' ' 8 #define MAX HIST SIZE (500) 9 #define MAX PEAK~(tO0) t 0 #define BASE PERCENTI LE (0 5) t t floatdata[MAX SIGNAL LENGTHI;
12 intnewSignallMAX SIGNAL LENGrHI;

14 int MaxOnlnterval(int start,int end) {
t6 inti;
17 float maxValue = data[startl;
18 Intmaxlndex = start;
t9 for(i=start;iCend;~
if (data[i1~maxValue) {
2t maxValue = data[il;
22 maxlndex = i;
23 }
24 return maxlndex;
}

27 void main(int a~gc,char -argv) 28 {
29 char infile,-outfile;
FILE inFP,-outFP;
31 intsignalLength;
32 float cursor;
33 int foo;
34 inti;
3s intmaskWidth = t0;
36 float maxValue;
37 intmaxlndex,modeVal~ ' ;teA, 38 inth[MAX HIST _ SIZE¦;
39 intfinalCount;
4û int r; " '~ r"~x _ PEAKSI;
4~ float baseThrffh 42 BOOLEAN upState;
43 float th;~3~io,1 DefArg("%s %s","infile outfile'',&infile,&outfile);
46 ScanArgs(argc,argv);

48 if ((inFP = fopen(infile,"r")) = = NULL) 49 DoError("Erroropeningfile%s\n",infiie);

Sl cursor = data;
52 while(fscanf(inFP,"%d,6f\n",bho,cunor~ ~)= =2) Copyright 1991 XeroxCorporation All Rights Reserved 53 If (~ursor-data>MAX SIGNAL ~ENGTH) 2 0 7 7 9 6 9 54 DoError( Slgnal is too long.`.n",NULL~;
SS signalLen9th = cursor-data;

57 1~ Compute the threhold for the black edge to black pixel ratio ~/
58 maxValue = datal0];
S9 for (i = û; i <signalLength; + + i) {
if (data[i] >maxValue) 61 maxValue = data[i];
62 }
63 baseThresh = maxValue'3ASE PERCENTILE;
64 printf("baserhresh = %3.3f\n"~aseThresh);
66 1~ Get the indices of the peaks taller than baseThresh 'I
67 finalCount = û;
68 upState = TRUE;
69 for (i = 0;i ~signalLength + + i) {
thisRatio = data[il;
77 if (thisRatio < baseThresh) 72 thisRatio = 0;
73 if (upState) {
74 if (thisRatio < lastRatio) {
finallndex[finalCountl = i;
76 finalCount+ +;
77 upState = FALSE;
78 }
79 }
else {
81 1~ upState = = FALSE 1 82 if (thisRatio > lastRatio) 83 upState = TRUE;
84 }
lastRatio = thisRatio;
86 if(finalCount= =MAX PEAKS) 87 break;
88 }

9û 1'~ Histogram the distances between adjacent peaks ~/
91 for(i=0;i~MAX HIST SlZE;h[i+ +]=0);
92 for(i=0;i<finalCount-r+ +i){
93 int d;
94 d = finallndex[i + 1] '' . " I~.. A[i];
9S if (d<MAX HIST SIZE) 96 h[d]~ +;
97 }

99 /1- Find the mod~ of the adjacent distances that is above MIN_MODE ~/
lû0 modeValue = h[MlN MODE];
10t modelndex = MIN MODE;
102 for(i=MlN MODI~i<MAX HIST SIZE;+ +i) 103 if (h[i] >modeValue) {
104 modeValue = h[i];
105 modelndex = i;
106 }
lû7 Copyright 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX ' pdge 21 ~)8 /~ Set the mask width to half of the most common spacing oF iargest peaks 9 maskWidth = irint(modelndex~0.80);
110 printf("maskWidth = %d.\n",maskWidth);
~12 for(i=0;i<signalLencth;newSignal[i~ ~]=o); 20~7 113 for(i=0;i<signa~Length-maskWidth; + ~ i) 114 newSignal[MaxOnlnterval~i,i I maskWidth)l+ ~;
1~5 116 if ((outFP = fopen(outfile,"w ')) = = NULL) 117 DoError("Erroropening file %s ~n",NULL);
118 for (i = 0;i <signalLength; ~
119 fprintf(outFP,"%d %d~n",i,newSignal[i~);
1 20 fclose(outFP);
121 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectl on D APPEN DIX Pag e 212 Jun t921:22 ~991 myWc.c ~include ~stdio.h>
2 #include "boolean.h" 2 ~ Y
3 #includ~ "error.h" J ~ ( 9 69 S typedefintState:
6 ~defineWHlTE SPACE 0 7 ~define UNKNOWN WORD 1 8 i~define ASCENDER=WORD 2 lû
1 t iYdefine MAX_STRING_LENGTH 2û0 13 BOOLEAN isWhite(charc) 14 {
lS return (c = = ' 'Il~ = = '\t'llc = = '~'~ \n~);
16 }

t8 BOOLEAN isAscender(char c) 19 {
return (~c = = 'b')¦¦(c = = 'd')¦¦~c = = 'f')ll(c = = 'h')¦¦(c = = 'i')¦¦(c = = 'j ')~ = = 'k ')¦¦(~ = = '1 ')¦¦
21 (c = = 't')¦¦((c> = 'A')&b(c< = 'z'))¦¦((~> = '0')&&(c< = '9'))¦¦(~ = = '\")¦¦(~ = = ""));
22 }

24 ~oid main(int argc,char ^~argv) {
26 char ~filename;
27 FILE ~fp;
28 chars[MAX STRING LENGTH+ l];
29 char ~ptr;
State state;
31 intwordsWithAscenders,v,c.. ~r~;~l,outAscenders,words;

33 if (argc ! = 2) {
34 ~ , . ,"Usage:~n");
~y.;ll~ ,.," %s <inputfile>\n");
36 exit(- 1 );
37 }

39 filenam~ ~ argv[ll;
if((fp=fopen(filename,"r"))= =NULL) 41 DoError("%s:cannotopeninputfile.\n'',filename);

43 wordsWithAscenders = 0;
44 .. .d.~ l,o.ltAscenders = 0;
words = 0;
46 fgets(s,MAX STRING _ LENGTH,fp);
47 while (!feof(~p)) {
48 ptr = s;
49 state = WHITE _ SPACE;
while (~ptr I = '\0') {
Sl switch (state) {
52 case WHITE_SPACE:
Copyright~ 1991 XeroxCorporation All RlghtsReserv~d - - :
Sectlon D APPENDIX . Page 213 53 if (isWh~te(-plr)) 54 + I ptr;
else 57 break; UNKNWN_WORD; 2 0 7 ~ 9 6 9 58 case UNKNOWN WORD:
sg if (isWhitel-ptr)) {
+ +~, .d~ ,outAscenders;
61 + + words;
663 state = WHITE_SPACE;
64 if (isAscender(-ptr~) {
+ +wordsWithAscenders;
66 + +words;
67 + +ptr;
68 state = ASCNDER _ WORD;
69 }
else 71 + +ptr;
72 break;
73 case ASCENDER WORD:
74 if (isWhite(-ptr)) state = WHITE _ SPACE;
76 + + ptr;
77 break;
78 default:
79 DoError("myWc: internal error - bad state.\n'',NULL);
} 1~ switch /
81 }~-whlle(-ptr. ... /
82 fgets(s,MAX STRING LENGTH,fp);
83 }/-while(!eo~..... -/
84 printf("words: %d\n" ,words);
printf("words with ascenders: %d\n",wordsWithAscenders);
86 printf( "words without ascenders: %d~n '' ,~. ~. u.~ ,outAscenders);
87 printf("wordds~ .. ld~ -d~, ratio: %6.2f\n", 88 (fls ~ l~scenders/(fP~t) .-d ~'.'; Ll lo~tA.~ d~
89 }

Copyright~ 1991 Xero:tCorporation Al I Ri ghts Reserved ~e~;lon D APPENDIX P~ge 2 l~
Aug 23 18.12 1991 new3aselines.c 2 0 7 7 9 6 9~
#include <stdio.h>
2 liinclude <~aiuff.h>
3 ~iinclude <math.h>
4 iiinclude"boolean.h"
S ~include"pict.h"
6 iiinclude"typff.h"
7 ~iinclude"lists.h"
8 iiinclude"lines.h"
g jijnclude '~baselines h 11 extern double sqrt(double);
12 extern int irint(double);

14 /"inline^/int~E.~.R~a~riA~:;UCHAR~base,intwidth,floatx,floaty) 16 intxi;
17 intyi;
18 UCHAR mask;
t9 xi = irintlx~;
zl yi = irint(y);
22 mask = Ox80 ~ ~ (xi & Ox7);
23 return ~(base ~ yi ~width + (xi ~ ~ 3)) & mask;
24 }
26 void NewCountLinelBit(Picture pict,int xl,int y1,int x2,int y2,int ~black,int blackEdge) 27 {
28 float x,y;
29 float xinc,yinc;
Float xupinc,yupinc;
31 float den;
32 int b,be;
33 intwidth,ucharWidth,height;
34 UCHAR 'data;
36 width = pict->width;
37 ucharWidth = pict->uchar _ width;
38 height = pict->height;
39 data = pict->data;
41 den = sqrt((y2-yl)~(y2-yl)~(x2-xl)~(x2-xl));
42 ~inc = (x2-xl)lden;
43 yinc = (y2-yt)/den;
44 xupinc = -yinc:
yupinc = xinc;
46 x = xl;
47 y=Yl;

49 b=0;
be=0;
52 while (x<width&&x> =O&&y<height&&y> =0) {
Copyright~ t99~ XeroxCorporation All Rlghts F~eser\~ed Sectlon D APPENDIX Page 215 2~77~9 _s3 + + b;
~i4 if (NewRe2dPixel(d2ta,ucharWIdth,x,y)) {
if (!(r~ .Rt~J~ir; - '~ri~r~,ucharWidth,x + xupinc,y + yupinc) &&
56 t~ ln~dr~ at~ ucharwidth~x-xupinc~y-yupinc~)~
57 + + be;
58 }
59 A + = xinc;
y + = yinc;
6~
62 }
63 'biack = b;
64 'blackEdge = be;
65 }

68 #define MIN BLACK S
69 void NewCountLlne(Picture pict,int x1 ,int yl,int x2,int y2,1nt 'black,int 'blackEdge) 7~ ~black = û;
72 'blackEdge = û;
73 NewCountLine~Bit(pict,xl,y~,x2,y2,black,blackEdge);
74 NewcountLine~Bit(pict~x~y~xl-(x2-x~)~y~ (y2 yl)~hl~ck.h~ r~ e);
}

77 static float x20ffset;
78 static float y20fket;
79 staticintp.v,~Lll,J~A, Bû static int ~blackPixels;
8 ~ stati c i nt "hl ~k r 'r, ^ i A~ I S;
82 static int ~coordx;
83 static int ~coordy;
84 BOOLEAN BaseLinePiston(Picture pict, int x, int y, BOOLEAN test, UCHAR color) {
86 if (test) {
87 NewCountLine(pict,x,y,(int)(x + x20ffset),(int)(y + y20ffset), 88 blackPixels + ~ -,h'7ckr '_ ~;A~I~ + ~.. v,_~ll.,~i~A), 89 ~VVI~ ,o-~ Ll.. ' = x;
~vv~ j v~Lllld.. A+ +l = y;
91 return tfft;
92 } else 93 return test;
94 }
96 static int lastX;
97 static intlastY;
98 BOOLEAN Edl'ui~P;,Iv-l(l ,~LIJre pict, int x, int y, BOOLEAN t~st, UCHAR color) 99 {
lOO if (test) {
lO~ lastX = x;
~û2 lastY = y;
~û3 }
~04 return test;
105 }

lû7 voidE,~irc.",L,(~,~Lurepict,doubleangle,int'tx,int'ty,int-bx,int~by) Copyright~ l99~ XeroxCorporation All Rights Reserved Sectlon D APPENDIX P~ge 216 1og Intxc,yc; 7 9 6 9 110 intmaxLength; 207 111 float normal;
112 floatx2,y2,x3,y3;

114 /~ Make normal to text point in quadrants I and 11~/
~15 /~ Assume 0 < = angle < 2-M Pl ~/
116 normal = fmod(angle ~ M Pr2,2~M Pl);
1~7 if(normal >M Pl) 1~8 normal-= M Pl;

120 xc = pict->width~2;
121 yc = pict->heighV2;

lZ3 maxLength = pict->width+pict~>height;
124 x2 = xc ~ maxLength 'cos(normal); /- At bottom of picture /
125 y2 = yc ~ maxLength'sin(normal);
126 Y3 = xc-maxLengthtcos(normal); /-Attopofpicture-/
23 y3 = yc-maxLength-sin(normal);
129 LineEngine(pict,xc,yc,(int~x2,(int)y2,0,Cr,droi ,Lri.ton);
130 bx = lastX;
131 by = lastY;
132 ~ C yi"~(pict,xc,yc,(int)x3,(int)y3,0,E,~clP~ "LFisto,~);
133 tx = lastX;
134 ty = lastY;
135 }

137 doubledistance(intxl,intyl,intx2,inty2) 139 returnsqrt((~o~ ` Y1-x2)~(x1-x2)~(y1-y2)~(y1-y2)));
14û }

142 FILE PlotBaselineContour(char ''plotFile,int topCount, 143 float ~rati0,int ~newSignal, 144 float baseThresh) 145 [
146 FILE outfile;
147 inti;

149 prinff("Opening baselines plot file~n");
150 if((outfile = r" ,("loLF;~,"w~))= =NULL){
151 printf("Erroropeningbaselineplotfile\n'');
152 exit(-1);
153 }
154 for(i=0;i<topCount; ~
155 fprintf~outfile,"%d ~6f\n",i,ratioslil/baserhresh-S);
156 fprintf(outfile,''\"Ratio~n\n");
157 for(i=0;i<topCount;+ li) 158 fprintf(outfile,"%d %d\n",i,newSignal[il), 159 fprintf(outfile,"\''~ Lion~n\n");
160 fprintf(outfile, 161 "0 %f\n%d %f,6\n\"Baseline Threshold\n", 162 baseThresh,topCount,baseThrffh);
Copyright ~1991 Xerox Corporation All Rights Reserved Secti o n D APP E N Dl X P~g e 2 1 7 63 return outfile;
~64 }

166 int MaxOnlntervai(float 'data,int start,int end) 1 67 { 2 0 7 7 9 ~ 9 169 floatmaxValue = data[start];
~7û intmaxlndex = start;
171 for(i =start;i<end; + +i) 172 i f (data[i I > maxValue) {
173 maxValue = data~il;
174 maxlndex = i;
175 }
176 return maxlndex;
lJ7 }

179 #defineBASE PERCENTILE050 180 #define MIN LINE HEIGHT FRACTION 0 50 181 #define MIN MODE (S) /~ MIN MODE must be less than MAX HIST SIZE '/
182 #defineMAX HIST SlZE(500r 183 #defineMAX 8ASELINES(300) 184 List BaseLines¦F~cture plct,double angle,char plotF~le) 185 {
186 float't~,,vr.;? ), 187 int 'topCoordx,'topCoordy;
188 int 'finalcoordx~finalcoordy~finallndex;
189 inttoplndex,b~ ,nlndeA, 190 inttopCount,botCount,finalCount;
191 i nt maxLength;
192 i nt xc,yc;
193 floatx2,y2,x3,y3;
194 floatmaxValue,lastValue;
int i,j;
196 floatbaseThresh;
197 inttopX,topY,bottomX,bottomY;
198 BOOLEANonTextLine;
199 ListxList,yList,result;
200 double totalDistance,averageDistance;
201 FILE 'outfile;
202 int inside;
203 BOOLEAN upStat~;
204 flodt ratio,lastRatio,thisRatio;
205 float 'ratios;
206 int newSignal;
207 intllalrr~ = 10;1^forcomputingratios'/
208 intr ' nnodeValue,modeindex;
209 int h[MAX HIST SIZEI;
210 i nt maskW~dth; /'~or max filter '/

212 printf("angle = ~633Rn",angle);

214 /-ThelongestlingthoughthepicturewillbeshorterthanmaxLength~/
215 maxLength = pict->width+plct->height;

217 /~Allocatespaceforthepageprojectionvalues'/
Copyright~ 1991 XerolCorporation All Rights Reserved Sectlon L~ APPENDIX Page 218 218 blackPixels - (Int ~)calloc(max-ength,sl2eof(int));
219 blackEdgePixels = (int^)calloc(maxLength,sizeof(int)); ~ , e;r~
220 ratios = (float^)calloc(maxLength,sizeof(float)); bU ~ ~ J ') '' 221 newSignal = (int-)calloc(maxLength,si2eof(int));
222 topCoordx = (int ^)calloc(maxLength,sizeof(int~);
223 topCoordy = (int ^)calloc(maxLength,si2eof(int));
224 finalCoordx = (int ~)calloc(maxLength,sizeof(int));
225 finalCoordy = (int~)calloc(maxLength,si2eof(int));
226 finallndex = (int t)~AIlo~(r^AYI ~ngth,sizeof(int));

228 if((blackPixels = = NULL)¦¦
229 (bla~kEcl5~r-Ac'. = = NULL)¦¦
230 (ratios = = NULL)¦¦
231 (newSignal = = NULL)¦¦
232 (topCoordx = = NULL)¦
233 (topCoordy = = NULL)¦
234 (finallndex = = NULL) ¦
235 (finalCoordx = = NULLI¦¦
236 (finalCoordy = = NULLI) {
237 printf("BaseLines: cannotallocate memory\n");
238 exi t(- 1 );
239 }

241 /^ Compute the endpoints of a lin~ through the center of the picture in the direction 242 perpendicular to the text lines. This line wlll be used as the reference frame for 243 ^ computing projections. ^1 244 CndP~,,(p,ct,angle,~tnrY,~t~pY,&bottomX,&bottomY);

246 printf("Main Line: (%d,%d)-(%d,%d)\n'',topX,topY,bottomX,bottomY);
247 /~ DrawLine(pict,topX,topY,bottomX,bottomY,Oxff); ^/

249 /^ Compute the projection of the image at each point along the line.
2 50 ^ tOp~ n wi l l have the nu mber of bl ack pi xels on a l i ne and 251 ^ratioswillhavethefractionofblackpixelsonalinethatare 252 the ends of vertical extents. ^/
253 x20ffset = maxLength~cos(angle);
254 y20ffset = maxLength~sin(angle);
255 p, ~ ,r!< ,~ = û;
256 coordx = topCoordx;
257 coordy = topCoordy;
258 Li.~_:"~;"_(pict,topX,topY,bottomX,bottomY,0,8aseLinePiston);
259 topCount = ,~ LA~

261 /~ Comput~ the ratios plot ^/
262 for (i s O;i ~1~1 fr ~ '~V.'iJ~I" + ~ i) 263 ratios[il s 0;
264 for(i =topCount-~ dll"i<topCount; ~ I i) 265 ratios[il = 0;
266 for(i=O,inside=O;i<halfMaskWidth^2+1;~ 1 i) 267 inside I = blackPixels[il;
268 for (i = halfMaskWidth; i < topCount-half MaskWidth; + ~ i) {
269 ratioslil = (flo~ c~F~gePixels[i]/inside;
270 inside - = blackPixels[i-l~l r~ ' ' W;J ~i ,1;
271 inside + = blackPixels[i ~ h~l,'' ' ~'i Copyright 1991 Xerox Corporation All Rights Reserved Sectlon D APPENDIX Page 219 74 /- Compute the threhold for the black edge to black pixel ratlo ~/
275 maxValue = ratios[ûl; ~7 r1 Q ~ 9 276 for(i=û;i<topCount;+ +i){ 2~ "
277 if (raliOS[il >maxValue) 278 maxValue = ratios[il;
279 }
28û
281 baseThresh = maxValue~BASE PERCENrlLE;
282 printf("baseThresh = f~3.3f\n'~baseThresh);

284 /~ Get the coordinates of the baselines and toplines by finding peaks in the 285 ~ ratios projection. ~1 286 finalCount = 0:
287 upState = TRUE:
288 for(i=0;i<topCount;++i){
289 thlsRatio = ratios[il;
290 if(thisRatio < baseThresh) 297 thisRatio = 0;
292 if (upState) {
293 if (thisRatio < lastRatio) {
294 finallndex[finalCountl = i;
295 finalCount+ +;
296 upState = FALSE:
297 }
298 }
299 else {
300 /~ upState = = FALSE ~/
3ût if (thisRatio > lastRatio) 302 upState = TRUE;
303 }
304 iastRatio = thisRatio;
305 if (finalCount = = MAX BASELINES) {
306 fprintf(stderr,"Warning: found too many baselines.\n");
307 fprintf(stderr," Ignoring remaining baselines.\n'');
308 break;
309 }
310 }

312 1~ Histogram the distances between adjacent peaks ~/
313 for(i =û;i<MAX HIST _ SlZE;hli + + 1 =0);
314 for (i = 0; i < finalCount- 7, + + i) {
31s intd;
316 d = finallndex[i + 1] r, 317 if(dCMAX HIST SIZE) 318 h[dl+ +;
319 }

32~ I~Findthemodeoftheadja~entdistancesthatisaboveMlN MOOE~/
322 modeValue = h[MlN MODEI;
323 modelndex = MIN MODE;
324 for(i =MIN MODE;i<MAX _ HIST _ SIZE; + +i) 325 if (h[il>modeValue) {
326 modeValue = h[il;
327 modelndex = i;
Copyright~ l991 XeroxCorporation All Rights Reserved Sectlon L~ ~ APPENDIX P~ge 220 2077~9 328 }

330 1' Set the mask width to half of the most common spacing of largest peaks t/
331 maskWidth = irint(mod~ J~~0.80);
332 p~intf~"maskWidth = %d.\n",maskWidth);

334 fO~ (i = 0; i ~ topCount; newSignal [i ~ ~1 = 0);
335 for(i=0;i~topCount-ma~k~'i~ ti) 336 newSignal[MaxOnlnterval(ratios,i,i t maskWidth)~

338 /' Plot the baseline contour if requested '/
339 if (plotFile! = NULL) 340 outfile = PlotBaseiineContour(plotFile,topCount,ratlos,newsignal,baseThresh);

342 /' Pi ck off the new peaks /
343 /'Computethethreholdfortheblackedgetoblackpixelratio-/
344 maxValue = newSignal[0];
345 for (i = 0;i ~topCount; ~ ~ i) {
346 if(newSignal[il~maxValue) 347 maxValue = newSignal[il;
348 }

350 baseThresh = maxValue'0.80;
35~ printf("baseThresh = %3.3f~n",baseThresh);

353 1~ Get the coordi nates of the basel i nes and toplines by fi nding peaks in the 354 ~ ratios projection. '/
355 finalCount = 0;
356 upStat~ = TRUE;
357 for(i=0;i~topCount;~ ti){
358 thisRatio = newSignal¦i];
359 if (thisRatio ~ baseThresh) 360 thisRatio = û;
361 if (upState) {
362 if (thisRatio ~ lastRatio) {
363 finalCoordx[finalCount¦ = topCoordx[i];
364 finalCoordy[finalCount] = topCoordy[i];
365 finallndexlfinalCountl = i;
366 finalCount I l;
367 upState = FALSE;
368 }
369 }
370 els~ {
37~ /' upState = FALSE "
372 if ~thisRatio > lastRatio) 373 upState = TRUE;
374 }
375 lastRatio = thisRatio;
376 if(finalCount = = MAX BASELINES){
377 fprintf(stderr,"Warning: found too many baselines.\n");
378 ~ r(~ld~"~I gnoringremainingbaselines.\n'');
379 break;
380 }
381 }

Copyright~ ~991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 221 2~77~i~9 384 /- t/

386 if (finalcount&l~
387 --finalCount; /~ Only take an even number of I i nes ~l 388 hr(totalDi5tance=0,i=0,j=0;i<fina~Count;i+=2){
389 topX = finalCoordx~
390 topY = finaiCoordy[i];
391 bottomX = finalCoordx[i+11;
392 bottomY = finalCoordy[i+11;
393 totalDistance + = i~ upX,topY,bottomX,bottomY);
394 j + = 2;
395 }
396 averageDistance = totalDistance/(finalCounV2)-MlN_LINE HEIGHT FRACTION
397 for(i=0,j=0:i<finalCount;i+ =2~{
398 topX = finalCoordx(il;
399 topY = finalCoordylil;
400 toplndex = finallndex[il, 401 bottomX = finalCoordx[1+1l;
402 bottomY = finalCoordy[i+1];
403 bulLu~ deA = finallndex[i + 11;
404 finalCoordx 1l = topX;
4o5 finaiCoordy jl = tPY;
406 finallndexG' = topindex;
407 finalCoordx ï + 1~ = bottomX;
408 finalCoordy j + 1~ = bottomY;
409 finallndex[j+11 = b~ ùMl~d~
410 if ( i;,l.-~ (topX,topY,bottomX,bottomY)>averageDistance) 411 j+=2;
412 }
413 #ifdeffoo 414 count = j;
41s returnCoordx = finalCoordx;
416 ~returnCoordy = finalCoordy;
417 #endif 418 result = nil;
419 for(i=j-l,i>=0;--i){
420 push(M~akero~l(ri~ 'Coordx[il,finalCoordy[il),result);
421 }

4Z3 if (plotFile ! = NULL~ ~
424 fprintf(outfile,"\nO %f~n",-baseThresh);
425 for(i =0,i<j,i + =2){
426 fprintf(outfile,"%d %f\n%d ,'0f\n~Od %f\n,6d fOf\n", 427 finallndex[il,-baseThresh, 428 finallndex[il,-2~baseThresh, 429 finallndex[i + 1 1,-2-baseThresh, 430 finallndex[i + ll,-baseThresh);
431 }
432 fprintf(outfile,"\"3aselines'');
433 fclose(outfile);
434 printf(''Donewritingbaselineplotfile.\n");
435 }

437 return result;
Copyright~ 1991 XeroxCorporation All Rights Reserved ~ectlonrD APPENDIX Page 222 439 ~ 9 440 vo;d D~awBd5eLines(Picture pict, List pointList, double angle) 2 ~ ~ ~ 9 441 #ifdef foo 442 i nt count,inl ~coordx,int ~coordy,double angle) 443 ~endif 444 {
445 int max~ength;
446 floatx2,y2,x3,y3;
447 int x,y;
448 Point temp;
449 maxLength = pict->width~pict->height;
450 while (!endp(pointList)) {
45t temp = pop(pointList);
452 x = temp->x;
453 y = temp->y;
454 x2 = x+maxLength~cos(angle);
455 y2 = y+maxLength~sin(angle);
456 x3 = x~maxLength~cos(angle);
457 y3 = y-maxLength~sin(angle);
458 ::)rawLine(pi,x,y,(int)x2,(int)y2,0xffl;
459 DrawLine(pict,x,y,(int)x3,(int)y3,0xffl;
460 }
46~ }

Copyricht t991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 22 ~ug 2519:481991 newBloblfy c t #include <stdio.h>
2 #include <math.h> 2 ~ 7 7 ~ g 3 3 #include"my~ib.h"
4 #include''blobify.h"
s 7 #define MAX_KERNAL_51ZE (40) 9 extern int irint(double);
1~ staticUCHARbitmasks[] = {ûx80,0x40,0x20,0xlO,Ox8,0x4,0x2,0xl};

13 UCHAR'address(Picturepict,floatx,floaty~
14 {
return pict->data +irint(y)^pict-~uchar width ~ (irint(x)>>3);

18 UCHAR mask(float x) 19 {
staticmasks[l = {Ox8û,ûx40,0x20,0xl0,8,4,2,1};
21 return masks[irint(x)%81;
22 }

24 int X(f oat x) {
26 return irint(x);
27 }

29 int Y(float y) {
31 return irint(y);
32 }
34 Pi cture ~ 'e . . 3 I~ L. f~(Picture old, i nt hal f MaskWidth ,d oubl e threshold,dou ble angl e) {
36 Picture new;

38 intindex;
39 float x,y xinc,yinc;
UCHAR k~,.l '~t,'~ X KERNAL SlZEi,^kp[MAX KERNAL 51ZE¦;
41 UCHARkc.-l ' ' k,t"NX _ KERNAr 51ZEI,km[MAX KERNAL 51ZEI;
42 intkernalX~MAX KERNAL 51ZEI,kernalY[MAX KERNAL 51~EI;
43 intkx[MAX KER~AL 51ZE~kylMAX KERNAL 51ZE];
44 UCHAR kblMAX KERNAL 51ZEI;
UCHAR ^dest;
46 UCHAR dm;
47 int tval,i,j,k,inside;
48 intwidth,height,ucharWidth,maskWidth;

if (halfMaskWidth^2+ 1 > MAX KERNAL 51ZE) 51 DoError("Blobify: maskistoolarge.\n",NULL);

Copyright D 1991 Xerox Corporation All Rights Reserved SectlorrD ~ APPENI~IX Page 224 53 tval = irint(threshold~(halfMaskwidth~2 + l));
width = old->width; r) ~ r~ 61 56 height = old->height; ~ V I ~ ~ J
57 ucharW~dth = old-~uchar _ width;

sg new - new_pict(width,heighl,l);
61 xinc = cos(angle);
62 yinc = sin(angle);
63 index = 0;
64 kernalPtr~index] = address(old,halfMaskWidth,halfMaskWidth);
/' 66 kernalX[index] = X(halfMaskWidth);
67 kernalY~index~ = Y(halfMaskWidth);
68 "/
69 kernalMasklindex+ +l = mask(halfMaskWidth);
~0 fOr (i = O,x = O,y = O i <hal~r ' ' ~t'R~LII; + + I) {
71 x + = xlnc;
72 y+ =yinc;
73 kerr~alPtr[index] = address(old,halfMaskWidth + x,halfMaskWidth + y~;
74 /~
kernalX[indexl = X(hali~' ~W;Jll,+x~;
76 kernalY[index] = Y(halfMaskWidth+y);
77 '/
78 kerr ' ' '<' ~ A + +I = ma~k(~,al~M \I\ id~l +x);
79 kernalPtr[indexl = acld,., ~ 1 halfMaskWidth-x,halfMaskWidth-y);
8û 1.
81 kernalXIindex~ = X(ll ,l, W;J~II-x);
82 kernalYIindexl = Y(l ~lli ' ~'iJll,-y);
83 'I
84 kernalMask[index+ +l = mask(halfMaskWidth-x);
}

87 maskWidth = 2'h~1 ~r ~ ' ~';dth + 1;

89 ~or (j = O;j Cheight r ~ '1, + + j) {
for(i=O;i<index; + +i){
91 kp[il = kernalPtrlil+j'ucharWidth;
92 km[il = kernalMasklil;
93 kbli] = kpli] + +;
94 1' kxlil = k-rnalX[il;
96 ky[il = kernalY[il + i;
97 ''I
98 }
99 dest=new->data+(j+halfMaskWidth)'ucharWidth+(~,~l vviJlll>>3);
100 dm = mask(halfMaskWidth);
~01 102 for (k = O;k<width-maskWidth; + + k) {
103 if(dm = = 0){
104 dm = Ox80;
105 dest I +;
106 }
107 for(i=O,inside=O;i<index; + +i)~
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX P~ge 225 ~og km[i] - Ox80; 2 0 7 ~ 9 6 9 110 kb[i] = ~kp[il + +;
11t }
~12 /~
~13 printf~''(%d,%d): %d - %x %x -> %x\n",kx[il,ky[il,kblil&km[il,kp[il-~,km[il~kb[i]);
~ ~4 kx[i] + +;
115 '/
116 if (kb[il&km[il) + +Inside;
~8 km[i] >>= 1;
119 }
1 20 /~
12~ printf("%d\n\n'',inside~;
~ 22 'I
123 if (inside > tval) 124 ~destl= dm;
125 dm >>= 1;
126 }

128 }

130 return new;
~3~
132 }

134 #ifdef TRYMAIN
void main(a~gc,argv) 36 i nt argc;
~37 cha~argv;
~38 {
139 char ~infile,'outfile;
140 Pictureold,new;
~4~ int halfMaskSI~e;
142 floatthreshold;
143 floatangle;

~45 DefArg("%s%s%d%f5~f",''infileoutfilehalfMaskSizethresholdangle", ~46 8.. " 'e,~u ~'e,~halfMaskSi~e,&threshold,&angle);
~ 47 ScanArgs(argc,argv);

149 printF("~oading %s. . .",infile);
lS0 old = load pict(infile);
151 new = ~ 'y(old,halfMaskSi~e,threshold,angle);
152 wri~e _ pi~t(ou:~"e~rlew);
153 }
1 54 ~endif Copyright0 1991 XeroxCorporation All Rights Reserved Se~tlorrD - APPENDIX Page 226 Aug 1506.~1 1991 newContour.c 2077969 - ~
j~include <Kdio.h>
2 ilinclude <values,h>
3 i!include < math, h >
4 #include"boolean.h"
S #include"types.h'' 6 #include''pict,h'' 7 #include''lines.h"
8 #include"lists.h"
3 #include"dict.h"
i!include"diff.h"
11 #include''fontNorm.h"

13 extern Picture thePict; /~ Picture used for annotated shapes '/

15 /' The following are misc. definitionas and routlneS havine to do with 16 ~ vectors and coordinates. ~/

18 typedef struct {
19 double x;
2û double y;
21 } DPoint80dy,^DPoint;

24 static doubi e Dot~DPoi nt a, DPoi nt b) {
26 /~ printf("Dot: (%If,%lf)~(%lf,%lf) = %If n",a->x,a->y,b->x,b->y,a->x~b->x a->y~b->y); ~f 27 returna->x~b->x ~ a->y~b->y;
28 }
30 static DPolnt PolarroCartesian(double angle,double radius) 31 {
32 DPointresult = (DPoint)calloc(l,si~eof(DPolnt80dy));
33 i~(result = = NULL) 34 DoError("Dot: cannotallocatespace~n");
3s result->x = cos(angle);
36 result->y = sin(angle);
37 r2turn result;
38 }

4û static DPoint 1~ qG-I .t a~
41 {
42 DPointresult = (Dl'~ 'I,si~eof(DPolnt80dy));
43 if(result = = NULL) 44 DoError("Dot: cannot allocate space\n"):
result-~x = -a->y;
46 result- >y = a- > x;
47 return result;
48 }

Copyright 1991 Xerox Corporation All Rights Reserved Section D APPENDIX P~gr~ 227 52 /t This p~ston s~ans plct up and down from ~he top and bottom of the 53 bounding box, looking for the highest and lowest pixels In the ~ n ~ ~ 9 6 9 54 ~word lfthepictisnotNuLL~thesep~xelswlllbecoloredas4 ~'3 SS ~ in thePict ^/
56 static int stanX;
57 static int startY;
58 staticdoublestopDistance;
S9 static int lastY;
6û static BOOLEAN valid;
61 800LEANTracePiston(Picturepict,intx,inty,BOOLEANtest,UCHARcolor) 62 {
63 double distance;
64 i f (test) {
distance = sqn((double)(stanX-x)-(stanX-x) ~ (stanY-y)-(stanY y));
66 if (distance~stopDistance) {
67 /~ lastY = stopDistance - distance; /
68 lastY = distance;

If (ReadPixel(pict,x,y)) {

72 if (thePict) 7 3 W, i ~ i ct, x, y,4);

valid = TRUE;
76 return FALSE;
77 } else {
78 valid = FALSE;
79 return test;
}
81 }
82 else {
83 If (thePict) 84 WritePixel(thePict,x,y,4~;
#ifdef foo 86 lastY = distance; /~ Used to be û
87 #endif 88 lastY = HIT THE 80X;
89 valid = FAL~E;
return FALSE;
91 }
92 }
93 return test;
94 }

97 /~ This piston moves from left to right across a bounding box, calling 98 ~ trace piston and saving its output in topY, baseY, and bothX ~/
99 #define MAX SHELL LENGTH 400 100 static int numberOfLegs;
101 staticinttopY[MAX SHELL LENGTHI;
102 static int baseY[MAX _ SHELr LENGTH~;
103 staticintbothX[MAX SHELL LENGTHI;

l OS static double leftDistance;
106 static DPoint lineVector;
Copyright~ 1991 XeroxCorporation Al~ Rights Reserved Sectlon ~ APPENDIX Page 228 107 static int downX
108 staticlntdownY; 2 ~ 7 ~ 9 5 ~
~ 09 static double boxTopDistance;
110 static double boxBase~istance:
111 300LEAN ShellPiston(Picture pict, int x, int y, BOOLEAN test, UCHAR color~
112 {
113 ,nt xDistance;
114 DPoint80dythisPoint;
1 15 i f (test) {
116 if(numberOfLegs>= MAX SHELL LENGTH) 17 return FALSE;
118 thisPoint.x = x;
119 thisPoint.y = y;
120 xDistance = Dot(&thisPoint,lineVector)-leftDistance;
121 stopDistance = boxTopDistance;
122 startX = x;
123 startY = y;
124 LlneEngine(pict,x,y,x + downX,y + downY,O,TracePiston);
125 bothX[numberOfLegsl = xDistance;
126 if (valid) 127 topYlnumberOfLegsJ = lastY;
128 else 129 topY[numberOfLegsl = HIT rHE BOX;

131 stopDistance = boxBaseDistance;
132 startX = x+downX;
133 startY = y+downY;
134 LlneEngine(pia,x + downX,y + downY,x,y,O,TracePiston);
if(valid) 136 baseYlnumberOfLegs~ = lastY;
1 37 else 138 baseY[numberOfLegsl = HIT THE BOX;
39 numberOfLegs+ +;
~40 141 }
142 return test;
143 }

145 /~Thisfunction,findstheupperandlowercontours~ ,ond;.-~
146 ~ to a word wi thi n a boundi ng box ~/
147 void'~ ' 'ih~ r~cau~epict,Boxbox, 148 Dictionarydia,intdictEntry) 149 {
I SO DPoint normalVeaor;
I S I DPoint80dy temp;
152 double boxTop,box8ase;
153 int rightX,rightY;

155 lineVector = PolarroCartesian(box->angle,1);
156 normalVector = Normal(lineVector);
157 temp.x = box->x;
158 temp.y = box->y;
IS9 boxTop = Dot(&temp,normalVector);
160 box->pageY = irint(boxTop);
161 boxBase = boxTop + box->height;
Ccpyright~ 1991 XeroxCorporation All Rights Reserved Section D APPEND~X Page 229 163 20~7969~
164 /- CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE ~/
~65 boxTopDistance = boxBase-boxrop;
166 boxBaseDistance = boxBase-boxTop;
167 t~ CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE ~1 169 downX = box->heigh2~cos(box->angle+M P112);
170 downY = box~>height-sln(box->angle+l/l_P112);

172 rightX = box->wldth~cos(box->angle);
173 rightY = box->wldthtsin(box->angle);

175 numberOfLegs = 0;
176 leftDistance = Dot(&temp,lineVector);
177 box->pageX = irlnt(leftDistance);
178 #ifdef foo 179 malloc verify();
1 8û #end i f 18~ LlneEngine(pict,box->x,box->y, 18Z box->x + rightX,box->y + rightY,û, 183 ShellPiston);

185 ~ CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE ~/
186 {
187 int i;
188 for (i = û;i <numberOfLegs; + + i) {
189 if (~(topY + i)l = HIT THE_BOX) 190 ~(topY+i) + = boxrop;
191 if (~(baseY + i)l = HIT THE BOX) 192 ~(baseY + i) = boxBase~(baseY + i);
193 }
194 }
195 /~ CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE CHANGE ~1 197 #ifdef foo 198 malloc verify();
199 #endif 2û0 StoreRawOutlinePair(dia,diaEntry,box,bothX,topY, 201 baseY,numberOfLegs);

204 BOOLEAN OnABaseLine(Box box,List baseLinePoints) 205 {
206 DPoint lineVeaor,normalVector;
207 DPointBody temp;
208 double boxTnp,~ ~ top ha~
209 PolnttopPoint,basePoint;

211 lineVector = PolarToCartesian(box->angle,1);
212 normalVector = ~ 1(" ,eVe~to,);
213 temp.x = box->x;
214 temp.y = box->y;
215 boxTop = Dot(normalVector,&temp);
216 boxBase = boxTop+box->helght;
Copyright~ 1991 XeroxCorporation Ali Rights Reserved Section D APPEN Dl X Pase 2 3 0 2'8 while(!endp(baseLlnePoints)){
219 topPoint = pop(baseLinePo~nts);
220 basePolnt = pop(baseLlnePoints); ~ ~ 7 ~ ~ ~ 3 221 temp.x = topPoint->x;
222 temp.y = topPoint->y;
223 top = Dot(normalVector,&temp);
224 temp.x = basePoint->x;
225 temp.y = basePolnt->y;
226 base = Dot(normalVector,& emp);

228 If ((boxTop = top && boxTop < = base~ box top is between /
229 (boxBase> = top && box3ase < = base) ~ box bottom is between ~/
230 (top > = boxTop && top < = boxBase~ both lines inside box ~/
231 return TRUE
232 }
233 return FALSE;
234 }

236 BOOLEAN BoxToShell(Picture pict,Box box,List baseLinePoints, 237 Dictionary dict,int dictEntry) 238 {
239 Point topPoint,bott-,,rui"~, 24~ if (OnABaseLin~(hnY,h~ -~l inePoints~) {
242 MakeShell(pi-t,hoY, i~t.di~tFntry);
243 return TRUE;
244 }
245 else 246 return FALSE;
247 }

249 #defineMAX SHAPES 100û
25û void Bar80xLis~Picture pict,List boxList,List baseLinePoints, 251 char ~filename,char infoStrlng, NormallzationDescriptor ~nd) 252 {
253 Dictionarydict;
254 intcount = 0;
255 long int location;

257 dict = NewDict(MAX SHAPES);
258 dict->infoString = in~oString;

260 while (len~r(h~ t))~
261 #ifdef foo 262 if (BoxToShell(pict, 263 (~nY)rop(bt Y~ i~t).
264 baseLinePoints, 265 dict, 266 count)) 267 + I count;
268 #endif 269 /~ Change 818/91 27û ~ All boxes ~re stored i n the dictionary.
271 ~Thepostprocessingstageinne,.,o,~l~.o.,l,.cwillweedoutboxes~/
CopyricJht~ 1991 XeroxCorporation All Rlghts Resen~ed 5ectlon D APPENDIX Page 231 272MakeShell(plct,(Box~pop(boxLlst),dict,count); 2 ~ 7 ~ 9 6 9 273+ ~count;
2741'~ End of change 8/8191 '/
275if (count> = MAX SHAPES) {
276printf("Maximum dictiondry si~e exceeded \n");
277printf("lgnoringrestofshapes.~n");
278break;
279}
280}
281dict->numberOfEntri~s = count;
282PageStatistics(dict,"statistics'',nd);
283/~ PostProcess(dict); ~/
284WrlteDictionary(dict,filename);
285}

Copyright ~199~ Xerox Corporation All Rights Reserved Sectlc~n D . APPENDIX Page 232 Jan11 17:071991 newDIff2c ~77969 #include <stdio.h>
2 #inciude"bcolean.h"
3 #include"types.h"
4 #include "e~ror.h"
s #include"pict.h"
6 #include''dict.h"
7 #Include"diff.h"

9 /' Given the names of two dictionary files, compute the squared difference lû 'betweeneverypalrofshapesinthecrossproductofthedictionaries.
11 ~ The result is a matrix printed to stdout. rhe wldth and helght are 12 ' followed by the matrix entries in row major order. rhe output is in 13 'asciitofacilitatereadingbyaSymbolics.'/
14 Plcture CompareDictionarles(char 'filel,char 'file2) {
~6 Dictionarydictl,dict2;
17 Plcture pict;
18 Int x,y;
19 dictl = ReadDictionary(filel);/'height'/
2û dict2 = ReadDictionary(file2);/'wldth'/
21 plCt - new pict~dict2->numberOfEntrles, 22 dictl->numberOfEntries, 23 32);
24 for(y=0;ycpict->height; + +y) for(x=0:x<pict->width; + +x){
26 printf("(~d,%d)'',y,x);
27 '((float ')(pict- >data) + pict- >width'y + x) =
28 DiffPair('(dictl->outlines + y), 29 '(dict2- >outlines + x));
}
31 return pict;
32 }

34 void WritePictureAsAscii(Picture pict,char 'filename) {
36 FILE ~fp;
37 intx,y;
38 i nt count = 1;
39 if((fp = ~ "(i'''~, :,"w"))= = NULL) DoError("Writ~PictureAsAscii: error openlng output file\n",NULL);
41 fprintfffp,"%d\n%d~n",pict->wldth,pict->helght);
42 for(y=0;y<pict->heiqht; + +y) 43 for(x=0;x<pict->width;++x){
44 fprintf(fp,"%f ",'(((float ')pict->data) ~ + ));
4s i f ( !((count + + )~ S)) 46 fprintf(fp,"\n");
47 }
48 fprintf(fp,"\n");
49 fclose(fp);
}
Copyright~ 1991 XeroxCorporation All Rlghts Reserved Se~tl~n D APPENDIX Page 233 Aug 2617:201991 newMaln c 2 0 7 7 ~ 6 ~ ~
#include <stdio.h~
#include <values.h~
3 #incl ude < math.h 4 #include"misc.h"
Yinclude''boolean.h'' 6 #include "error h"
7 #include"types.h 8 #include"pl,h'' 9 #include''lists.h"
#include''lines.h'' 11 iYinclude"orient.h"
12 #include"baselines.h"
13 .Yinc~ude "bloblfy h"
14 #include"boxes.h"
#include"dlct.h"
16 #incl ude "di ff.h "
17 #include"newContour.h"
18 #include"numbers.h"

#definerRY
21 #ifdef TR~' 22 Pictu-e thePict;
23 #endif void D~ " e Li nes(Picture pict, List poi ntList, doubl e angle) 26 {
27 int maxLength;
28 int xc,yc,xBot,xrop,yBot,yTop;
29 Polnt temp;
float xZ,y2,x3,y3;
31 inti,len;
32 maxLength = pict-~width~pi->height;
33 len = ListLength(pointList);
34 pop(pointList1;
for(i = 1;i<1erl-1;i + =2){
36 temp = pop(pointList~;
37 xTop = temp->x;
38 yTop = temp-~y;
39 temp = pop(pointList);
xBot ~ t~mp->x;
41 yBot = temp->y;
42 xc = (xBot I xTop)/2;
43 yc = (yBot I yTop)12;
44 x2 = xc ~ maxLength~cos(angie);
y2 = yc ~ maxLength~sin(angle);
46 x3 = xc-maxLength~cos(angle);
47 y3 = yc-maxLength~sin(angle);
48 DrawLine(pict,xc,yc,(int)x2,(int)y2,0);
49 DrawLine(pict,xc,yc,(int)x3,(int)y3,0);
}
51 }

Copyright~ 199t XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 231 53 vold Draw80xList(Plcture olct,Llst boxLIsl) 2 ~ 7 7 54 {
while (!endp(boxList)) {
56 Draw30x(pict,(Box)pop(boxLlst));
57 }
58 }

void ~abelShapes(Picture pict,Dictionary dict) 6~ ~
62 int i;
63 80x box;

for(i=0;i<dict->numberOfEntries; + +i){
66 box = ('(dict->outlines + I))->box;
67 DrawColotBox(pict,box,3);
68 DrawNumber(pict,box-~x,box->y,2,(flo~t)box->helghV2,1);
69 }
}
7~
72 double FixAngle(double angle) 73 {
74 if (angle > M_P112 && angle c ~.S~M Pl) return angle-M _ Pl;
76 else 77 return angle;
78 }

8û int Scan~ntArg(int argc,chat ''argv,int index) 8~ {
82 if (index<arg~) 83 return atoi(argv[indexl);
84 else DoError(" Expe~ted an integer argument\n" ,N U LL);
86 }

88 float S~anFloatArg(int arg~,~har ~'argv,lnt index) 89 {
if (index<arg~) 9~ returnatof(argv[index]);
92 else 93 DoError("Exp~ted a floating point argument~n",NULL);
94 }
96 char ~S~anStringArg(int arg~,~har ~'argv,int index) 9~ {
98 if (index<arg~) 99 return argv[indexl;
100 else 101 DoError(''Expected a string argument\n",NULL);
~02 }
~03 ~04 void main(argc,argv) S int argc;
~û6 char ''argv;
~07 {
~opyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 235 108char-lnflle; 2077969 109 intcoarseDirections,coarseSamples,fineDIrections,fineSamples;
t 10 Picture pict,newPict,finalPict;
111 floatcoarseAngle,mediumAngle,fineAngle:
1~2 floatcoa~seError,mediumError,fineError;
113L15t basclines,boxList;
1 t4 int maskWidth;
115float blobThreshold;
116int i;
117char tshapesFile, d,~... '` i ' ,~., ile;
118 char draw30xesFile,'plotFile,-plotOrlentfile:
119 char-drawColo.E ~ e,-drawBlobsFile;
120 char flag;
121 BOOLEAN doorientation~doBaselirl~do3rly~ d~chapes~draw3aselines~drawBoxes:
122 BOOLEAN plotBaselines,plotOrientatlon,drawColorBoxes,drawBlobs:

noXl le:gl.~.J",~,noAs~end~ .",.,dontOrientation,doBlobThreshol-l,c' ~ bWidth 124 Normall~ationDescriptornd;

126 DefArg~ %s, infile ,8infile);
127 DefOption( -orientation % f, -orientatlon (page orlentation in radians)", 128 &dontOrientation,&fineAngle);
129 DefOption("-findOrientation","-findOrientation",&doOrientation);
130 DefOptlon("-plotOrientation /Os ', -plotOrientatlon (file top plot xgraph format image to) ", 131 &plotOrientation,&plotOrientFile) 132 DefOption("-maskWidth /cd'',''-maskWidth (integer half mask width)", 133 &doMaskWidth,&maskWidth);
134 DefOption("-blobThreshold %f","-blobThreshold (float onloff threshold)", ~35 &doBlobThreshold,&blobThreshold):
136 DefOption("-drawBlobs %s","-drawBlobs (file to output image to)",&dravdBl~hs,8 ' ~..310LsFile);
137 DefOption("-J- ~ ,%s~ -J-_ E ' ,~,(filetooutputimage to) " ,&.~, ~ .. 3~s~
138 8~JI ~ .. ;le);
139 DefOptlon("-plotBaselines'~s","-plotBaselines(filetoplotxgrapghformatbaselinesto)", 140 &plot8aselin~,&r' ~~'e);
~41 DefOption("-drawBoxes /Os","-drawBoxes (file to output image to)",&J,~. E~ ,~ ' E r;'e);
142 DefOption("-shapeFunctions%s",''-shapeFunctions(filetooutputshapefunctionsto)", t43 &doShapff,&jh, ciR~);
144 DefOption("~ t.JS~" %s","-annotatedShapes(filetooutputimageto)", 145 &drawColu-E ,l~'_ ColorBoxesFile):
146 DefOption~"-n ~ .,","-noAs~c"cl~ "",&noAs~c-~d~
147 DefOption~"-noXll~ r.~l.,","-noXHeightNorm",&noXHe;~ilil'~ 1");

149 i=2;
lSO coarseDirections = 72;
151 coarseSamples = 400;
152 fineDirections = 40;
153 fi" ' ,j~l~. = 10;
154 maskWidth = 3;
155 blobThreshold = 0.01;

1 57 ScanArgs(argc,argv);
Copyright~ 1991 XeroxCorporation All Rlghts Reserved Sectlon D APPE N Dl X Pag e 2 3 6 58 If (dontOrlentatlon) ~59 doOrlentation = FALSE, 16l nd.noXl~e.~ alize s ncX~lr,,~,~tr.~""; 2 ~ 7 7 ~ ~ 9 162 nd.n~'~s~ rr~: ",alize = noAscenderNorm;

164 printf~"Loading %s . . .\n",infile);
165 pict = load pict(infile);
~66 if (pict->depth ! = 1) 167 DoError("error:onlydepth I issupported~n'',NULL);

169 if(drawBaselineslldrawBoxes) 170 hnalPict = new_pict(pl~t->width,pict->height,pict->depth);

172 if (doOrientation) {
173 #defineNUMBER OF ANGLES 180 174 #defineSAMPLES PER ANGLE 10 175 #defineBlN ERR~R4 176 printf("Fin~ngcoarseor~entation \n"~;
177 coarseAnsle = NewFine(pict,SAMPLES PER ANGLE,NUMBER OF ANGLES, 178 ' 0,M Pl,NULL);
179 coarseError = (M Pl-0~/NUMBER OF ANGLES;
180 printf( Coarseangle: ~/,f(Ofl~n ,coarseAngie,coarseAngle/M Pl~80~;
181 printf("Coarseerror: ~f(~fl~n",coarseError,coarseError/M_P~180~;

183 mediumAngle = NewFine(pict,SAMPLES PER ANGLE,NUM3ER OF ANGLES, ~84 coarseAngle-BlN ERRORtcoarseError, 185 coarseAngle I BIN ERROR~coarseError, 186 NULL) 187 mediumError = 2~BIN ERROR~.ua~s. C.,u,/NUMBER OF ANGLES;
188 printf("Mediumangle %f(%fl~n",mediumAngle,medrumAngle/M Pl~180~;
189 printf("Medium error: ~,f(%fl~n",mediumError,mediumError/M _ Pl' 180~;

192 fineAngle = NewFine(pict,SAMPLES PER ANGLE,NUMBER OF ANGLES, 193 mediumAngle-15~ d,.. ,C.,u~,mediumAngl~ I IS~mediumError, 194 plotOrientFile~;
19S fineError = 30~mediumError/NUMBER OF ANGLES;
196 fineAngle = FixAngle(fineAngle~;
197 printf("Fineangle: %f(%fl~n'',fineAngle,fineAngle/M P1~180);
198 printf("Fineerror: %f(/Ofl~n",fineError,fineErrorlM Pl~180);
199 }

201 printf("Adjusted angle: %If\n",fineAngle);

203 #ifdef foo 204 printf("Finding baselines\n");
205 baselines = BaseLines(pict,fineAngle,plotBaselines?plotFile:NULL);

207 if (,~- - 3.. ,~1.. ,~;) ~
208 CopyPicture(finalPict,pict);
209 DrawBaseLines(finalPict,baselines,fineAngle~;
210 write pict(drawBaselinffFile,finalPict~;
211 }

Copyright~ Ig91 Xerol Corporation All Rights Reserved Section D . APPENDIX Pdge 237 213 prlntf("Bloblfylng~n") 214 newlPfct = Bloblfy(pict,maskWidth,blobThreshold); 2 ~ ~ 7 9 6 216 printf~"NewBlobify~n'');
217 /- newPict = ~'~w31OL,i~y(pict,maskWidth,blobThreshold,fineAngle); 1 218 newPict = Blobify(pict,maskWidth,blobThreshold);
219 prlntf("Finding baselines\n");
220 baselines = BaseLines(newPict,fineAngle,plotBaselines?plotfile:NULL);
221 if ~ ;) {
222 CopyPicture(finalPict,pict);
223 DrawBaseLines~finalPict,baselines,fineAngle);
224 write _ plct(d,~ .rile,finalPict);
225 }

228 D,~ nes(newPict,baselines,fineAngle);
229 if (draw310bs) 230 write plct(drawBlobsFile,newPict);
231 printf(~Findins boxes~n");
232 boxList = r;ndBo,d~.~(newPict,fineAnsle);

234 i f (drawBoxes) {
235 CopyPicture(finalPict,pict);
236 DrawBoxList~finalPict,boxList);
23~ write _ pict(drawBoxesFile,finalPict);
238 }

240 if (doShapes) {
241 ColorMap cmap;
242 int x,y;

244 If (drawColorBoxes) {
245 thePict = new pict(pict->width,pict->heisht,8);
246 cmap = NewColorMap(6); 1' black, white, and 16 colors /
247 WriteColorValue(cmap,0,0,128,0); /- Olive ~/
248 WriteColorValu~(cmap,l,0,0,0); /~ 31ack /
249 WriteColorValue(crr~r,7.7s~i~7~5~7~s); /- White /
250 WriteColorValue(cmap,3,0,0,255); /- Blue ~/
251 WriteColorValue(cmap,4,255,255,80); /- Yellow /
252 WriteColorValue(cmap,5,128,0,0); /~ Blood ~/
253 thePict-~cmap = cmap;
254 for(y~O;y~pict-~heisht; ~ ~y) 255 for(x=O;x<pict->width; ~ I x) 256 Wli~ rict,x,y,R~adPixel(pict,x,y)?0:1);
257 }
258 else 259 thePict = NULL; /~ Important /

261 printf("Tracins outlines\n");
262 BarBoxLlst(pi-t h~7~ ist~hAcrlines~shapesFile~ArgListTostring(argc~argv)~&nd);

264 if (drawColorBoxes) {
265 Dictionary dict;

267 dict = ReadDictiona~ ap~ir;le);
Copyrisht 1991 XeroxCorporation All RlghtsReserved Section D APPENDIX P~ge 238 68 LabelShapes(thePi~t,dict): 2 ~ 7 7 ~69 wrlte_pi~t(drawColor80xesFlle,thePict);
270 }
271 }
272 }

Copyright~ 1991 XeroxCorporation All Rights Reser~led Sec on D APPENDIX Page 239 Jan ~1 17.071991 numbers.c 2~7 ~ 9 ~include "stdio.h"
2 ~linclude"bool~an.h'' 3 #in~lude"pict.h"
4 ~include''lines.h"
s 6 static float localScale;
7 static int localColor;
8 static int localX;
9 static int localY;
static Picture localPict;
1~
12 void DrawSegment(floaty1,floatxl,floaty2,floatx2) 13 {
14 DrawLine(localPict,irint(localX + x1 ~localScale), irint~,l,ocalY + yl ~localScale), ~6 irint(localX + x2~10calScale), 17 irint(localY + y2~10calScale),localColor);
18 }

void DrawO(Picture pict, int x, int y, int color,float scale) 22 localPict = pict;
23 localScale = scale;
24 localColor = color;
localX = x;
26 localY = y;
27 D~ S~ Jl(0,0,0,1);
28 D.~.. " ,.. ,~.ll(l,O,l,l);
29 Dl~,S~ (O,O,l,O);
D rawSegm ent(O, I ,1,1 );
31 }

33 void Drawl(Picturepict, intx, inty, intcolor,floatscale) 34 {
3s localPict = pict;
36 localScale = scale;
37 localColor = color;
38 localX = x;
39 localY = y;
D- S ~ 0,0 S,l,.S);
41 }

43 void Draw2(Pi cture pict, i nt x, i nt y, i nt col or, fl oat scal e) 44 {
4s localPict = pict;
46 localScale = scale;
47 localColor = color;
48 localX = x;
49 localY = y;
Dl_.. Se~".L.,L(d,O,O,l);
51 D-_.. 5~7,.,~.lL(O,l,.S,l);
52 D~ S~ EIIL( S~1~ S~U);
Copyright 1991 XeroxCorporation All Righ~s Reserved Sectlon D APPENDIX Pdge 2~0 3 Dl_.. 'c~ t( S,O,l,O);
4 Dl_.. '~ (1,0,1,I);
55 }

58 voidDraw3(Picturepict,intx,inty,intcolor,floatscale) 2~77969 59 localPict = pict localScale = scale;
61 localColor = color;
62 localX = x;
63 localY = y;
64 Dr3~ 'c,tl"~ ,~(0,0,0,1);
Dl_.. '~ (0,1,1,1);
66 Dl_.. 'c~ (1,0,1,1);
67 Dl ~ " L( S,O, S, ~ );
68 }

void Draw4(Picture pict, int x, int y, int color,float scale) 71 {
72 localPict = pict;
73 lo~alScale = scale;
74 localColor = color;
localX = x;
76 localY = y;
77 D,_~Se~",a.,~(0,0, S,0);
78 D,_.. e~ (0,1,1,1);
79 D,_ASe~ (.S,0, S,1);

82 voidDrawS(Picturepict,intx,inty,intcolor,floatscale) 83 {
84 localPict = pict;
localScale = scale;
86 localColor = color;
87 localX = x;
88 localY = y;
89 Dl _ . . S~,. " ~ 0,0,0,1 );
Dl_.. '~ O,O,.S,0);
91 Dl_.. ,c~ ,.5,1,.5,0);
92 Dl_.. S, ~.5,1,1,1);
93 Dl S, /t 1 ,0, 1 , 1 );
94 }
96 void Draw6(Picture pict, int x, int y, int color,float scale) 97 {
98 localPict = pict;
99 localScale = scale;
100 localColor = color;
101 localX = x;
102 localY = y;
103 Dl_ 5~ "~(0,0,0,1);
104 Dl Sr~ "~(0,0,1,0);
105 Dl S~ "~(.S,I,.S,0);
106 D-_.. Se~ "~(.5,1,1,1);
107 Dl ASe~ "l(1,0,1,1);
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 241 ~77~9 108 }

110 void Draw7(Picture pict, int x, int y, Int color,float scale) 111 {
112 localPict = pict;
113 localScale = scaie;
114 localColor = color;
llS localX = x;
116 localY = y;
117 Dl~ S~ -,l(O,O,O,l);
118 Dr S~",~ O,l,l,l);
119 }

121 voidDraw8(Picturepict,intx,inty,intcolor,floatscale) lZ2 {
123 localPict = pict;
124 localScale = scale;
125 localColor = color;
126 localX = x;
127 localY = y;
128 D,~..e~ "~(O,O,O,~);
129 D, S~,~rr,~"L(O,O,I,O);
130 D.3~ Sey,~ L(l,O,~,t);
131 Dl~ yl~l~.lL( sll~ 5~o);
132 D, d .e~"~ l(O, l, l, l );
133 }

135 voidDraw9(Picturepict,intx,inty,intcolor,floatscale) 136 {
137 localPict = pict;
138 localScale = scale;
139 localColor = color;
140 localX = x;
141 localY = y;
142 Dl Sc~n~ l(O,O,O,l);
143 Dl~ S~y~,ll(.S,O,.S,l);
1 D~ S~yn,~";(O,O,.S,O);
145 D~ SL~ II(O~
146 }

148 typedefvoidDrFct~Picturepict,intx,inty,lntco~or,floatscale);
~49 ISO DrFct~DrawFunctionsO = {DrawO,Drawl,Draw2,Draw3,Draw4,DrawS,Draw6, l S l Draw7, Draw8, Draw9};

153 void D, ~ cture pict, int x, int y, int color. float scale, int n) ~54 {
155 t~D~awFunctions[nl)(pict,x,y,colo~,scale);
156 }

158 void DrawNumber(Picture pict, int x, int y, int color, float scale, int n) 159 {
160 chars~100];
161 char ~ptr;

Copyright ~1991 Xerox Corporation All Rights Reserved Sectlc~n D APPENDIX Pdge 212 ~63 sprlntf(s,"~'~d",n); 2 0 7 7 9 6 9 64 ptr = s;
~65 while (~ptr ! = '\0') {
166 DrawNumeral(pict,x,y,color,scale,~ptr-'0');
167 x I = irint(scale~l S);
168 ptr I ~;
~69 }
~70 }
~7~
172 #ifdef TRYMAIN
173 maln() 174 {
175 Picture plct;
176 pict = new pict~400,200,~);
~77 DrawNumber(pict,50,50,~,20,~2345);
178 DrawNumber(plct,50,100,1,10,67890~;
179 write _ plct(''junkfile.image'',pict~;
180 }
181 #endlf Copyright9 199~ XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 2'L3 Jul 218481991 orlentc 2Q7796~ ~
#include <stdio h~
2 #include <values h>
3 #include <math h~
4 #include ''misc h"
S #include ''boolean h'' 6 # i ncl ude " pi ct h "
7 #include "orient h"
8 #include "lines h'' 2 #defineABS(x) (((x)<û)?-(x) (x)) ~ 3 extern long random();

1 s int RandomCoordinate(int maxValue~

17 return(float)(random()&Oxffffl-maxValue/Oxffff;
18 ?

void fi~, dv",~dg~ ri~ ~ri~L~re pict,int x, int y) 21 {
22 while(TRUE) {
23 x = Randomcovld;llale(pict->v~idth);
24 y = RandomCov J;l~ e(p;ct-~height);
if (ReadPixel(pict,-x,~y)) 26 if (!(ReadPix~l(pict,-x + 1,-y) &&
27 ReadPixel(pict,-x-1,-y) &&
28 ReadPixel(pi,-x,-y + 1) &&
29 ReadPixel(pict,-x,-y-1) &&
ReadPixel(pict,-x + 1,-y + 1) &&
31 ReadPixel(pict,-x-1,-y-1) &&
32 ReadPixel(pict,-x + 1,-y-1) &&
33 ReadPixel(pict,-x-l,-y + I))) 34 return;
}

37 }

39 /'' #define 5YMTHRESH 4 /
#define SYMTHRESH 0 17453278 41 800LEAN ri 'E ' '' ~(rlv.,t -distancff, int coarseDirections, float step, 42 float v ;_, La~;v~l) 43 {
44 int i,j,minlndex,min21ndex;
into"_,Lclvll~, v, 46 ~loat minValue,min2Value;
47 intmax8inError = irint(SYMTHRE5H/step);

49 minlndex = 0;
SO minValue = distances[O];
51 ~or(i =O;i<coarseDirectioGs; + +i) 52 if (distances[i] < minValue) {
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 244 53 mlnValue = distances~l];
~s4 minlndex=i; 2~79~
56 /- Na,v verify that there is another mi ni ma M_Pl away /

58 min21ndex = (minlndex+coarseDirections/4)%coarseDirections;
S9 min2Value = distanceslmin21ndexl;
for(i=û,j=min21ndex;i<coarseDirections/2; + +i,j = (j + 1)%coarseDirections) 61 if (distances[jl ~ min2Value) {
62 min2Value = distances[jl;
63 min21ndex = j;
64 }
orientationError = AeS((min21ndex-m,nl,ldeA)~' coarseDirections) -66 coarseDirections/2;
67 U~ Ldliu"[r,u~ = A35(orientationError);
68 if (Oli_ llallOI~CIIOI <maxBinError) {
69 'orientation = ","~lndr~strp;
return TRUE
71 } else {
72 printf("Orientation error %d %3 3f\n'',L),,_ ,t~1lon~
73 o"_ ,t~lionC,,or Sle,~ Pl/2-360);
74 printf("%3 3f %3 3f %3 3f %3 3f\n'',mlnlndex-step,minValue, 7s min21ndex~step,min2Value);
76 return FALSE;
77 }
78 }

8û float Fine(Picture pict,int fineSamples, int fineDirections, 81 int coarseDirections, float coarseAngle, char plotFile) 82 {
83 float coarseError;
84 int x,y;
float x2,y2;
86 int i,j;
87 float 'counters;
88 float step,angle;
89 float maxAngle;
go float maxValue;
91 float maxLength;
92 FILE outfile;

94 counters I (float ~)calloc~fineDirections,sizeof(float));
9S if (counters 5 - NULL) {
96 printf~"Fine cannotallocatememory\n");
97 exit(-l);
98 }
99 /- coarseError = 2-(5YMTHRESH + 1)-2^M_Pl/coarseDirections; ~/
100 coarseError = 2-5YMTHRESH;
~ 01 step = ~ù~" ,e:" u,/ri,le~irections;
102 printf("fine +/- %3 3~n'',fineDirections/2-step);

104 maxLength = sqrt((double)(pict-~width-pict-~width +
105 pict->height-pict->height));
106 for(i =0;i<fineSamples; + +i){
107 R~ndu,,~C~ I~Pi~el(pict,&x,&y);
Cop~right~ 1991 XeroxCûrpûration All Rights Reserved Se~t~on D APPEN :)IX Page 245 ~08angle = -fineDirections/l~step+~oarseAngle;
109for(j =0;j<fineDirections: + +j,angle + =step) { 2 9 7 7 g ~ 9 110x2 = x + maxLength~cos(angle);
111y2 = y + maxLength~sin(angle);
112countersGI + = CountLlne(pict,x,y,(int)x2,(int)y2);
113 }
114 }

116angle = -fineDirections/2~step+coarseAngle;
117maxAngle = angle;
118maxValue = counterslOI;
119for(i=0;i<fineDirections;+ +i,angle + = step){
120/~ printf("%3.3f: %3.3f\n",angle,counters[i]~
121if (counters[i]~maxValue) 122maxAngle = angle;
123maxValue = counters[i];
124 }
125 }

t 271~ Plot the orientation graph if requested '/
128angie = -fineDirections/2'step + coarseAngle;
129if (angle < 0) 130angle + = 2~M Pl;
131if (plotFil~l = NUr) {
132printf("Opening fine orientation plot file\n"), 133if ((outfile = fopen(plotFile,"a'')) = = NULL) ~
134printf("Erroropeningfineorientationplotfile.~n'');
135exit(-l);
136 }
137for(i =0;i<fineDirections; + +i, angle + = step) 138fprintf(outfile,"%f %f\n",fmod(angle,2'M Pl),counters[il);
139fprintf(outfile,"\"FineDi"~.~,e,~n\n");
140fclose(outfile);
141printf(" Done writing fine orientation plot file \n ");
142 }

145return maxAngle;
146 }

148floatNewFine(Pictur~pict,intfineSamples,lntfineDirections, 149floatangl~Start,floatangleEnd, char plotFile) 150 {
lSlintx,y;
152float x2,y2:
153i nt i ,j ;
154Float ~counters;
155floatstep,angle;
156float maxAngle;
157float maxValue;
158float maxLength;
l S9FILE ~outfile;

161counters = (float~)calloc(fineDirections,sl2eof(float));
162if(counters = = NULL){
Copyright 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX ' Pi~ge 246 163 printf( Fine cannotallo~atememory~n");
~ 1 64 exit( 1 ); 2 0 ~ 7 ~ ~ 9 167 step = A85(angleEnd-angleStart)/fineDirections 169 maxLength = sqrt~double~(pict->wldth-pict->width +
170 pict-~height-pict->height));
t71 for(i=0;1<fineSamples;~+i){
172 Rando m Ed gePi xel ~pict, &x, &y);
173 angle = angleStart;
174 for~j=0 j<fineDirections + +j){
175 angle = fmod~angle,2~M P~);
176 x2 = x + maxLength-cos~ngle) 177 y2 = y + maxLength-sin~angle);
178 counters[jl + = CountLine~pict,x,y,(int)x2,(int)y2) 179 angle + = step;
180 }
181 }

183 angle = angleStart 184 maxAngle = angle;
185 maxValue = counterslûl;
186 for(i =0;i<fineDirections; + +i){
t87 angle = fmod(angle,2~M Pl);
188 if (counters[iJ >maxValue~
189 maxAngle = angle;
190 maxValue = counters[i];
191 }
192 angle + = step;
193 }
~94 printf("Orientationisat%f(%fl~n",maxAr~gl~ n~jle/21M_P1~36û);

196 /~ Plot the orientation graph if requested 1 197 if [plotFile) {
198 printf("Openingfineorientationplotfile\n");
199 if ((outfile = fopen(plotFile,"w")) = = NULL) {
200 printf("Erroropeningfineorientationplotfile\n"~;
2ûl exit(-l);
202 }
203 angle = angleStart;
204 for(i=0;i<fineDireaions;++i){
20s angle 5 fmod(angle,2~M Pl);
206 fprintf(outfile,"%f %f\n",angle,counters[il);
2û7 angle + = step;
208 }
209 fprintf(outfile,''\"Fine Distances\n\n'');
210 fclose(outfile);
211 printf("Donewritingfineorientationplotfile\n'');
212 }
213 return maxAngle;
214 }

Copyright~ 1991 XeroxCorporation All Rights Reserved Sectl on 1:) APPE 1~1 DIX Pag e 247 JanlS15:~2199~ ove~layc 2~7 #include <stdio.h>
2 #include Cmath.h>
3 #include"boolean.h"
4 #i nclude " pict.h '' s 6 main(argc, argv) 7 int argc;
8 char 'argv[];
9 {
tO char~inFilel,~inFile2,'outFile;
I l Picture pictl ,pict2,finalPict;
12 ColorMapcmap;
13 int %,y;

lS if(argc!= 4) 16 {
17 printf("~nUsage: %sinfilel infile2outfile\n~n", 18 argv[01);
19 exit(0);
}

22 inFilel = argv[~ getargs~l 23 inFile2 = argY[21;
24 outFile = argv[3];
26 pictl = load pict(inFil~1);
27 pict2 = load pict(inFile2);
28 if((pictl->depth!= l)¦¦(pict2->depthl= 1)) 29 DoError( overlay- onlydepth 1 supported.\n ,NULL);
if ((pictl->width ! = pict2->width)¦¦~pictl->height ! = pia2->height)) 31 DoError("overlay: imagesmustbethesamesize\n",NU~L);

33 finalPict = new pict(pictl->width,pictl->height,8);
34 cmap = NewCol~rMap(3);
WriteColorValue(cmap,0,0,0,0); /~ Black ~/
36 WriteColorValue(cmap,1,0,128,0); /~ Olive /
37 WriteColorValue(cr~p~ n~s5~0); /~ Green '/
38 finalPia->cmap ~ cmap;

for (y = û;ycpict1->height; 1 ~ y) 41 for(x=O;xcpial->width; ~ t X) 42 if (F 'P; ~ ;al,x,y)) 43 \fJ,;~PiA~l(r;" '~;t,x,y,2);
44 else if (ReadPixel(pict2,x,y)) WritePixel(finalPict,x,y,l);

47 write _ pict(outFile,finalPict);
48 }
Copyright ~1991 Xerox Corporation All Rights Reserved Section D APPENDiX Page 218 ~ul ~ 13:451991 pagestats.c #include <stdio.h> 2 ~ 7 ~ 9 6 9 2 #include <math.h>
3 #include''boolean.h"
4 #include"types.h"
S #include"error.h'' 6 #include"pict.h"
7 #include"dict.h"

9 #define UP O
lû #define DOWN ~
1~ typedef int Direction:
~2 13 extern Picture thePict;
~4 ~S void StoreRawOut~inePair(Dictionarydict, intdictEntry, 16 Box box,int ~bothX,int ~topY, int ~baseY, 7 int numberOfLegs) ~8 {
19 RawOutlinePairtemp;
int i;
2~ int ~xCursor,~topCursor,-bottomCursor;

23 temp = (RawOu~ era.. )- " '~,sizeof(RawOutlin~r3;,BoJ~)), 24 if (temp = = NULL) DoError("StoreRawOutlinePair: cannot allocate space~n'',NULL~;

27 lemp->box = box;
28 temp->numberOfLegs = numb~rOfLegs;

temp->x = (int ~)calloc(temp->numberOfLegs,slzeof(int)):
31 temp->top = (int-)calloc(temp->numberOfLegs,si2eof(int));
32 temp->bottom = (int-)calloc(temp->numberOfLegs,sizeof(int));
33 if((temp->x = = NULL)¦¦
34 (temp->top = = NULL)¦¦
(temp->bottom = = NULL)) 36 DoError("StoreRawOutlinePair: cannot allocate space\n",NULL);

38 xCursor = temp->x;
39 topCursor = temp->top;
bottomCursor = temp-~bottom;

42 for(i=O;i<numberOfLegs; + +i) {
43 ~xCursor + + = ~bothX ~ +;
44 'topCursor+ + = ~topY+ +;
~bottomCursor ~ + = ~baseY + +;
46 }
47 ~(di->rawOutlines+dictEntry) = temp;
48 }

SO void StoreOutlinePair(Dictionary di, int diEntry, St int middleLine,int fontXHeight) 52 {
CopyricJht~ 1991 XeroxCorporation All Rights Reserved _ Sectlon D APPENDIX Page 219 53 RawOutllnePalr raw;
54 OutlinePalrtemp;
SS inti,numberOfLegs; 2~77 56 int y;
57 intoffset;
58 int~xSCursor,'topSCursor,'bottomSCursor;
S9 float 'xDCursor,-topDCursor,'bottomDCursor;
float 'xCursor,'topCursor,'bottomCursor;
61 Int left,right;
62 float foffset;

64 raw = ~(dict->rawOutlines+dictEntry);
66 temp = ~OutlinePair)calloc~1,sizeof~OutlinePalrBody));
67 If ~temp = = NULL) 68 DoError( StoreOutlinePair: cannotallocatespace\n ,NULL);

temp->x_i(float')calloc(raw->numberOfLegs,si2eof(float));
71 temp->top = (float ~)calloc(raw->numberOfLegs,sizeof~float));
72 temp->bottom = ~float')calloc~raw->numberOfLegs,sizeof~float));
73 if(~temp->x = = NULL)¦¦
74 ~temp->top = = NULL)¦¦
~temp->bottom = = NULL)) 76 DoError~ 'StoreOutlinePair: cannot allocate space~n",NULL~;

78 temp->box = raw->box;
79 temp->blackoutHeight = 0;
temp->numberOfLegs = raw-~numberOfLegs;
81 offset = temp->offset = ~raw->x);
82 temp->widlh = ~raw->x + rdw->numberOfLegs-7) - temp->offset;

84 xDCursor = temp->x;
topDCursor = temp->top;
86 bottomDCursor = temp->bottom;
87 xSCursor = raw->t;
88 topSCursor = raw->top;
89 bottomSCursor = raw->bottom;
91 numberOfLegs = raw->numberOfLegs;
92 for ~i = 0; i < numberOfLegs; + + i) {
93 'xDCursor+ + = (float)(-xSCursor+ + -offset)/fontXHeight;
94 y = middleLine - 'topSCursor + +;
9S if (y<0) 96 y=0;
97 'topDCursor+ + = ~float)y/fontXHeight;
98 y = ~L~oi~ sor+ + -middleLine;
99 if ~y<0) 700 y=;
101 'bottomDCursor+ + = ~float)y/fontXHeight;
102 }

104 /~ Now try to remove parts of the contour on to the left and right of the 105 ' word shape that are at height 0 '/

107 topDCursor = temp->top;
Copyright~ 1991 XeroxCorporation All Rights Reserved Sertir~n D APPENDIX Page 250 108 bottomDCursor = temp->bottom; 2 ~ 7 79 ~ a ~109 for(i =0;i<numberOfLegs; + + I) {
~~10 if ((~topDCursor+ + ! = 0)~ bottomDCursor + + ! =0)) I l ~ break;
112 }
113 ieft = i;

11s topDCursor = temp->top+numberOfLegs-l;
~16 bottomDCursor = temp->bottom + numberOfLegs-l;
117 for(i = numberOfLegs-l;i> =0;--i) {
1 t8 if ((ttopDCursor-- ! = 0)11('bottomDCursor-- ! = 0)) 1 19 break;
120 }
121 rlght = i + 1;

123 xDCursor = temp->x;
124 topDCursor- temp->top;
125 bottomDCursor = temp->bottom;
126 xCursor = temp->x+left;
127 topCursor = temp->top+left;
128 bottomCursor = temp->bottom + left;
129 foffset = ~xSCursor;
13û for(i=left;i~right;+ +i){
131 ~xDCursor+ + = ~xCursor+ + -foffset;
732 topDCursor+ + = ~topCursor+ +;
133 bottomDCursor+ + = ~bottomCursor+ +;
134 }
135 temp-~numberOfLegs = right-left;

137 ~(dict- >outiines + dictEntry) = temp;
~38 }

140 static int lineSpacing;
141 Int OrderOutlinePair(OutlinePair 'o1,0utlinePair o2) 142 {
143 IntyDistance;
j44 intxDistance;
145 yDistance = (~ol)->box->pageY - ('o2)->box->pageY;
146 i f (yDistance < lineSpacing && yDistance > -1 I neSpaci ng) {
147 xDistance = (-ol)->box->pageX-(~o2)->box->pageX;
148 return xDistance;
149 }
1 Sû return yDistance;
151 }

153 void SortDictionary(Dictionary dict) 154 {
lSS lineSpacing = 20;
156 qsort(dict->rawOutlines,dict->numberOfEntria~ci7ao~(R? IOutlinePair), 157 OrderOutiinePair);
158 }

160 #define HIST SIZE 100 161 void Histogram(int~data,intdataLength, intoffset, int ~histogram) 162 {
Copyright~ 1991 XeroxCorporation All Rights Reserved ~e~llon ~ APPf NDlX Page 251 t64 for (i - 0;i <dataLength; + + i) { 2 ~ ~ 7 ~ ~ 9 ~
165 bin = 'data-offset;
166 if ((bin> =0)&&(bin<HlST_SIZE)) t67 histogramlbinl+ ~;
t 68 data + +;
t69 }
t70 }
17t 172 voidll;,~,y,c,,~ ?~(int~data,intdata-ength,intoffset,int~histogram) t73 {
t 74 I nt i ,bin;
t75 Directiondirection;
t76 t77 if (~(data + t) < ~data) t78 direction = UP;
t 79 else {
180 bln = 'data-offset;
18t If((bin>=0)&b(bin<HlST SIZE)) t 82 histogram [bl nl + +;
t83 direction = DOWN;
t84 }
t 85 + + data;
t86 t87 ~or(i=t;i<dataLength-l;+ +i){
t88 If((direction = = UP)&&
t89 (^data ~ ~(data + t ))) {
t90 /~ ~data is a peak ~/
t9t bin = ~data-offset;
t92 if((bin>=0)&&(bin<HlST SIZE)) t 93 h istogram [bi n I + +;
194 direction = DOWN;
t95 }
t96 elseif((direction = = DOWN)&&
t97 (~data > ~(data + 1))) {
t98 /~ ~data is a valley ~1 t99 direction = UP;
200 }
Z01 + +data;
202 } /~ for i ~/
203 }

205 voidHistogramValleys(int~data,intdataLength,intoffset,int~histogram) 206 {
207 inti,bin;
208 Direction direction;

210 if (~(data + 1) > ~'data) 21 t direction = UP;
212 else{
213 bin = ~data-offset;
214 if ((bin> = 0)&&(bin< HIST SIZE)) 215 histogram[binl+ +;
216 dlrection = DOWN;
217 }
Copyright'D t99t Xero~Corporation All Rights Resen/ed Sectlon D APPENDIX Page 252 18 ~ ~dat2; 2077969 l9 220 for (i = 1;i ~dataLength~ + i) {
22~ if((direction = = UP~&&
222 (~data ~ ~(data ~ ~ ))) {
223 /~ ~data is a peak ~1 224 bin = ~data-offset;
225 if((bin~ =0)&&(bin<HlST_SIZE)) 226 histogram [bi nl + t;
227 direction = DOWN;
228 }
229 elseif((direction = = DOWN)&&
230 (~data < ~(data ~1))) {
231 /~ ~data is a valley ~/
232 direction = UP;
233 }
234 1 ~ data;
235 } /~ for i ~1 236 }

238 int MaxBin(int ~histogram) 239 {
240 int i;
24; int maxValue;
242 int maxlndex;

244 maxValue = histogram[0¦;
245 maxlndex = û;
246 for (i = 0; i < HIST SIZE; +, i) 247 if (histogram[il >maxValue) {
248 maxValue = histogram[i];
249 maxlndex = i;
250 }
251 return maxlndex;
252 }

254 void PostProcess(Dictionarydict) 255 {
256 int index;
257 int temp;
258 int i,startlndex,firstY,minY,endlndex,shape;
259 i nt topstHlST _ SIZE];
260 int bottomslHIST SIZEl;
261 intmiddleLine,topLine,bottom~ine;
262 int fontXHeight;
263 RawOutlinePairthisShape;

265 SortDictionary(dict);

267 index = 0;
268 #ifdef foo 269 mallo~_verify();
270 #endif 27; while (index < dict-~ numberOfEntrles~ {
272 startlndex = index;
Copyright~ 1991 XeroxCorporation All Rlghts Reserved Sectlon D APPENDIX . Page 253 273 firstY = (~(di~t.>rawOutlines + Index))->box->pageY; 7 7 9 6 9 274 mlnY = firstY; 2 275 while((~(dict->rawOutlines+index))->box->pageY-fi-stY < 20&&
276 (~(dict->rawOutlines + index))->box->pageY - firstY > -20) {
277 if ( m inY > ( ~-(dict- >rawOutl ines + i ndex))- > box- >pageY )) 278 minY = (~(dict->rawOut!ines+index))->box->pageY;
279 + +index;
28û if(index = = dict->numberOfEntries) 281 break;
282 }
283 endlndex = index;

285 #ifdef foo 286 malloc_verify();
287 #endif 289 /~ shapes from start Index through endindex are all on ~1 290 /~ the same text line ^/
291 /~ minY has the top of the highest box on the line. ~/

293 /~ Find the base and toplines by taking the mode of the helghts of the 294 ~ val leys of the boUom contours and the peaks of the top contours ~/
295 for(i=0;i<HlSr _ SlZE;i+ +){
296 tops[i] = û;
297 bottoms[i~ = 0;
298 }
299 for (shape = ~ldl ~I"~A,,l,ape<endlndex; + + shape) {
300 thisShape = ~(dict-~rawOutlines+shape);
301 lI;it~ ".(l;.. ~ >top,thisShape->numberOfL-cgs,minY,tops);
302 lli~t~ .lYI(li~s.~, >bottom,thisShape->numberOf~egs,minY,bottoms);

304 #ifdef foo 305 ~ o~ldl~Pc ' 'll~;~shape->top~thisshape->numberofLe9s~miny~tops);
306 llistogramValleys(thisShape->bottom,thlsShape->numberOfLegs,minY,bottoms);
307 #endif 308 }
309 topLine = MaxBin(tops)+minY;
310 bottomLine = MaxBin(bottoms) + minY;
31~
312 if (thePict) {
313 int maxLength:
3 ~ 4 i nt hal fWidth;
3 ~ 5 int x,y;
3 ~ 6 float x2,x3,y2,y3;
3 ~ 7 float angle;
3~8 3~9 angle = (~(dict->rawOutlines))->box->angle;
320 maxLength = thePict->width+thePict->he~ght;
321 halfWidth = thePict->width/2;
322 x = topLine ~ -sin(angle) + halfWidth ~ cos(angle);
323 y = topLine ~ cos(angle) + halfWidth sin(angle);
324 x2 = x+maxLength~cos(angle);
325 y2 = y + maxLength~sin(angle);
326 x3 = x-maxLength~cos(angle);
327 y3 = y-maxLength~sin(angle);
Copyright ~ 1991 ~terox Corporation All Rights Reserved Section D APPENDIX P~ge 254 28DrawLine(thePict,x,y,(int)x2,(int)y2 5 ~29DrawLine(thePict,x,y,~int)x3,(int)y3 5), 3331x = bottomLine ' -sin(angle) ~ halfWidth cos~angle~; 2 ~ 7 7 91~ 9 332y = bottomLine '' cos~angle) ~ halfWldth ' sln(angle);
333x2 = x~maxLength'cos(angle);
334y2 = y~maxLength~sin(angle);
335x3 = x-maxLength'cos(angle);
336y3 = y-maxLength'sin(angle) 337DrawLine(thePict x,y,(int)x2 (int)y2 S) 338DrawLine(thePict x,y,(int)x3 (int~y3 5), 340 }

342 #ifdef foo 343mal I oc veri fy() 344 #endif 346middleLine = (bottomLine+topLine~/2 347fontXHeight = bottomLine-topLine;
348 /~ Clip and normalize the contours '/
349 for (shape = startlndex;shape<endlndex, ~ ~ shape~
350 Sto~eOutlinePai-(dict,shape,middleLine,fontXHelght);
351 ~ /- Do another line of text '/
352 }

Copyright~ 1991 XeroxCorporation Al I Rights Reserved Sectlon D APPENDIX Page 255 Jul t 13 46 ~991 postproc ~ 2 0 7 ~ ~ 6 9 #include Cstdio h~
2 #include <math h>
3 #include " boolean h "
4 #include "types h"
S #include "error h"
6 #include "pict h"
7 #include "dict h"

9 #define UP0 #define DOWN t 11 typedef int Direction;

13 extern Picture thePict;

voidStoreRawOutlinePair(Dictlonarydict,lntdictEntry, 16 Box box,int ~bothX,int ~topY, int ~baseY, 17 int numberOfLegs) 18 {
19 RawOutlinePairtemp;
int i;
21 int-xCursor,~topCursor,-bottomCursor;

23 temp = (RawOu " I~Pail)calloc(l,sizeof(RawOutlinePairBody));
24 if(temp = = NULL) DoError("StoreRawOutlinePair cannotallocatespace\n",NULL~;

2~ temp->box = box;
28 temp->numberOfLegs = numberOfLegs;

temp-~x = (int')calloc(temp->numberOfLegs,sizeof(int~);
31 temp-~top = (int-)calloc(temp->numberOfLegs,slzeof(int));
32 temp->bottom = (int- "- L~, "~->numberOfLegs,slzeof(int));
33 if((temp->x = = NULL)¦¦
34 (temp->top = = NULL)¦¦
(temp->bottom = T NULL)) 36 DoError("Sto c:~_ /CutlinePair cannotallocatespace~n",NULL);

38 xCursor = temp->x;
39 topCursor ~ temp-~top;
bottomCurso~ = temp->bottom;

42 for(i=0;i<numberOfLegs;+ ~i){
43 ~xCursor+ + = ~bothXt +;
44 ~topCursor+ ~ = topY+ ~;
bottomCursor + + = baseY + +;
46 }
47 ~(dict->rawOutlinff+dictEntry) = temp;
48 }

void StoreOutlinePair(Dictionary dict, int dictEntry, Sl int middleLine,int fontXHeight) 52 {
Copyright ~1991 Xerox Corporation Al I Rights Reserved Sectlon D APPENDIX Page 256 s3 RawOutlinePairraw; 2~7 ~54 OutlinePair temp; 73 ~9 int i,numberOfLegs;
56 int y;
57 int offset;
58 int 'xSCursor,'topSCursor,~bottomSCursor;
S9 float 'xDCursor,'topDCursor,-bottomDCursor;
6û float xCursor,~topCursor,-bottomCursor;
6~ intleft,right;
62 float foffset;

64 raw = (dict->rawOutlines+dictEntry);
66 temp = ~OutlinePair)ca~loc(7,slzeof(0utlinePairBody));
67 if(temp = = NULL) 68 DoError('StoreOutlinePair cannotallocatespace\n ,NULL);

temp-~x = (float-)calloc(raw->numberOfLegs,sizeof(float~);
71 temp->top = (float')calloc(raw->numberOfLe~c, ~(riG"~)), 72 temp->bottom = (float-)callo~(raw->numberOfLegs,sizeof(float));
73 if((temp->x = = NULL)¦¦
74 (temp->top = = NULL)¦¦
(temp->bottom = = NULL)) 76 DoError("StoreOutlinePair cannot allocate space\n ,NULL);

78 temp->box = raw->box;
79 temp->blackoutHeight = û;
8û temp->numberOfLegs = raw->numberOfLegs;
81 offset = temp->offset = ~(raw->x);
82 temp->width = '(raw->x+raw->numberOfLegs-1) temp->offset;

84 xDCursor = temp->x;
topDCursor = temp->top;
86 bottomDCursor = temp->bottom;
87 xSCursor = raw->x;
88 topSCursor = raw->top;
89 boUomSCursor = raw->bottom;
91 numberOfLegs = raw >numberOfLegs;
92 for(i=0;icnumberOfLegs;+ +i){
93 'xDCunor + + 2 (float)(~xSCursor + + - offset)/fontXHeight;
94 y = middleLine-'topSCursor+ ~;
jf (yco) 96 y=0;
97 'topDCursor + + = (float)y / fontXHeight;
98 y = 'bottomSCursor+ + -middleLine;
99 jf (y<o) 100 Y = ;
101 bottomDCursor+ + = (float)y/fontXHelght;
102 }

~ 04 /~ Now try to remove parts of the contour on to the ~eft and right of the 105 ' word shape that are at height 0 '/

107 topDCursor = temp->top;
Copyright1991 XeroxCorporation All Rights Reserved Sectlon D APPENOIX P~,cle 257 108 bottomDCursor = temp->bottom;
109 fo~(i=0;i<numberOfLegs;+ +i~ %o~7969 110 if ((~topOCursor + + ! = 0)¦¦('bottomDCursor + + ! = 0)) 11 1 break;
112 }
113 left = i;

115 topDCunor = temp->top+numberOfLegs-1;
116 bottomDCursor = temp-~bottom+numberOfLegs-1;
117 for(i=numberOfLegs-1;i>=0;~i){
118 if (('topDCursor-- ! = 0)¦¦('bottomDCursor-- ! = 0)) 1~ 9 break;
120 }
121 right = i + 1;

123 xDCursor = temp->x;
124 topDCursor = temp->top:
125 bottomDCursor = temp->bottom;
126 xCursor = temp->x+left;
127 topCursor = temp->top+left;
128 bottomCursor = temp->bottom+left;
129 foffset = ~xSCunor;
1 3û for (i = left; i < rlght; + + i) {
13~ ~xDCunor+ + = ~xCunor+ +-foffset;
132 ~topDCursor+ + = ~topCursor+ +;
133 ~bottnmD~-rsor+ + = ~bottomCursor+ +;
134 }
135 temp->numberOfLegs = right-left;

137 (dict->outlines+dictEntry) = temp;
138 }

140 static int lineSpacing;
141 int OrderOutlinePair(Outl inePair ol ,OutlinePair 'o2) 142 {
143 intyDistance;
144 irlt xDistance;
145 yDistance = (~ol)->box->pageY-(~o2)->box->pageY;
146 If (yDistance<lineSpacing && yDistance > -lineSpacing) ( 147 xDistance = (~ol)->box->pageX-(~o2)->box->pageX;
14S3 return xDistance;

150 return yDistance;
151 }

153 void SortDictionary(Dictionary din) 154 {
155 I~neSpacing = 20;
156 qsort(dict->rawOutlines,dict->numberOfEntries,sizeof(RavvOut~inePair), 157 OrderOutlinePair);
158 }

160 #define HIST _ SIZE 100 161 voidll;stcy,,.,.~ Y(int~data,intdataLength,intoffset,intsign,int~histogram)162 {
Copyright~ ~991 XeroxCorporation All Rights Reserved Section D APPENDIX Page 258 2a779~
~63 Int l,bin;
~64 if (sign ~0) {
166 int maxValue;
~67 maxValue = 'data;
168 fo- (i = 0; i < d ataLength; + + i ) 169 if(data[i]~maxValue~
170 ma~Value ~ datali];
~71 bin = maxValue-offset;
172 if((bin>=O)&&~bin<HlST SIZE)) 173 histogram[binl+ +;
174 }
175 else {
176 Int minValue;
177 minValue = ~data;
178 for(i =O;i~dataLength; + +i) 179 If(data[i]<mlnValue) 18û mlnValue = da~a[i];
181 bin = mlnValue-offset;
182 ~f((bin>=O)&&(bin<HlST_SIZE)) 183 histogram[bin¦+ +;
184 }
185 }

187 void Histogram(int ~data,intdataLength, intoffset, Int ~histogram) 188 {
189 inti,bin;

191 for(i=O;i<dataLength;+ ~i){
192 bin = 'data-offset;
193 If ((bin> =O)&&(bin<HlST_SIZE)) 194 histogram~binl+ +;
19S data+ +;
196 }
197 }

199 voidH,.lo~ ,.,.,~ 'int~data~intdataLength~intoffset~int~histogram) 200 {
201 i nt i,bin;
202 Di recti on d i recti on;

204 if (~(data + 1) < ~data) 205 direction = UP;
206 else {
207 bin = ~data-offs~t;
208 if (~bin~ = O)&&~bin<HlST _ SIZE)) 209 I~ y.~l.. [L~ + +;
210 direction = DOWN;
211 }
2~2 + +data;

214 for(i=l;i<dataLength-l;++i){
215 if((direction = = UP)&&
216 (~data < ~(data + 1))) {
217 /~ 'data is a peak ~/
Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX Page 259 218 bln = 'data-offset, , 2 0 7 7 9 G 9 219 if((bin>=o)&&(bln<HlsT_SIZE)) 220 histcgram [bi n] + +;
221 direction = 30WN;
22Z }
223 elseif (~direction = = DOWN) &&
224 ~datd > ~(data + 1 ))) {
225 /~ ~data is a vall~y ^/
226 direction = UP;
227 }
228 + +data;
229 } /- for i /
230 }

232 void HistogramValleys(int data,int dataLength, int offset, int histogram)233 {
234 int i,bin;
235 Direction direction;

237 if (-(data + 1) > data) 238 direction = UP;
239 else {
240 bin = data-offset;
241 if((bin> =0)&&(bin<HlST_SIZE)) 242 histogram[bin] + +;
243 direction = DOWN;
244 }
245 + +data;

247 for(i=l;i<dataLength-l;+ +i){
248 if ((direction = = UP) &&
249 (-data > (data + 1))) {
250 /- ~data is a peak /
251 bin = data-offset;
252 if(~bin> =0)&&~bin<HlST SIZE)) 253 histogram[binl + +;
254 direction = DOWN;
255 }
256 elseif((direction s = DOWN)&&
257 ~-data C ~data + 1))) {
258 /~ ~data is a valley ~/
25g direction = UP;
260 }
261 + +data;
262 } /~ for i ~/
263 }

265 int Max8in~int histogram) 266 {
267 int i;
268 int maxValue;
269 int maxlndex;

271 maxValue = histogram[01;
272 maxlndex = 0;
Copyright 1991 Xerox Corporation All Rights ieserved Sec+lon D APPENDIX P~ge 260 73 fo-(i=0;i<HlST SIZE;~
~74 if (histogram~i~ >maxValue~ {
2776 ma%lnde% - 1; 2 ~ 7 79 ~9 277 }
278 return maxlndex;
279 }

281 void PostProcess(Dictionarydict) 282 {
283 int index;
284 int temp;
285 int i,startlndex,firstY,minY,endlndex,shape, 286 inttops[H~ST SIZE¦;
287 int boltomslHlST SIZEI;
288 int middleLine,topLIne,bottomLine;
289 Int fontXHelght;
290 RawOutlinePair thisShape;

292 SortDictlonary(dict);

294 index = 0;
295 #ifdef foo 296 malloc verify();
297 #endif 298 while (index < dict->numberOfEntries) {
299 startlndex = index;
3û0 firstY = (~(dia->rawOutlines+index))->box->pageY;
301 minY = firstY;
302 while ( ~(dict- > rawOutlines + index))- > box- > pageY - fintY < 20 &&
303 (~(dict->rawOutlines~index))->box->pageY-firstY >-20 304 if ( minY > ( (-(di->rawOutlines + index))->box->pageY )) 305 minY = (~(dict->rawOutlines + index))->box->pageY;
306 ~ +index;
307 if (index = = dict->numberOfEntries) 308 break;
309 }
310 endlndex = index;

312 #ifdef foo 313 malloc verifyl);
314 #endif 316 /~ shapes from start index through endindex 2re all on 'I
317 /~ the same te%t l i ne ~/
318 /'minYhasthetopofthehighestboxontheline.-l 320 /~Findthebaseandtoplinesbytakingthemodeoftheheightsofthe 321 ~ val leys of the bottom contours and the peaks of the top contoun ~/
322 for(i=0,i<HlST _ SlZE;i~ ~){
323 tops[i1 - 0;
324 bottomstil = 0;
325 }
326 for(shape=,l~ 1"J~ I,ap~<endlndex; + +shape~{
327 thisShape = ~(dict->rawOutlines+shape);
Copyrirht û 1991 XeroxCorporation All Rights Reserved Sec~on D APPENDIX P~ge 261 328 Hlstogram(thisShape->top,thlsShape-~numberOfLegs,minY,tops); 2 0 7 7 329 h~tc,~ (Ll,lsShape->bottom,thisShape-~numberOfLegs,minY,bottoms);
33û
331 #ifdef foo 332 hi~Lu~, 7~ ;sShape->top,thisShape->numberOfLegs,minY,tops);
333 HistogramV "~s(~ ;hape->bottom,thisShape->numberOfLegs,minY,bottoms);
334 #endif 335 }
336 topLine = MaxBin(tops)+minY;
337 bottomLine = Max8in(bottoms)+minY;

339 if (thePict) {
34û intmaxLength;
34~ int halfWldth;
342 int x,y:
343 float x2,x3,y2,y3;
344 float angle;
345 . .
346 angle = (~(dict->rawOutlines))->box->angle;
347 maxLength = thePict->width+thePict->helght;
348 halfWidth = thePict >width/2;
349 x = topLine ^ -sin(angle) + halfWidth ~ cos(angle);
35û y = topLine ~ cos(angle) + halfWidth ' sln(angle);
351 x2 = x+maxLength^cos(angle);
352 y2 = y+maxLength~sin(angle);
353 x3 = x-maxLength~cos(angle);
3s4 y3 = y-maxLength^sin(angle);
355 DrawLine(thePict,x,y,(int)x2,(int)y2,5);
356 DrawLine(thePict,x,y,(int)x3,(int)y3,5);

358 x = bottomLi ne ^ -sin(angl~) + hal fWidth ^ cos(angle);
359 y = bottomLine^cos(angl~) + halfWidth"sln(angle);
360 x2 = x + maxLength^cos(angle);
361 y2 = y + maxLength~sin(angle);
362 x3 = x-maxLength^cos(angle);
363 y3 = y-maxLength^sin(angle);
364 DrawLine(thePict,x,y,(int)x2,(int)y2,5);
365 DrawLine(thePict,x,y,(int)x3,(int)y3,5);

367 }

369 #ifdef foo 370 malloc verify();
37 1 #~endif 373 middleLine = (bottomLine+topLine)/2;
374 fontXHeight = bottomLine-topLine;
375 /~ Clip and normalizethe contours ^l 376 for (sh a pe = ~L~" Il" ' h , ~ end l ndex; + + shape) 377 StoreOutlinePair(dict,sh~r~ e,fontXHeight);
378 } /^ Do another I i ne of text ^/
379 }
38û
381 vc id Pag~Statistics(Dictionary dict,char tf j leName) 382 /~WARNlNG-thismustberunbeforePostProcesssincePostProcesschangestheraw Copyright~ 1991 XeroxCorporation All Rights Reserved Sectlc\n D APPE~DIX ~ Pa~e 262 ~83 t shape data. '/ 2 0 7 7 9 6 ~
385 int index;
386 int temp;
387 int i,startlndex,firstY,minY,endlndex,shape;
388 inttops[HlST _ SIZE];
389 int bottonns[HIST SIZEI;
390 intascenderslHlS~ SIZE¦;
391 intdescenders[HlST SIZEI;
392 int middleLine,topLIne,bottomLine,ascenderLine,descenderLine;
393 intd,~el,U~,H~ ,des~t,.d~,Ha;gllL,lineNumber;
394 int fontXHeight;
395 RawOutlinePairthisShape;
396 FILE ~fp;

398 if ((fp = fopen(fileName, 'w'')) = = NULL) 399 DoError~"PageStatistlcs: error openlng output file %s.\n",fileName);

401 SortDictionary(dict);

403 index = 0 404 #ifdef foo 405 malloc verify();
406 #endif 407 lineNumber = o;
408 while (indêx < dict->numberOfEntries) {
409 startlndex = index;
410 firstY = (~(dict->rawOutlin~s~index))->box->pag~Y;
411 minY = firstY;
412 while(('(dict->rawOutlines~index))->box->pageY-firstY < 20&&
413 (~(dict->rawOutlinestindex))->box->pageY-firstY>-20){
414 if ( minY > ( (-(dict-~rawOutlines ~ index))->box->pageY )) 415 minY = (^(dict->rawOutlines~index))->box->pageY;
416 I tindex;
417 if(index = = dict->numberOfEntries) 418 break;
419 }
420 endlndex = index;

422 #ifdef foo 423 malloc verify~);
424 #endif 426 1~ shapes from start index through endindex are all on '/
427 1~ the samc text I ine ~/
428 l~minYhasthetopofthehighestboxontheline.~l 430 1~ Fi nd the base and toplines by taking the mode of the heights of the 431 ~ valleys of the bottom contours and the peaks of the top contours ~1 432 for(i =0;i<HlST _ SlZE;i ~ ~){
433 topsli] = o;
434 bottoms[il = o;
43s ascenders[il = ;
436 descenders[il=0;
437 }
Copyright0 1991 XeroxCorporation All Rights Reserved Secllon L~ APPEt`lDIX Page 263 438 for (shape = startlndex;shdpe<endlndex; ~ + shape) { 2 0 7 7 ~ ~ 9 439 thisSh2pe = (dict->~awOutlines+shape);
440 lI;~tulJ~a-~ Shape->top,thisShape->numberOfLegs,minY,tops);
441 Il~ a~ shape->bottom~thisshape->numberofLegs~miny~bottoms);

443 lI;~cy. '~ Shape->top,thisShape->numberOfLegs,minY,-l,ascenders);
444 I'i~t~J.c.,,'~(thisShape->bottom,thlsShape->numberOfLegs,minY,l,descenders);
445 }
446 topLine = Maxain(tops) + minY;
447 bottomLlne = Max8in(bottoms)+minY;
448 ascenderLlne = MaxBln(ascenders) + minY;
449 descenderLine = Maxain(descenders)+minY;

451 ~Fifdef foo 452 malloc verify();
453 #endif 455 middleLine = (bottomLine+topLine)/2;
456 fontXHeight = bottomLine-topLine;

458 ds.~"d~.He,ght = bottomLine-ascenderLine;
459 dc~s~ He~ L = descenderLine-bottomLine;
460 fprintf(fp,"%d: %d %d %d ~2.6f\n~ ineNumber~fontxHeight~as~e~ H~ llL~de~clld~H~
461 (flOat)a,.ell~ ;"l,L/(float)fontXHeight);
462 + +lineNumber 463 ~ /^ Do ~nothe~ line of text /
464 fCloSe(fp);
465 }

Copyright~ ~991 XeroxCorporation All Rights Reserved Sectlon D APPENDIX P~ge 264 ~ul ~01 3: 1 71991 testFlne.c ~2~79Gg #include <stdio h>
2 i~include ~math.h >
3 #include''boolean.h"
4 #include''pict.h"
S #include"lines.h"

7 #define ABS(x) (((x1~0)?(-(x)):(x)) 9 extern long random();
11 Int R~ndomCoordinate(int maxValue) ~2 {
73 return (float)~random()&Oxffffl'maxValue/Oxffff;

~6 vold RandomEdgePixel~Picture pict,int x, Int 'y) 17 {
18 while(TRUE){
~9 x = RandomCoo-d;mlL~(p;ct->width);
y = RandomCoo~dinate(pict->height);
21 if(ReadPixel(pict,'x,-y)) 22 if (!(ReadPixel~pict,'x ~1,-y) &&
23 ReadPixellpict,-x-~,-y) &&
24 ReadPixellpi~t,-x,-y I ~) &&
ReadPixellpict,~x,'y-1)&&
26 ReadPixellpict,'x~ y1 1)&&
27 ReadPixellpict,-x-1,-y-1)&&
28 '`~ t -x ~ y-1) &&
29 ReadPixel~pict,-x-l,-y f 1))) 3û return;

33 }

float Fine(Picture pict,int fineSamples, int fineDirections, 36 f loat ang I eStart, f loat angl eEnd, ch a r pl otFi I e) 38 int x,y;
39 float x2,y2;
i nt i,j;
41 float counters;
42 float step,angle;
43 float maxAngle;
44 float maxValue;
float maxLength;
46 FILE 'outfile;

4~3 counters = (float~)calloc(fineDirections,sizeof(float));
49 i f (counters = = N U LL) {
SO printf(" Fine: cannot allocate memory\n " );
51 exit(- ~ );
52 }
Copyright 1991 Xerc~x Corporation All Rights Reserved Sectlon D APPENDIX . Page 265 54 step = ABS(angleEnd - angleStart)lfineDirectlons; 2 0 7 7 9 6 9 56 maxLength = sqrt((double)(pict~width~pict->width+
57 pict->height~pict->height));
58 for(i=û;i<fineSamples;+ +i){
S9 RandomEdgePixel~pict,&x,&y);
angie = angleStart;
61 for(j=0;j<fineDirections;+ +j){
62 angle = fmod(angle,2~M Plj;
63 x2 = x + maxLength~cos~ngle);
64 y2 = y + maxLength^sin(angle);
counters~j] + = CountLine~pict,x,y,(int)x2,tint)y2);
66 angle + = step;
67 }
68 }

ang~e = angleStart;
7t maxAngle = angle;
72 maxValue = countersl0];
73 for (i = 0;i <fineDirections; + + i) {
74 angle = fmod(angle,2~M Pl);
if (counters[il~maxValue~
76 maxAngle = angle;
~7 maxValue = counters[il;
78 }
79 angle + = step;
~0 }
81 printf(" O~ientdtion is at % f(q~ fl\n " ,maxAngle,maxAngle/2/M_Pl ~360);

83 /~ Plot the orientation graph if requested ~/
84 printf(''Op~ning fine orientation plot file~n");
if ((outfile = fopen(plotFile,"w")) = = NULL) ~
86 printf("Erroropenlng fineorientation plot file.~n");
87 exi t(- 1 );
88 }
89 angle = angleStart;
9û for(i=0;i<fineDirections;+ +i){
91 angle = fmod(angle,2~M Pl);
92 fprintf(outfile,"%f %f~n'',angle,counters[i]);
93 angle + = step;
94 }
9S fprintf~outfile,"\"FineDistances~n~n");
96 fcl~ (cl~l f~
97 printf("Donewritingfineorientationplotfile.~n");
98 return maxAngle;
99 ~, 101 main(argc, argv) 102 int argc;
03 char ~argv~l;

105 char'i"r;lrc~ coarseOutFil~Name,-fineOutFileName,~fine20utFileName;
106 intfineDirections,fineSamples;
107 floatco~" ^.ngl~,fineAngle,fineAngle2;
Copyright 1991 Xerox Corporation All Rights Reserved Section D APPENO~X P~ge 266 ~08 float firstspaclng~secondspacing~thlrdspaclng;
09 Picture pict; 2 0 7 7 9 ~ 9 111 if(argc!= 7 112 {
113 printf("\nUsage: q6s infile coars~rl(,~f;le finePlotFile\n",argvl0~);
114 printf(" ri"~.Plo~F;'e#directions#samples\n\n");

1 16 exit(0);
117 }

119 inFileName = argv[ll; I'getargs~l 120 coarseOutFileName = argv~21;
121 fineOutFileName = argv[3¦;
122 fine20utFileName = argv~4];
123 fineDirections = atoi(argvlSI);
124 fineSamples = atoi(argv[6]);

126 pict = load pict(inFileName);
127 coar5eAngle = Fine(pict,fineSamples,fineDirections, 128 0,M Pl,coarseOutFileName);
129 firstSpacing = (M Pl-0)lfineDirections;
130 printf("CoarseangTe: ,~f(%fl\n",coarseAngle,coarseAnglelM Pl~80);
131 printf(''Coarsespacing: %f(%fl\n",firstSpacing,firstSpacinglM P1~180);

~33 fineAngle = Fine(pict,fineSamples,fineDirections, 134 coarseAngle-4~firstSpacing,coarseAngle t 4-firstSpacing, 1 ~S fineOutFileName);
136 ~e~o,~USp0cing = 8~firstSpa~ /r;,)~irections;
137 printf("Fine angl~: %f(%fl\n",fineAngle,fineAnglelM P1~780);
138 printf("Finespacing: %f(%fl\n'',secondSpaclng,secondSpacinglM P1~180);

140 fineAngle2 = Fine(pict,fineSamples,fineDirectlons, 141 fineAngle-lS~secondSpacing,fineAngle I 15~secondSpacing, 142 fine20utFileName);
143 thirdSpacing = 30's~ .i5pa.i-)yl~ Directions;
144 printf("Finerangle: %f(~6fl\n",fineAngle2,fineAngle21M P1~18û);
145 printf("Finerspacing: %f(%fl\n",~l.;,~Spac;r~.~,thirdSpacinglM _ P1~18û);
146 }

Copyright~ 1991 Xerox Corporation All FightsReserved SeC~lon D APPENDIx P~ge 267 Aug 1506.32199~ types.~
207'~969--#include "stdio.h '' 2 #include''mylib.h"
3 #include''typff.h"
4 #include''error.h"
s 6 Box Make30x(int x,lnt y,int width,int height,double angle) 7 {
8 aOx temp;
9 temp = ~80x)calloc(1,sizeof~Box30dy));
If(temp= =NULL~
11 DoError("Makeaox: outof memory\n",NULL);
12 temp->x = x;
13 temp->y = y;
14 temp->width = width;
temp->height = height;
16 temp->angle = angle;
17 return temp;
18 }

Point MakePoint~lnt x,int y) 22 Point temp;
23 temp = ~F~,"L).~.lloc(l,sizeof~PointBody));
24 if ~temp = = NULL) 2S DoError~"MakePoint: outof memory~n",NULL);
26 temp->x = x;
27 temp->y = y;
28 return temp;
29 }

Copyright 1991 XeroxCorporation All Rights Reserved

Claims (34)

1. A method of forming a word shape, from which information about a symbol string may be derived, including the steps of:
a) isolating a symbol string image;
b) identifying a first reference with respect to the symbol string;
c) deriving a set of single independent variable measurements about at least a portion of the shape of the symbol string with respect to the reference.
2. The method as described in claim 1 wherein the reference is a line through the symbol string.
3. The method as described in claim 1 wherein a second reference is established at least partially enclosing the image.
4. The method as described in claim 3 wherein the first reference is a line through the symbol string.
5. The method as described in claim 4 where the measurements are distances from the enclosing reference to the symbol string image or the reference.
6. The method as described in claim 5 wherein a set of points is identified defining an outer edge of the symbol string image, and the set of measurements are distances from the reference to each member of the set of points.
7. The method as described in claim 1 wherein the measurements are distances from the reference to a set of points defining an outer edge of the symbol string image.
8. A method of forming a word shape, from which information about a symbol string may be derived, including the steps of:
determining orientation of a symbol string within an image;
isolating a discrete symbol string in the image by differentiating between adjacent symbol strings;
establishing a reference at least partially enclosing a discrete symbol string;
defining a reference line parallel to, and extending through, the symbol string;
deriving a set of distance measurements for each of a set of line segments between the symbol string or the reference line, and the enclosing reference.
9. The method as described in claim 8, wherein the enclosing reference includes an upper boundary line, parallel to the orientation of the symbol string, defining an upper limit of the symbol string image.
10. The method as described in claim 9, wherein the enclosing reference includes a lower boundary line, parallel to the orientation of the symbol string, defining a lower limit of the symbol string image.
11. The method as described in claim 8, wherein the enclosing reference includes a lower boundary line, parallel to the orientation of the symbol string, defining a lower limit of the symbol string image.
12. The method as described in claim 8, wherein the reference line has a thickness, to provide distinct upper and lower reference edges, to which distance measurement may be derived.
13. The method as described in claim 8, wherein the reference line has a thickness, defined by upper and lower reference edges, approximately one third of an x-height, determined for the symbol string, and defined with the lower edge spaced one third of the determined x-height from a lower limit of the symbol string image.
14. The method as described in claim 8, wherein a reference line is established having a thickness defined by upper and lower reference edges approximately one third of an x-height, determined for the symbol string, and defined with the upper reference edge spaced one third of the determined x-height from the upper limit of the symbol string image.
15. The method as described in claim 8, wherein the line between the symbol string image or the reference line, and the enclosing reference is perpendicular to the orientation of the symbol string.
16. The method as described in claim 8, wherein for an image defined by an array of pixels having a resolution of N pixels per unit length, the set of measurements derived has an equal resolution.
17. The method as described in claim 8, and including the step of deriving a second set of distance measurements, equal to the difference between the distance from the enclosing reference to the reference line, and the first set of distance measurements.
18. A method of forming a word shape, from which information about a symbol string may be derived, including the steps of:
determining orientation of a symbol string within an image;
isolating a discrete symbol string in the image by differentiating between adjacent symbol strings;
defining a reference line parallel to, and extending through, the symbol string;
defining a set of points along an outer edge of the symbol string;
deriving a set of distance measurements for each of a set of line segments between the reference line, and symbol string outer edge points defined.
19. The method as described in claim 18, wherein the reference line has a thickness, to provide distinct upper and lower reference edges, to which distance measurement may be derived.
20. The method as described in claim 18, wherein the reference line has a thickness, defined by upper and lower reference edges, approximately one third of an x-height, determined for the symbol string, and defined with the lower edge spaced one third of the determined x-height from a lower limit of the symbol string image.
21. The method as described in claim 18, wherein a reference line is established having a thickness defined by upper and lower reference edges approximately one third of an x-height, determined for the symbol string, and defined with the upper reference edge spaced one third of the determined x-height from the upper limit of the symbol string image.
22. A method of forming a word shape from an image of text, from which information about a discrete symbol string therein may be derived, including the steps of:
a) detecting the orientation of text within an image;
b) determining within the text image, upper and lower limits of any lines of text;
c) operating on the text image to distinguish between inter-symbol spacing and inter-string spacing;
d) using said determined upper and lower limits of any lines of text, and said distinguished inter-string spacing, to define at least a first reference at least partially enclosing a discrete symbol string;
e) establishing a reference line with respect to the symbol string image and the orientation of the image, said reference parallel to the test orientation and through the symbol string image;
f) making a set of distance measurements for each of a set of line segments between the reference, and the enclosing reference.
23. The method as described in claim 22, wherein the enclosing reference includes an upper boundary line, parallel to the orientation of the text, defining an upper limit of the symbol string image.
24. The method as described in claim 23, wherein the enclosing reference includes a lower boundary line, parallel to the orientation of the text, defining a lower limit of the symbol string image.
25. The method as described in claim 22, wherein the enclosing reference includes an lower boundary line, parallel to the orientation of the text, defining an lower limit of the symbol string image.
26. The method as described in claim 22, wherein the reference line has a thickness, to provide distinct upper and lower reference edges, to which distance measurement may be made.
27. The method as described in claim 22, wherein the reference line has a thickness, to provide distinct upper and lower reference edges, to which distance measurement may be derived.
28. The method as described in claim 22, wherein the reference line has a thickness, defined by upper and lower reference edges, approximately one third of an x-height, determined for the symbol string by the determined upper and lower limits of any lines of text, and defined with the lower edge spaced one third of the determined x-height from a lower limit of the symDol string image.
29. The method as described in claim 22, wherein a reference line is established having a thickness defined by upper and lower reference edges approximately one third of an x-height, determined for the symbol string by the determined upper and lower limits of any lines of text, and defined with the upper reference edge spaced one third of the determined x-height from the upper limit of the symbol string image.
30. The method as described in claim 22, wherein the line between the symbol string image or the reference line, and the enclosing reference is perpendicular to the orientation of the symbol string.
31. The method as described in claim 22, wherein for an image defined by an array of pixels having a resolution of N pixels per unit length, the set of measurements derived has an equal resolution.
32. The method as described in claim 22, and including the step of deriving a second set of distance measurements, equal to the difference between the distance from the enclosing reference to the reference line, and the first set of distance measurements.
33. A method of deriving a signal representative of the shape of a symbol string in an array of image data comprising the steps of:
a) identifying a distinct symbol string in the array of image data;
b) identifying a reference with respect to which the shape signal will be derived for the symbol string;
c) representing the shape of the identified symbol string as a closed curve; and d) for a selected portion of said closed curve, representing said selected portion as a signal f(t) derived with respect to said reference.
34. A method of deriving a signal representative of the shape of a symbol string in an array of image data comprising the steps of:
a) about a selected symbol string, represented by the signal l(x,y), defining a closed boundary uniquely enclosing said selected symbol string in the array of image data;
b) deriving from l(x,y) the edge signal E(x,y) representing the edges of l(x,y) detected within the closed boundary;
c) augmenting with additional data l(x,y), such that E(x,y) is a signal E'(x,y) defined at every sampling point over a range of data;
d) representing a portion of E'(x,y) as a signal f(t), where f(t) is a single independent variable representation of at least a portion of the shape of said selected symbol string.
CA002077969A 1991-11-19 1992-09-10 Method of deriving wordshapes for subsequent comparison Expired - Fee Related CA2077969C (en)

Applications Claiming Priority (2)

Application Number Priority Date Filing Date Title
US79439191A 1991-11-19 1991-11-19
US794391 1991-11-19

Publications (2)

Publication Number Publication Date
CA2077969A1 CA2077969A1 (en) 1993-05-20
CA2077969C true CA2077969C (en) 1997-03-04

Family

ID=25162513

Family Applications (1)

Application Number Title Priority Date Filing Date
CA002077969A Expired - Fee Related CA2077969C (en) 1991-11-19 1992-09-10 Method of deriving wordshapes for subsequent comparison

Country Status (5)

Country Link
US (1) US5640466A (en)
EP (1) EP0543594B1 (en)
JP (1) JP3259993B2 (en)
CA (1) CA2077969C (en)
DE (1) DE69230633T2 (en)

Families Citing this family (32)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH0756956A (en) * 1993-07-22 1995-03-03 Xerox Corp Method for access of data based on image created by human being
IL113204A (en) * 1995-03-30 1999-03-12 Advanced Recognition Tech Pattern recognition system
US6195638B1 (en) * 1995-03-30 2001-02-27 Art-Advanced Recognition Technologies Inc. Pattern recognition system
US5999647A (en) * 1995-04-21 1999-12-07 Matsushita Electric Industrial Co., Ltd. Character extraction apparatus for extracting character data from a text image
US6108444A (en) * 1997-09-29 2000-08-22 Xerox Corporation Method of grouping handwritten word segments in handwritten document images
KR100454541B1 (en) * 1998-04-27 2004-11-03 산요덴키가부시키가이샤 Method and system of handwritten-character recognition
US6201901B1 (en) * 1998-06-01 2001-03-13 Matsushita Electronic Industrial Co., Ltd. Border-less clock free two-dimensional barcode and method for printing and reading the same
US6529643B1 (en) 1998-12-21 2003-03-04 Xerox Corporation System for electronic compensation of beam scan trajectory distortion
JP2001216470A (en) * 2000-01-31 2001-08-10 Keyence Corp Method and device for pattern matching
US6944344B2 (en) * 2000-06-06 2005-09-13 Matsushita Electric Industrial Co., Ltd. Document search and retrieval apparatus, recording medium and program
JP4189506B2 (en) * 2000-06-09 2008-12-03 コニカミノルタビジネステクノロジーズ株式会社 Apparatus, method and recording medium for image processing
US8682077B1 (en) 2000-11-28 2014-03-25 Hand Held Products, Inc. Method for omnidirectional processing of 2D images including recognizable characters
US6735337B2 (en) * 2001-02-02 2004-05-11 Shih-Jong J. Lee Robust method for automatic reading of skewed, rotated or partially obscured characters
US7447361B2 (en) * 2005-05-26 2008-11-04 Marvell International, Ltd. System and method for generating a custom font
JP4771804B2 (en) * 2005-12-20 2011-09-14 富士通株式会社 Layout analysis program, layout analysis apparatus, layout analysis method
JP4909216B2 (en) * 2006-09-13 2012-04-04 株式会社キーエンス Character segmentation device, method and program
US8144989B2 (en) * 2007-06-21 2012-03-27 Sharp Laboratories Of America, Inc. Methods and systems for identifying text orientation in a digital image
US8208725B2 (en) * 2007-06-21 2012-06-26 Sharp Laboratories Of America, Inc. Methods and systems for identifying text orientation in a digital image
JP4960817B2 (en) * 2007-09-19 2012-06-27 キヤノン株式会社 Image processing apparatus and image processing method
US8244062B2 (en) * 2007-10-22 2012-08-14 Hewlett-Packard Development Company, L.P. Correction of distortion in captured images
US7684038B1 (en) * 2008-04-04 2010-03-23 Kla-Tencor Corporation Overlay metrology target
US8290302B2 (en) * 2009-01-30 2012-10-16 Xerox Corporation Method and system for skew detection of a scanned document using connected components analysis
US11461782B1 (en) * 2009-06-11 2022-10-04 Amazon Technologies, Inc. Distinguishing humans from computers
US9158983B2 (en) 2010-07-08 2015-10-13 E-Image Data Corporation Microform word search method and apparatus
DE102011010315A1 (en) * 2011-02-03 2012-08-09 Hönigsberg & Düvel Datentechnik GmbH Detection of objects
JP5948866B2 (en) * 2011-12-27 2016-07-06 富士ゼロックス株式会社 Image processing apparatus and program
JP5884560B2 (en) * 2012-03-05 2016-03-15 オムロン株式会社 Image processing method for character recognition, and character recognition device and program using this method
US9245205B1 (en) 2013-10-16 2016-01-26 Xerox Corporation Supervised mid-level features for word image representation
US9684984B2 (en) * 2015-07-08 2017-06-20 Sage Software, Inc. Nearsighted camera object detection
US9785850B2 (en) 2015-07-08 2017-10-10 Sage Software, Inc. Real time object measurement
US10037459B2 (en) 2016-08-19 2018-07-31 Sage Software, Inc. Real-time font edge focus measurement for optical character recognition (OCR)
JP6798619B2 (en) * 2017-07-31 2020-12-09 富士通株式会社 Information processing equipment, information processing programs and information processing methods

Family Cites Families (47)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US2905927A (en) * 1956-11-14 1959-09-22 Stanley F Reed Method and apparatus for recognizing words
US3127588A (en) * 1959-04-24 1964-03-31 Bell Telephone Labor Inc Automatic reading of cursive script
US3133266A (en) * 1960-06-14 1964-05-12 Bell Telephone Labor Inc Automatic recognition of handwriting
US3295105A (en) * 1964-08-27 1966-12-27 Sylvania Electric Prod Scan control and normalization for a character recognition system
US3755780A (en) * 1971-06-28 1973-08-28 Pattern Analysis & Recognition Method for recognizing characters
GB1401008A (en) * 1971-08-17 1975-07-16 Mullared Ltd Character recognition apparatus
JPS5729745B2 (en) * 1974-09-25 1982-06-24
US4105998A (en) * 1976-03-30 1978-08-08 Fujitsu Limited Pattern recognition processing system
US4155072A (en) * 1976-12-17 1979-05-15 Ricoh Company, Ltd. Character recognition apparatus
US4326190A (en) * 1978-08-30 1982-04-20 Borland David L Boundary trace slope feature detection system
US4377803A (en) * 1980-07-02 1983-03-22 International Business Machines Corporation Algorithm for the segmentation of printed fixed pitch documents
US4400828A (en) * 1981-03-27 1983-08-23 Bell Telephone Laboratories, Incorporated Word recognizer
US4495644A (en) * 1981-04-27 1985-01-22 Quest Automation Public Limited Company Apparatus for signature verification
JPS5947666A (en) * 1982-09-13 1984-03-17 Dainippon Screen Mfg Co Ltd Data compressing method of binary picture
US4499499A (en) * 1982-12-29 1985-02-12 International Business Machines Corporation Method for identification and compression of facsimile symbols in text processing systems
US4558461A (en) * 1983-06-17 1985-12-10 Litton Systems, Inc. Text line bounding system
US4864628A (en) * 1983-08-26 1989-09-05 Texas Instruments Incorporated Method of optical character recognition
US4741045A (en) * 1983-09-23 1988-04-26 Dest Corporation Optical character isolation system, apparatus and method
US4701960A (en) * 1983-10-28 1987-10-20 Texas Instruments Incorporated Signature verification
DE3515159A1 (en) * 1984-04-27 1985-10-31 Canon K.K., Tokio/Tokyo IMAGE PROCESSING DEVICE
US4731857A (en) * 1984-06-29 1988-03-15 International Business Machines Corporation Recognition system for run-on handwritten characters
JPS61188681A (en) * 1985-02-15 1986-08-22 Matsushita Electric Ind Co Ltd Character recognition device
EP0194331B1 (en) * 1985-03-14 1990-07-18 Toppan Printing Co., Ltd. Inspecting device for print
US4764972A (en) * 1985-05-23 1988-08-16 Nec Corporation Continuous characters recognition system
US4918740A (en) * 1985-10-01 1990-04-17 Palantir Corporation Processing means for use in an optical character recognition system
US5060277A (en) * 1985-10-10 1991-10-22 Palantir Corporation Pattern classification means using feature vector regions preconstructed from reference data
US4817166A (en) * 1986-05-05 1989-03-28 Perceptics Corporation Apparatus for reading a license plate
GB2190778B (en) * 1986-05-19 1990-04-25 Ricoh Kk Character recognition with variable subdivisions of a character region
JPS63158678A (en) * 1986-12-23 1988-07-01 Sharp Corp Inter-word space detecting method
JP3014097B2 (en) * 1987-02-20 2000-02-28 株式会社日立製作所 Contour tracking method and system
US5144682A (en) * 1987-03-05 1992-09-01 Ricoh Company, Ltd. Method and an apparatus for isolating an area corresponding to a character or word
JPS63268081A (en) * 1987-04-17 1988-11-04 インタ−ナショナル・ビジネス・マシ−ンズ・コ−ポレ−ション Method and apparatus for recognizing character of document
US4949281A (en) * 1987-04-23 1990-08-14 H. Berthold Ag Method and apparatus for generating and producing two-dimensional graphic object by polynominal parametric curves
JP2667435B2 (en) * 1987-05-01 1997-10-27 株式会社リコー Region extraction method
US4809344A (en) * 1987-05-11 1989-02-28 Nippon Sheet Glass Co., Ltd. Apparatus for preprocessing of character recognition
JP2619429B2 (en) * 1987-11-05 1997-06-11 グローリー工業株式会社 How to separate contact characters
US5031225A (en) * 1987-12-09 1991-07-09 Ricoh Company, Ltd. Character recognition method for recognizing character in an arbitrary rotation position
JPH01183793A (en) * 1988-01-18 1989-07-21 Toshiba Corp Character recognizing device
US4998285A (en) * 1988-03-11 1991-03-05 Kabushiki Kaisha Toshiba Character recognition apparatus
JPH06101049B2 (en) * 1988-03-25 1994-12-12 インターナシヨナル・ビジネス・マシーンズ・コーポレーシヨン Character string detection method
JP2597006B2 (en) * 1989-04-18 1997-04-02 シャープ株式会社 Rectangular coordinate extraction method
JP2930612B2 (en) * 1989-10-05 1999-08-03 株式会社リコー Image forming device
US5129014A (en) * 1989-12-08 1992-07-07 Xerox Corporation Image registration
US5048109A (en) * 1989-12-08 1991-09-10 Xerox Corporation Detection of highlighted regions
US5187753A (en) * 1989-12-08 1993-02-16 Xerox Corporation Method and apparatus for identification and correction of document skew
US5212739A (en) * 1990-10-17 1993-05-18 Hewlett-Packard Company Noise tolerant optical character recognition system
US5216725A (en) * 1990-10-31 1993-06-01 Environmental Research Institute Of Michigan Apparatus and method for separating handwritten characters by line and word

Also Published As

Publication number Publication date
JPH05282490A (en) 1993-10-29
US5640466A (en) 1997-06-17
JP3259993B2 (en) 2002-02-25
DE69230633T2 (en) 2000-07-13
CA2077969A1 (en) 1993-05-20
EP0543594B1 (en) 2000-02-02
EP0543594A2 (en) 1993-05-26
EP0543594A3 (en) 1994-05-25
DE69230633D1 (en) 2000-03-09

Similar Documents

Publication Publication Date Title
CA2077969C (en) Method of deriving wordshapes for subsequent comparison
US5687253A (en) Method for comparing word shapes
CA2077970C (en) Optical word recognition by examination of word shape
US6249604B1 (en) Method for determining boundaries of words in text
US8548253B2 (en) Fast line linking
EP0063454B1 (en) Method for recognizing machine encoded characters
Pechwitz et al. Baseline estimation for Arabic handwritten words
US7174043B2 (en) On-line handwriting recognizer
US5390259A (en) Methods and apparatus for selecting semantically significant images in a document image without decoding image content
US5410611A (en) Method for identifying word bounding boxes in text
EP0587301A2 (en) Bending point extraction method for optical character recognition
US20020051574A1 (en) Character recognition method, program and recording medium
Maddouri et al. Baseline extraction: comparison of six methods on IFN/ENIT database
EP1394726A2 (en) Image processing for pattern recognition using edge detection and projections along predetermined directions
JPH03225579A (en) Device for segmenting character pattern
JP2616994B2 (en) Feature extraction device
JP3127413B2 (en) Character recognition device
CN115830607A (en) Text recognition method and device based on artificial intelligence, computer equipment and medium
JPH0877293A (en) Character recognition device and generating method for dictionary for character recognition
JPS6019287A (en) Character recognizing method
JPS59157776A (en) Pattern recognizing system
JPH04139593A (en) Postal code number recognition device
JPS5971584A (en) Pattern recognizing system
JPH10154207A (en) Method for segmenting character, and device therefor
JPH06139407A (en) Character segmenting method

Legal Events

Date Code Title Description
EEER Examination request
MKLA Lapsed