Sie sind auf Seite 1von 197

University of the Philippines Manila

College of Arts and Sciences


Department of Physical Sciences and Mathematics

Tess2Speech: An Intelligent Character


Recognition-To-Speech Application for
Android Using Google’s Tesseract Optical
Character Recognition Engine

A special problem in partial fulfillment


of the requirements for the degree of
Bachelor of Science in Computer Science

Submitted by:

Anter Aaron M. Custodio


June 2016

Permission is given for the following people to have access to this SP:

Available to the general public Yes

Available only after consultation with author/SP adviser No

Available only to those bound by confidentiality agreement No


ACCEPTANCE SHEET

The Special Problem entitled “Tess2Speech: An Intelligent Char-


acter Recognition-To-Speech Application for Android Using Google’s Tesseract
Optical Character Recognition Engine” prepared and submitted by Anter Aaron
M. Custodio in partial fulfillment of the requirements for the degree of Bache-
lor of Science in Computer Science has been examined and is recommended for
acceptance.

Gregorio B. Baes, Ph.D.


Adviser

EXAMINERS:
Approved Disapproved

1. Richard Bryann L. Chua, M.Sc.


2. Avegail D. Carpio, M.Sc.
3. Perlita E. Gasmen, M.Sc.
4. Ma. Sheila A. Magboo, M.Sc.
5. Vincent Peter C. Magboo, M.D., M.Sc.
6. Marvin John C. Ignacio, M.Sc.

Accepted and approved as partial fulfillment of the requirements for the


degree of Bachelor of Science in Computer Science.

Ma. Sheila A. Magboo, M.Sc. Marcelina B. Lirazan, Ph.D.


Unit Head Chair
Mathematical and Computing Sciences Unit Department of Physical Sciences
Department of Physical Sciences and Mathematics
and Mathematics

Leonardo R. Estacio, Jr., PHD


Dean
College of Arts and Sciences

i
Abstract

Tes2Speech is an Android mobile application for recognizing handwritten texts


and optionally convert it to speech. By training Google’s Tesseract, which is a
free open-source Optical Character Recognition (OCR) Engine, to recognize hand-
written texts, I created an alternative for Intelligent Character Recognition (ICR)
Engine that are proprietary and expensive. OCR Engines’ main purpose is to con-
vert scanned documents with computer printed texts into an editable and machine
encoded text. But by improving an OCR into ICR to recognize handwritten texts
and integrating it into a mobile application in this day and age, it greatly improves
its usability. It can help speech-impaired people to communicate, help children
to recognize the proper pronunciation of words they write, etc. Thus, creating a
free and non-proprietary handwriting-to-speech application that is accessible for
everyone, and will be very useful for those who are looking for a free, portable,
and reliable alternative to ICR, OCR, and other related expensive communication
devices. Tes2Speech includes a user-friendly Tesseract trainer desktop application
in order for the user to personalize Tess2Speech for their own handwritings.
Keywords: Android, Training, Handwritten Texts, Tesseract, Optical Character Recog-

nition (OCR), Computer Printed Texts, Intelligent Character Recognition (ICR), Free

and Non-Proprietary, Speech-Impaired

ii
Contents

Acceptance Sheet i

Abstract ii

List of Figures viii

List of Tables x

I. Introduction 1
A. Background of the Study . . . . . . . . . . . . . . . . . . . . . . 1
B. Statement of the Problem . . . . . . . . . . . . . . . . . . . . . . 4
C. Objectives of the Study . . . . . . . . . . . . . . . . . . . . . . . 6
D. Significance of the Project . . . . . . . . . . . . . . . . . . . . . 7
E. Scope and Limitations . . . . . . . . . . . . . . . . . . . . . . . 9
F. Assumptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

II. Review of Related Literature 12


A. Image-to-Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
A..1 Optical Character Recognition/Intelligent Character Recog-
nition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
A..2 Image Pre-Processing Techniques . . . . . . . . . . . . . . . 15
B. Text-to-Speech . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
C. Image-to-Speech . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
D. HandySpeech . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

III. Theoretical Framework 19


A. Optical Character Recognition . . . . . . . . . . . . . . . . . . . 20
A..1 Input Image . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
A..2 Preprocessing . . . . . . . . . . . . . . . . . . . . . . . . . . 20
A..3 Segmentation . . . . . . . . . . . . . . . . . . . . . . . . . . 21
A..4 Feature Extraction . . . . . . . . . . . . . . . . . . . . . . . 21

iii
A..5 Classification/Recognition . . . . . . . . . . . . . . . . . . . 21
A..6 Post Processing . . . . . . . . . . . . . . . . . . . . . . . . . 21
A..7 Output Text . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
B. Intelligent Character Recognition, Learning Classifier Systems,
and Neural Networks . . . . . . . . . . . . . . . . . . . . . . . . 22
B..1 Artificial Neural Network (ANN) . . . . . . . . . . . . . . . 22
B..2 Learning Classifier Systems . . . . . . . . . . . . . . . . . . 23
C. Image Processing/Preprocessing . . . . . . . . . . . . . . . . . . 25
C..1 Grayscaling . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
C..2 Thresholding & Binarization . . . . . . . . . . . . . . . . . . 26
C..3 De-Skew . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
C..4 Separation of Characters/Segmentation . . . . . . . . . . . . 26
C..5 Character Normalization . . . . . . . . . . . . . . . . . . . . 26
C..6 Adjusting Brightness and Contrast . . . . . . . . . . . . . . 27
D. Tesseract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
D..1 Tesseract Architecture . . . . . . . . . . . . . . . . . . . . . 28
D..2 Tesseract Word Recognition . . . . . . . . . . . . . . . . . . 30
D..3 Training Tesseract . . . . . . . . . . . . . . . . . . . . . . . 33
D..4 Criteria for Finishing Tesseract’s Training . . . . . . . . . . 41
E. Text-to-Speech . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

IV. Design and Implementation 44


A. Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
A..1 Block Diagram of Tess2Speech Mobile Application . . . . . . 44
A..2 Block Diagram of Tess2Speech Trainer Desktop Application 46
A..3 Block Diagram of Tesseract’s Training . . . . . . . . . . . . 47
A..4 Flowchart of Tess2Speech Mobile Application . . . . . . . . 47
A..5 Flowchart of Tess2Speech Trainer . . . . . . . . . . . . . . . 50
A..6 Use-Case Diagram . . . . . . . . . . . . . . . . . . . . . . . 52
B. System Architecture . . . . . . . . . . . . . . . . . . . . . . . . . 54

iv
B..1 Android OS . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
B..2 Java Programming Language . . . . . . . . . . . . . . . . . 54
B..3 Android Studio . . . . . . . . . . . . . . . . . . . . . . . . . 54
B..4 Tess-Two . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
B..5 Tess2Speech’ Tessdata folder . . . . . . . . . . . . . . . . . . 55
B..6 Text-to-Speech System . . . . . . . . . . . . . . . . . . . . . 55
B..7 Tess2Speech’ Canvas . . . . . . . . . . . . . . . . . . . . . . 55
B..8 Tess2Speech’ Image Viewer . . . . . . . . . . . . . . . . . . 56
B..9 Tess2Speech’ Camera . . . . . . . . . . . . . . . . . . . . . . 56
B..10 Image Cropping and Rotation . . . . . . . . . . . . . . . . . 56
B..11 Tess2Speech’ PDF Viewer . . . . . . . . . . . . . . . . . . . 56
B..12 PDF to Image and Vice-Versa . . . . . . . . . . . . . . . . . 57
B..13 Tess2Speech’ Ebook Viewer . . . . . . . . . . . . . . . . . . 57
B..14 Tess2Speech’s Built-in File Picker . . . . . . . . . . . . . . . 57
B..15 Saving Files . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
B..16 Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
B..17 Tess2Speech Trainer . . . . . . . . . . . . . . . . . . . . . . 58
C. Technical Architecture . . . . . . . . . . . . . . . . . . . . . . . 59
C..1 Development Environment . . . . . . . . . . . . . . . . . . . 59
C..2 Minimum System Requirements . . . . . . . . . . . . . . . . 60
D. Training Methodology . . . . . . . . . . . . . . . . . . . . . . . . 61

V. Results 63
A. Tess2Speech Mobile Application . . . . . . . . . . . . . . . . . . 63
A..1 Splash Screen . . . . . . . . . . . . . . . . . . . . . . . . . . 63
A..2 Home Screen/Canvas . . . . . . . . . . . . . . . . . . . . . . 63
A..3 Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
A..4 Browsing Image . . . . . . . . . . . . . . . . . . . . . . . . . 65
A..5 Displaying, Rotating, and Cropping Images . . . . . . . . . 66
A..6 Converting to Text . . . . . . . . . . . . . . . . . . . . . . . 67

v
A..7 Converting to Speech . . . . . . . . . . . . . . . . . . . . . . 68
A..8 Browse an Input PDF . . . . . . . . . . . . . . . . . . . . . 69
A..9 Browse an Input Epub . . . . . . . . . . . . . . . . . . . . . 71
A..10 Saving . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
A..11 Converting Image to PDF and Vice-versa . . . . . . . . . . . 73
A..12 Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
B. Tess2Speech Trainer . . . . . . . . . . . . . . . . . . . . . . . . . 76
B..1 Graphical User Interface . . . . . . . . . . . . . . . . . . . . 76
B..2 File Picker Dialog . . . . . . . . . . . . . . . . . . . . . . . . 77
B..3 Box Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
B..4 Automatic Training . . . . . . . . . . . . . . . . . . . . . . . 78

VI. Discussions 80
A. Tesseract Training . . . . . . . . . . . . . . . . . . . . . . . . . . 80
A..1 Training Results . . . . . . . . . . . . . . . . . . . . . . . . 80
A..2 Problems Encountered in Training . . . . . . . . . . . . . . 83
B. Developing Tess2Speech Trainer . . . . . . . . . . . . . . . . . . 84
B..1 Tess2Speech Trainer Results . . . . . . . . . . . . . . . . . . 84
B..2 Problems Encountered in Developing Tess2Speech Trainer . 85
C. Tess2Speech Mobile Application . . . . . . . . . . . . . . . . . . 85
C..1 Tess2Speech Results . . . . . . . . . . . . . . . . . . . . . . 85
C..2 Problems Encountered in Tess2Speech Application . . . . . 86
D. Significance of Tess2Speech . . . . . . . . . . . . . . . . . . . . . 89

VII. Conclusions 90

VIII. Recommendations 91

IX. Bibliography 92

X. Appendix 97
A. Box File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

vi
B. Source Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
B..1 Tess2Speech Mobile Application . . . . . . . . . . . . . . . . 101
B..2 Tess2Speech Trainer . . . . . . . . . . . . . . . . . . . . . . 158

XI. Acknowledgment 185

vii
List of Figures

1 Example of OCR in the 1930s when there are still no electronic


computers. [18] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2 Consonants of Odia Alphabet. [21] . . . . . . . . . . . . . . . . . . 14
3 Screen Capture of HandySpeech Interface. [15].
Image from:(https://itunes.apple.com/us/app/handyspeech/
id563600464?mt=8) . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4 Areas of Character Recognition. [26] . . . . . . . . . . . . . . . . . 19
5 Most OCR Tool’s Process would look like this. [27] . . . . . . . . . 20
6 Field tree – foundation of the LCS Community. [28] . . . . . . . . . 23
7 Tesseract-OCR Architecture. [18] . . . . . . . . . . . . . . . . . . . 29
8 Tesseract-OCR Architecture in Recognizing a word. [18] . . . . . . 30
9 A set of candidate chop points with arrows and the selected chop
as a line across the outline where the ’r’ touches the ’m’ [18] . . . . 31
10 Example of easily recognized word by Character Associator [18] . . 31
11 Static Character Classifier way of identifying the character using
the training prototype data [18] . . . . . . . . . . . . . . . . . . . . 32
12 Training Images Sample . . . . . . . . . . . . . . . . . . . . . . . . 35
13 Screenshot of jTessBoxEditor [32]. . . . . . . . . . . . . . . . . . . . 36
14 Block Diagram of Tess2Speech . . . . . . . . . . . . . . . . . . . . . 44
15 Sub-Explosion of Image Preprocessing in Fig. 14 . . . . . . . . . . . 44
16 Sub-Explosion of Tesseract in Fig. 14 . . . . . . . . . . . . . . . . . 45
17 Sub-Explosion of Text-to-Speech in Fig. 14 . . . . . . . . . . . . . . 45
18 Block Diagram of Tesseract Trainer . . . . . . . . . . . . . . . . . . 46
19 Block Diagram of Tesseract’s Training[18] . . . . . . . . . . . . . . 47
20 Flowchart of Tess2Speech Mobile Application . . . . . . . . . . . . 49
21 Flowchart of Tess2Speech Trainer . . . . . . . . . . . . . . . . . . . 51
22 Use-Case diagram of Tess2Speech . . . . . . . . . . . . . . . . . . . 53
23 Training Images Sample . . . . . . . . . . . . . . . . . . . . . . . . 62

viii
24 Splash Screen of Tess2Speech . . . . . . . . . . . . . . . . . . . . . 63
25 Home Screen/Canvas of Tess2Speech . . . . . . . . . . . . . . . . . 63
26 Camera Functionality of Tess2Speech . . . . . . . . . . . . . . . . . 64
27 Browse Image Functionality of Tess2Speech . . . . . . . . . . . . . 65
28 Displaying an image . . . . . . . . . . . . . . . . . . . . . . . . . . 66
29 Converting to Text . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
30 Converting the image in 28a to Speech . . . . . . . . . . . . . . . . 68
31 Browsing a PDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
32 Displaying Epub . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
33 Saving Files to .txt, .pdf, or .wav . . . . . . . . . . . . . . . . . . . 72
34 Converting Image to PDF and Vice-versa . . . . . . . . . . . . . . . 73
35 Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
36 GUI of Tess2Speech Trainer . . . . . . . . . . . . . . . . . . . . . . 76
37 File Picker Dialog of Tess2Speech Trainer . . . . . . . . . . . . . . . 77
38 Box Editor (edited jTessBoxEditor [32]) . . . . . . . . . . . . . . . 78
39 Automated Training . . . . . . . . . . . . . . . . . . . . . . . . . . 78
40 Test Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
41 Image Pre-processing . . . . . . . . . . . . . . . . . . . . . . . . . . 87

ix
List of Tables

1 Tesseract OCR Result Analysis after Grayscaling images. [22] . . . 16


2 Distribution of training and test samples of different users [3] . . . . 42
3 Result of the Rakshit and Basu’s experiment. [3] . . . . . . . . . . 42
4 Character Distribution of Training Dataset . . . . . . . . . . . . . . 80
5 Summary of the results of the default Tesseract trained data. . . . . 82
6 Summary of the results of the experimental trained data that I
created. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

x
I. Introduction

A. Background of the Study

A machine performing human-like capabilities is a dream we only see in Sci-Fi


movies. But over these past decades, that dream is slowly growing into reality.
Many applications and programs that make machine exhibit human-like behavior
were being developed such as OCRs and Text-to-Speech systems.
Optical Character Recognition (OCR) is a technology in the field of computer
vision that enables us to convert scanned paper documents, PDF files, and images
of computer-typed text, into an editable and searchable machine encoded-text
that the computer can manipulate [1].
Intelligent Character Recognition (ICR) is an advanced OCR which allows
different fonts to be learned by the computer. These fonts include different styles
of human handwritings [2]. In general, ICR systems have potential applications
in extracting data from filled in forms, interpreting handwritten addresses from
postal documents, automatic reading of bank cheques etc.[3]
Although, there is still no existing OCR that can read all characters in an
image with 100% accuracy especially when it comes to handwritten characters.
According to a research paper by Ch, S., Mahna, S., and Kashyap, N. entitled
Optical Character Reader on Handheld Devices [4], there are issues that they
encountered while using OCR on handheld devices namely: images often suffer
from skew and perspective distortion, uneven or insufficient illumination, lack of
auto-focus technology on the handheld devices camera, processors of handheld
devices are limited, and lack of arithmetic capabilities. These imply that the
accuracy of the OCR system depends on various factors affecting the quality of
the image which are: Focus of the camera, resolution of the picture, amount of
noise present etc. They tested an OCR called Tesseract using their handheld
devices and it achieved an average accuracy of 93% in reading non-handwritten
texts.

1
Tesseract is an open-source OCR library written in C++ that is now being
improved extensively by Google [5]. Tesseract also has the functionality to be
trained to read different font styles which technically makes it an ICR. This means
that Tesseract has the capability to learn human handwritings through training.
Tesseract uses ’.traineddata’ files as a data file for recognizing texts. These files
contains the character sets, character shapes, fonts, etc. that Tesseract will be
able to recognize. These files are produced by using Tesseract’s training tools.
Other existing systems today are under Speech Synthesis, which is a field in
Computer Science which pertains to the artificial production of human speech.
Android has a built-in Text-to-Speech (TTS) System since Application Program
Interface (API) level 4 (Android 1.6 code name ’Donut’) and recently introduced
an improved TTS in API level 17 (Android 4.2.2 code name Jelly Bean) [6].
With these existing libraries and functionalities, there are numerous possibil-
ities for creating new applications which are yet to be explored. One example
of this application is a Handwritten Text-to-Speech Android application in which
you write words to the device’s screen and convert it to speech. This application
can be very useful to patients that are suffering from different speech impairments.
One specific example of a speech impairment is Aphasia – a communication dis-
order that results from damage to the parts of the brain that contain language [7]
after a stroke. If a patient has not significantly recovered from aphasia two weeks
after a stroke, speech and language therapists will assess the patients alternative
means of communication possible [8]. This application could be that alternative
communication method.
Smartphones and tablet technology are the ideal platforms for this type of
application since these technologies has evolved to the point that almost everyone
has immediate access to this device. According to the latest report of US-Based
Industry tracker Strategy Analytics, nearly 2.5 billion people or 35% of the global
population is expected to have smartphones by the end of 2015 [9].
There are already applications that can save handwritten text to an image file,

2
but only a limited few, proprietary at that, can convert handwritings on a tablet
screen into computer text with significant accuracy. These phones support stylus-
based screens and one of those pioneers of handwritten-to-text is the Galaxy note.
One example of this is that according to a Korean news agency Yonhap, Samsung
agreed to buy 5% of the Japanese company Wacom for $58.2 million just for the
technology of their Stylus pens [10]. This is to improve Samsungs Galaxy Notes
performance which has handwritten-to-text functionality. With these existing
trends in the mobile world, there is a need for creating a free and non-proprietary
handwriting recognition software.
Smart phones and tablets are also more suitable for these kinds of applications
since they are more interactive compared to desktop. They are portable, have
built in camera, and support touchscreen functionality.

3
B. Statement of the Problem

Existing OCRs today for computer-typed texts are now producing good and ac-
curate results which can even achieve a close to 100% accuracy for certain input
images [11]. Unfortunately, handwriting recognition is harder to implement due
to high variability of peoples handwriting [12]. Due to this, its hard to find free
handwriting ICRs that produces satisfactory results. Most of them are proprietary
and expensive such as A2iA which is an ICR that can read handwritten text with
satisfactory results [13]. Another problem is that it is not a mobile application
and is only available for desktop computers.
By default, Tesseract cannot recognize handwritten text. Even though that
it is trainable, there are still no official trained data for it that are existing that
specializes in recognizing handwritten text.
People with poor eyesight have difficulties in reading PDF files or images of
computer-typed texts. They tend to rely on the zoom-in capabilities of their
phone. This causes to limit the words they can see on the screen and constantly
swipe it to read the next word. With a portable image-to-speech application,
these images can be converted to voice quickly and know the contents of these
files without reading them.
People with speech impairment, one for example is Stephen Hawking, relies
on Speech Synthesizer to communicate which costs a lot of money. Even with
this technology, those who are older and not technologically inclined tend to have
difficulties using keyboard of Speech Synthesizers compared to writing using a
pen, stylus, or even fingers.
Speech impairments are conditions in which the ability to produce speech
sounds that are necessary to communicate with others is impaired [14]. This
can include aphasia after having a stroke, throat cancer, trauma, ALS, muscular
dystrophy, people placed on vocal rest etc.
People with speech impairment that cannot afford to buy speech synthesizers,
like one of those Stephen Hawking has, tend to find an inconvenient alternative

4
means of communications such as alphabet boards, pictures, drawing board, sign
language, communication charts, and books [8]. The use of pen and paper, aside
from it is hard to convey emotions through written texts, can also be inconvenient
because the writer will need to give the paper to the ones that he/she is communi-
cating to. Without a free and easy-to-use technology that can help these people,
communication will remain a challenge for them.
Another problem is that pre-school students sometimes do not know how to
pronounce the words that they wrote. A smart phone or tablet application that
automatically pronounces the words that they write on the screen has not yet been
implemented in a school even though it could prove to be very beneficial.
Even with these existing problems, HandySpeech is the only existing applica-
tion in Android and iOS that can convert handwritten text to speech [15]. Another
problem is that this application is not free and costs $29.99.
Another existing problem is that mobile ICRs like HandySpeech is not re-
trainable, which means that the user cannot re-train their application once it is
deployed. It is also not personalizable which means that the user’s handwriting
might not be recognized by the application. The application does not have a way
to recognize your handwriting unless you contact the application developers.

5
C. Objectives of the Study

1. To be able to create a Tesseract Trained Data for handwritten texts with at


least 80% accuracy.

2. To be able to create a user-friendly desktop application that performs Tesser-


act’s training automatically.

3. To develop a free mobile based image-to-speech application with the follow-


ing features:

(a) Either upload an image that contains the handwriting (can also be com-
puter printed texts) or write the handwritten text itself on the mobile’s
screen, and output the voice equivalent after the image processing.

(b) Save the converted text file in either .txt or .pdf format, and the output
voice in .wav format.

(c) To allow users to personalize and re-train Tess2Speech to recognize


their own handwritings even after deployment. It can be done by using
Tess2Speech Trainer which is a desktop application bundled with this
application, or through updates.

6
D. Significance of the Project

1. Creating Tess2Speech will provide users with free, portable, and non-proprietary
Intelligent Character Recognition Engine.

2. Tess2Speech will provide other researchers or users with re-trainable ICR


Engine. Since it is re-trainable, it will continue to improve through time [5].
This will help other researchers to develop their own ICR without spending
money and time. This study also gives the researcher an idea to whether
the accuracy of Tesseract is satisfactory, not only on computer-typed text,
but also for handwritten text when training has been done.

3. According to HandySpeech [15], which is a non-free handwriting-to-speech


application, this application can reduce the frustration and helplessness of
patients suffering from speech impairments brought about by the inability
to talk. Such voice impairments that this application can help are speech
disorders resulting from vocal fold pathology, oral and laryngeal cancers,
motor speech disorders affecting larynx and oral structures such as apraxia
of speech, patients who are placed on vocal rest due to recent surgery, indi-
viduals with ALS, muscular dystrophy as long as they have enough motor
control to write.

4. Unlike HandySpeech, Tes2Speech will be free and has both OCR and ICR
capabilities. This means that it is not only limited on reading handwritings
written on the smart phone’s screen since the user also has a choice to
upload an image (either by taking a photo or browse an existing image file)
that contains computer-typed or handwritten texts, and convert it to both
editable text and speech.

5. Tess2Speech can also help users in reading or proof-reading their typed or


handwritten work because errors in written texts can be detected more ap-
parently and can be criticized more comprehensibly when they are read out
loud. Examples of these errors are the construction of sentences and mis-

7
spelled words [16].

6. Tess2Speech can also save their time by allowing them to convert texts on a
printed paper to an editable text in their devices without needing to retype
the whole paper.

7. Tess2Speech can also be useful in teaching pre-school students because some-


times pre-school students know how to write but does not know how to pro-
nounce the words that they wrote. By using this application, the students
can just write the words on the screen or take a picture of the words that
they wrote, and let this application pronounce those words. The students
can also check if their spelling is correct since this application also notifies
the user if the converted text exists in the English Dictionary.

8. Tess2Speech can be an easier and cheaper substitute for those expensive


voice synthesizers.

9. Since the user can save the recognized text into a .wav file, they can listen to
their document on-the-go after scanning by using earphones or headphones.

8
E. Scope and Limitations

1. Handwritten characters that Tess2Speech can convert are limited to non-


cursive (printed/block letters) handwritings. The letters are neither joined
together nor very close that it overlaps each other to produce satisfactory
results.

2. Tess2Speech only accepts PDF, JPEG, GIF, PNG, and BMP image formats
as input images. Ebook with .epub extensions are also accepted as input.

3. Words that Tess2Speech can convert to speech are limited to English lan-
guage. But it can be trained in future to read languages other than English.

4. Handwritten or computer typed texts that Tess2Speech can recognize is only


limited to the characters present on the training set provided.

5. The training set can contain any Unicode characters (coded with UTF-8)
[5].

6. Image noises such as poor illumination (see Chapter 3 C..6), skewed text,
garbage on texts such as strike-through, underline, erasures, broken texts,
and other lines that are not related to a character can greatly reduce Tess2Speech’s
accuracy.

7. Handwritten texts should be written using a black marker pen which have
at least an ultra-fine point in a white paper (or any white background). The
border of the paper should not be seen as it adds noise to the image and
may be interpreted as a character such as ’l’ (small L) or ’1’ (one).

8. The training is not a functionality of Tess2Speech mobile application. Train-


ing is done separately using Tess2Speech Trainer which is a desktop appli-
cation. This is because as of now, Tesseract can only be trained on desktop.

9. Tess2Speech Trainer is a desktop application that can only train for English
language because it always includes English dictionary when training for
different fonts.

9
10. The accuracy of Tesseract will be dependent on the quality of the handwrit-
ing and quality of the image itself. The higher the quality of the image, the
higher the accuracy of this application [5].

11. It is not recommended to use the phone’s camera if the desired input contains
small texts such as document, handwritten paragraphs, etc. A scanner is
recommended for these types of input.

12. The quality of the converted speech will be dependent on the Text-to-Speech
Engine installed by the user.

13. The performance of Tess2Speech’ writable canvas is dependent on the phone’s


hardware (touchscreen capability).

14. Tess2Speech does not require internet connection to work.

10
F. Assumptions

There are several assumptions made prior to the development of this application:

1. The OS of the mobile phone that this application will be installed to is


Android with minimum Application Program Interface (API) level 16 or
also called as Android 4.1 (Jelly Bean).

2. There are words or characters on the images that Tess2Speech is converting.

3. The words being processed are in English Dictionary, is/are readable, not in
cursive form, and as much as possible has minimal noises.

4. The input image contains black texts on a white background. If this con-
dition is not met, the image should at least be binarizeable (see chapter 3
C..2) – which are images that can be converted to black and white.

5. The user has a Text-to-Speech Engine installed on their mobile phone.

6. The users have an SD card inserted on their mobile phones.

7. The user has a desktop computer (aside from their mobile phone) and has
Java Installed.

11
II. Review of Related Literature

Since this application can be divided into two – Optical Character Recognition
and Text-to-Speech – some researches only exists for OCRs/ICRs and some only
exists for TTS.

A. Image-to-Text

A..1 Optical Character Recognition/Intelligent Character Recognition

The origin of character recognition can be found way back in 1870 and predates
electronic computers (see Figure 1). During the first decades of the 19th century,
several attempts were made to help develop devices to aid the blind. However,
the modern version of OCR did not appear until the middle of 1940s with the
development of digital computer [17].

Figure 1: Example of OCR in the 1930s when there are still no electronic com-
puters. [18]

12
Modern OCRs have character recognition rates of up to 99% on high quality
documents. If we have an average word length of 5 characters, this still means that
one out of 20 words is defect. Thus giving us at least 5% of all processed words
will have an OCR error [19]. Realistically, this OCR error will be even higher
because aside from this results are not from handwritten texts; there are many
factors such as the quality of the document, quality of the image, noise present in
the image, and print quality.

One research paper entitled Optical Character Recognition for Handwritten


Cursive English Characters [17] used a four-step method for their character recog-
nition:
First Step: Image Acquisition
Second Step: Image Pre-processing step where they used different image
pre-processing to enhance the image and convert it to a more usable form.
Third Step: Segmentation step wherein they separate the characters in a
word.
Fourth Step: Feature Extraction which is the extraction of the texture and
feature of the handwritten characters.

A research paper entitled Tesseract vs Gocr A Comparative Study [20] provided


error analysis of most common errors in Tesseract. Some of them are:

1. ’F’ is recognized as ’T’.

2. ’q’ is recognized as ’0’.

3. ’i’ is recognized as ’l’.

4. ’o’ is recognized as ’0’.

5. ’p’ is recognized as ’0’.

6. ’d’ is recognized as ’cl’ or ’0’.

7. ’g’ is recognized as ’0’.

13
8. ’ !’ is recognized as ’t’.

The research also proved that Tesseract indeed performs better than Gocr
which is another OCR tool.

There are also countless researches about training Tesseract, one example is
training Tesseract to recognize Odia Language [21] (see Figure 2). Odia language
is used in the state of Odisha (formerly known as Orissa), India.

Figure 2: Consonants of Odia Alphabet. [21]

The alphabet can be considered as a very complicated alphabet but they still
managed to train Tesseract to recognize its alphabets. This further proves that it
is possible that Tesseract can be taught to recognize handwritten characters.

14
The research paper by Rakshit, S. and Basu, S. [3] trained Tesseract to rec-
ognize handwritings. They concentrated on training Tesseract to recognize only
lower case characters of Roman Script. Though their training data set is small,
they still managed to produce accuracy around 78.4%. They also noticed that
Tesseract rejects around 9.24% characters in the data set mainly due to multi-
skewed handwritten text lines in the test documents. Completely cursive words
were also rejected completely in many cases during the experimentation. They
also concluded that the performance of the designed system can be improved by
incorporating more training data and inclusion of word-level dictionary matching
techniques.

A..2 Image Pre-Processing Techniques

Another research paper entitled Intelligent Character Recognition (ICR): A Novel


Algorithm to Extract Text from a Scanned Form Based Image [2] proposed a
system which performs a series of image pre-processing to aid the OCR. These se-
ries of image pre-processing are Binarization using different types of thresholding,
Skew Detection and De-Skewing, Slant Detection, Smoothing, Cleaning, Enhanc-
ing, Pre-Segmentation, Character Recognition, Separation of Characters, Normal-
ization of Characters, Thinning, Grid Formation, Singular Point Determination,
Line-Detection, Character Matching, and Post-processing. They have developed
a system which produces adequate accuracy in reading scanned form based images.

The paper entitled Optical Character Recognition by Open Source OCR Tool
Tesseract: A Case Study [22] proved that using grayscale images enhances the
accuracy of Tesseract (see Table 1).

15
Table 1: Tesseract OCR Result Analysis after Grayscaling images. [22]

A research by Ntirogiannis, K. entitled Performance Evaluation Methodology


for Historical Document Image Binarization [23] further proved that Binariza-
tion of image is of great importance in document image analysis and recognition
pipeline since it affects further stages of the OCRs recognition process. He con-
cluded that converting a document into a binary image can help in document
image analysis. A binary image is an image wherein there can only be two possi-
ble values for each pixel (Black or White).

16
B. Text-to-Speech

There are also many researchers who ventured and discussed Text-to-Speech. A
study done by Chandra E. and Sasirekha, D. [24] summarized published literatures
on TTS and discussed the efforts taken in each paper. They concluded that there
are many free TTS libraries and applications in our market today that continues
to improve. They also discussed the 5 fundamental components of TTS systems
namely:

1. Text analysis and detection

2. Text normalization and linearization

3. Phonetic Analysis

4. Prosodic Modeling and Intonation

5. Acoustic Processing

C. Image-to-Speech

There are also researches that discussed and ventured on making a similar ap-
plication of performing image-to-speech application. One such paper is Optical
Character Recognition by Mithe R., Indalkar, N., and Divekar N. [25] in which
they also used Tesseract as their OCR but did not train it to recognize handwritten
texts. They use Speech Synthesizer to convert text into audible speech. They have
successfully created a mobile application that converts an image of computer-typed
text into editable text. They also stated limitations of their application which are:

1. Accuracy of an OCR system is directly dependent on the quality of input


document.

2. The output from OCR systems is often quite noisy and garbled. In order to
correct this, the application will perform some post processing on the text
after it has received a response from the OCR package.

17
D. HandySpeech

HandySpeech is the only handwriting-to-speech application for iOS devices. HandyS-


peech lets users write on the screen of the tablet using a stylus or ones finger and
this application will convert it to speech. The voices that this device can use
can be a male or a female. It can learn the users handwriting style, understands
cursive, print and mixed handwriting styles, and contains dictionary of unusual
words. Recently, HandySpeech also implemented a voice-recognition capability
which is powered by Nuance. This application was created by a 12-year old boy
who was inspired by hear autistic sister which has speech disabilities [15]. Though
this application can recognize text, it doesnt have the capability to read text from
images captured by the phones camera. The texts that this application can read
is limited to the texts written on the tablets screen which limits the number of
words that it can convert to speech.

Figure 3: Screen Capture of HandySpeech Interface. [15].


Image from:(https://itunes.apple.com/us/app/handyspeech/id563600464?
mt=8)

18
III. Theoretical Framework

There are many areas in Character Recognition:

Figure 4: Areas of Character Recognition. [26]

In this special project, I will venture through Off-line Handwritten Script


Recognition and Verification.

19
A. Optical Character Recognition

Optical Character Recognition technology automatically recognizes texts from im-


ages with formats like JPG, PNG, BMP, GIF, TIFF and multi-page PDF files.
OCR involves analysis of the captured or scanned images and then translate char-
acter images into character codes, so that it can be edited, searched, stored more
efficiently, displayed on-line, and used in machine processes [27].
While we view text documents as lines of text, computers actually see them as
binary data, or a series of ones and zeros. Therefore, the characters within a text
document must be represented by numeric codes. In order to accomplish this, the
text is saved using one of several types of character encoding such as ASCII and
UTF-8 [1].

Figure 5: Most OCR Tool’s Process would look like this. [27]

OCR tools processes are step-by-step and defined as: [27]

A..1 Input Image

These are digitalized images like a scanned or captured text images. It could be
of different formats, i.e. PDF, TIFF, JPEG, GIF, PNG, and BMP image.

A..2 Preprocessing

This is a step essential for OCR systems for image handling. This is the step
where the image is enhanced through different image processing techniques such

20
as adding or removing of noises, maintaining the correct contrast of the image,
background removal, etc.

A..3 Segmentation

The accuracy of the OCR depends on the Segmentation algorithm used. Seg-
mentation consists of different steps. First is Page Segmentation which is the
separation of graphics from text. Next is Word Segmentation which is the prob-
lem of dividing a string of written language into its component words. Finally,
Character Segmentation separates characters from the others.

A..4 Feature Extraction

This step refers to the extraction of the most relevant information from the text
image which helps to recognize the characters in the text.

A..5 Classification/Recognition

It is the step wherein optical patters are classified into alphanumeric and other
characters. The information should be readable to both human and machine.

A..6 Post Processing

The goal of this step is to increase recognition by checking grammatical errors and
misspellings in the OCR output text after the input image has been scanned and
completely processed.

A..7 Output Text

The editable text that is extracted from the input image is displayed in the output
text.

21
B. Intelligent Character Recognition, Learning Classifier

Systems, and Neural Networks

Intelligent Character Recognition (ICR) is an advanced OCR which allows differ-


ent fonts to be learned by the computer through training. These fonts include
different styles of human handwritings [2]. According to Ray Smith [18], who is
from Google, Tesseract uses Adaptive Classifier as its default training mechanism.
But after reading the wiki on Tesseract-OCR, there is an option called ”Cube
Mode” where Tesseract will switch to using Neural Network for the learning in-
stead of the adaptive classifier. Unfortunately, Tesseract will now deprecate Cube
Mode since using it is slower, and will now introduce a better adaptive classifica-
tion algorithm [5].

B..1 Artificial Neural Network (ANN)

An Artificial Neural Network (ANN) or sometimes called Neural Network (NN) is a


mathematical or computational model that is inspired by the way biological neural
networks, like our brains, process information. A neural network consists of highly
interconnected group of artificial neurons that works together to solve specific
problems using a connectionist approach. ANNs, like people, are an adaptive
system and can learn by examples. ANN changes its structure based on external
or internal information that flows through the network during the learning phase
[26].
Since Tesseract’s Cube Mode is now deprecated, Tesseract will not use this as
their Training Mechanism anymore.

22
B..2 Learning Classifier Systems

Learning Classifier Systems (LCS) is one of the many Nature-Inspired Algorithms.


LCS is a combination of Evolutionary algorithm from the Biology Field, and Re-
inforcement Learning and Supervised Learning from the Machine Learning Field
[28] (see Figure 6).
Learning Classifier System algorithm optimizes payoff or reward based on ex-
posure to stimuli from a problem-specific environment by managing credit assign-
ment for those rules that prove useful and searching for new rules and variations
on existing rules using an evolutionary process [29].

Figure 6: Field tree – foundation of the LCS Community. [28]

23
An LCS has four practically universal components [28]:

1. A finite population of classifiers that represents the current knowledge of the


system.

2. A Performance Component, which regulates interaction between the envi-


ronment.

3. A Reinforced Component, which is also called credit assignment component,


which distributes reward received from the environment to the classifier.

4. A Discovery Component which uses different operators to discover better


rules and improve existing one.

According to Smith [18], It has been suggested and demonstrated that us-
ing Adaptive Classifier can improve OCR engine’s accuracy. It will be further
discussed later on (see D.).

24
C. Image Processing/Preprocessing

Here are some image processing techniques that are usually used in OCRs [2]:

C..1 Grayscaling

GrayScaling is an image processing technique that converts the images color into
a range of gray shades from white to black.
Basic grayscale algorithms utilize three basic steps[30]:

1. Get the Red, Blue, and Green values of a pixel (RGB Color Channels).

2. Use math to turn the combined values of Red, Blue, and Green pixel into a
single gray value.

3. Replace the original Red, Blue, and Green pixel with the new gray value.

Another approach is the desaturation of the image. In this method, instead


of using the RGB Space (Red, Green, Blue), the HSL color space is used (Hue,
Saturation, lightness). Hue could be considered as the name of the color (Red,
Blue, Green etc.). Mathematically, hue is described as an angular dimension on
the color wheel ranging from 0◦ to 360◦ , where pure Red occurs at 0◦ and 360◦ , pure
Green at 120◦ , and pure Blue at 240◦ . Saturation describes on how pure or vivid
a color is. A pure color has 100% saturation while gray has 0% or no saturation.
Lightness describes the brightness of a color; white has full lightness, while black
has zero lightness.
This implies that by setting the saturation of an image to 0, we can easily
create a grayscale image.

25
C..2 Thresholding & Binarization

Thresholding is an image segmentation method that converts a gray scale image


into a binary image using different kinds of Thresholding algorithms. Binary image
is a black and white image. Each pixel could only have 0 or 1 as values (black or
white).
Tesseract is using a Binarization method called Otsu Binarization before it
process an image. The method involves iterating through all the possible threshold
values and calculating a measure of spread for the pixel levels each side of the
threshold, i.e. the pixels that either falls in foreground or background. The aim is
to find the threshold value where the sum of foreground and background spreads
is at its minimum [31].

C..3 De-Skew

De-Skewing is an image processing technique that aligns tilted and skewed doc-
uments by tilting the image a few degrees clockwise or counter-clockwise. I will
use an alternative for automatic de-skewing since this image processing technique
is very broad and studying its implementation is another topic.

C..4 Separation of Characters/Segmentation

The idea behind separation of characters is to search the blank spaces between
the individual characters to identify which are the cut-off points of the scanned
word. Tesseract is already implementing this inside its function and will be further
discussed at the next section (see D.).

C..5 Character Normalization

Since handwritten characters vary greatly in different styles, we normalize the


characters. Normalization means that a character is made to fit into a standard
size square. This means that characters that are close to the normalized character

26
will be considered as that normalized character. Tesseract is already implementing
this inside its function.

C..6 Adjusting Brightness and Contrast

Adjusting Brightness and Contrast can help process an image with poor illumina-
tion and can also be an alternative for Thinning since increasing brightness and
contrast can result to a pseudo-thinning to a character. Illumination is the amount
of light present in an image.
Thinning is applied to all normalized characters. It refers to the reduction
of the thickness of the normalized character to create a more general and non-
strict normalized character. Thinning only retains the most significant feature or
identifiers of a character.
Android can use a Matrix to manipulate a bitmap’s color [6]. This Matrix is
called a Color Matrix which is a 5 x 4 matrix for transforming the color and alpha
components of a Bitmap. The matrix can be passed as single array, and is treated
as follows:

[ a, b, c , d, e ,
f , g, h, i , j ,
k , l , m, n , o ,
p, q, r , s , t ]

Then, if we apply this matrix to a color [R, G, B, A] (where R = Red, G = Green,


B = Blue, A = Alpha – transparency of bitmap), the resulting color is computed
as:

R = a∗R + b∗G + c ∗B + d∗A + e ;


G = f ∗R + g∗G + h∗B + i ∗A + j ;
B = k∗R + l ∗G + m∗B + n∗A + o ;
A = p∗R + q∗G + r ∗B + s ∗A + t ;

27
That resulting color [R, G, B, A] then has each channel restricted to the 0 to 255
range.
With this knowledge, we can adjust the brightness and the contrast of an im-
age by applying this matrix to the image:

contrast , 0, 0, 0 , brightness ,
0, contrast ,0 , 0 , brightness ,
0, 0, contrast ,0 , brightness ,
0, 0, 0, 1, 0

Where the default value of contrast is 1 and can have any value from [1,10],
and the default value for brightness is 0 and can have any value from [-255, 255].

D. Tesseract

Tesseract is Free Open-source OCR engine. It was first developed between 1984
and 1994 at HP. In 1995, it was one of the top 3 engines in the 1995 UNLV
Accuracy test after the joint project between HP Labs Bristol and HPs Scanner
Division in Colorado. Finally in 2005, Tesseract was released as open source by
HP and is now being extensively developed by Google which greatly increased
its accuracy [25]. Tesseract supports over 60 languages and is combined with
the Leptonica Image Processing Library which can read a wide variety of image
formats and perform some image processing for Tesseract [5]. It is available at
http://code.google.com/p/tesseract-ocr.

D..1 Tesseract Architecture

Tesseract OCR works in a step by step manner. These steps are shown in figure
7 and are also defined below according to the research done by Patel, C., Patel,
D., and Patel, A. [22].

28
Figure 7: Tesseract-OCR Architecture. [18]

1. Adaptive Thresholding
This is the step wherein the input image is converted into a binary image
using Otsu’s Binarization Method.

2. Connected Component Analysis


This is the step which is used to extract the character outlines. It does the
recognition of character in the image with white text and black background.
These outlines are then converted into Blobs (Binary Large Objects), which
a collection of binary data stored as a single entity.

3. Find Text Lines and Words


This is the step wherein the Blobs are organized into text lines. Lines
and regions are analyzed for some fixed area or equivalent text sizes. Texts
are then divided into words. Tesseract created a line finding algorithm that
allows it to recognize a skewed page without de-skewing it.

4. Recognize Word Pass 1

29
The first pass is an attempt to recognize each word from the text. Each
word passed as satisfactory is passed to an adaptive classifier as a training
data.

5. Recognize Word Pass 2


The second pass is an attempt to recognize each word after it has learned
something new using the adaptive classifier (will be explained later on). With
these, various recognition issues are resolved and the texts from the images
are then extracted.

D..2 Tesseract Word Recognition

Tesseract uses Classifiers to train. Before we could analyze how Tesseract trains
its data, we need to know the architecture of Tesseract in recognizing words. This
architecture (see Figure 8), including each steps and the Classifiers, were discussed
by Smith, R. from Google Inc. as follows: [18]

Figure 8: Tesseract-OCR Architecture in Recognizing a word. [18]

30
1. Character Chopper Tesseract attempts to improve the result by chopping
the Blob with the worst confidence from the character classifier (will be
discussed later on in 4). Confidence is the measure on how confident or sure
the Tesseract is that the extracted word will be correct.
These chops (see Figure 9) are executed in priority order. If the chops
do not improve the confidence, the chops are undone but not completely
discarded because chops can be re-used by the associator if needed.

Figure 9: A set of candidate chop points with arrows and the selected chop as a
line across the outline where the ’r’ touches the ’m’ [18]

2. Character Associator
If all the potential chops have been exhausted but the words still have
low confidences, it is given to the associator and performs an A* (best first)
search of possible combinations of the maximally chopped blobs into candi-
date characters.

Figure 10: Example of easily recognized word by Character Associator [18]

3. Dictionary and Number Parser


Tesseract can use a dictionary that helps in recognizing words. A word
that is in the dictionary will increase its confidence. Tesseract’s built-in

31
dictionary can support different languages such as English, Tagalog, Indian,
etc. Dictionaries can also help Tesseract identify whether the text are a
number or a letter by using Punctuation and Number dictionary, aside from
the Wordlist dictionary.

4. Static Character Classifier


Static Character Classifier uses outline fragments extracted from the out-
line as features and matches it to the features of the prototype training data.
There is a process called small to large matching in the classifier that can
easily recognize a broken character. Performing Static Character Classifi-
cation is computationally heavy. This shows that Tesseract uses polygonal
approximation as input instead of the raw outlines, which is believed to be
a main weakness of Tesseract.

Figure 11: Static Character Classifier way of identifying the character using the
training prototype data [18]

5. Adaptive Character Classifier


Since Static Character classifier focuses on generalizing any kind of font,
its ability to discriminate between different characters is weakened. Due to
this, a more font-sensitive adaptive classifier is used to obtain greater dis-
crimination within each document, where the fonts are limited. Adaptive
Character Classifier is trained through the output of Static Character Clas-
sifier. Adaptive Character Classifier uses the same technique as the Static

32
Character Classifier. The only difference is that they use different normal-
ization techniques.

D..3 Training Tesseract

Here are the steps, commands, and required files in order to train Tesseract [5]
(see block diagram of training in Figure 19):

1. To train Tesseract, training tools for Tesseract should be installed on


your computer. These binary files should be present on your Tesseract
directory:

(a) ambiguous words.exe

(b) classifier tester.exe

(c) cntraining.exe

(d) combine tessdata.exe

(e) dawg2wordlist.exe

(f) mftraining.exe

(g) set unicharset properties.exe

(h) shapeclustering.exe

(i) tesseract.exe

(j) unicharset extractor.exe

(k) wordlist2dawg.exe

2. Identify the required files that we need to be able to create our trained
data. Suppose that we want to name our trained data as ’engh’. Then the
required files are:

(a) engh.unicharset

(b) engh.inttemp

(c) engh.pffmtable

33
(d) engh.normproto

(e) engh.shapetable

(f) engh.config (Optional)

(g) engh.punc-dawg (Optional)

(h) engh.word-dawg (Optional)

(i) engh.unicharambigs (Optional)

(j) engh.number-dawg (Optional)

(k) engh.freq-dawg (Optional)

(l) engh.bigram-dawg (Optional)

(m) engh.unambig-dawg (Optional)

(n) engh.params-model (Optional)

(o) engh.fixed-length-dawgs (Deprecated)

(p) engh.cube-unicharset (Deprecated)

(q) engh.cube-word-dawg (Deprecated)

The combination of these files will be ’engh.traineddata’, which will be


the final product of our training. Tesseract can now use this file to read the
font that we have trained it to.

3. Generating the training Image and creating a .box file.


Training image is the image that contains the characters you want Tesser-
act to learn (see Figure 12). The image format can be anything that Tesser-
act accepts, however the recommended format is TIFF because it can contain
multiple image in one image file which can minimize the number of image
files in our directory. The Training image should be readable by Tesseract
and should contain one type of handwriting per image file if possible, (which
is also the reason why TIFF is recommended) for more accurate results.

34
Figure 12: Training Images Sample
(a) Page 1 (b) Page 2

(c) Page 3 (d) Page 4

35
The box file is a text file which has a .box extension. It contains the
characters in the training image, in order, one per line, with the coordinates
of the bounding box around the image. This is a sample content of a box
file (First letter ’A’ in page 1 of training images in Figure 12):

A 283 3208 372 3329 0

The format i s :
C h a r a c t e r X Y Width Height T i f f −Page

See Appendix A. for the whole content of the box file for the sample
training image in Figure 12.
As you can see from the example, creating a box file for numerous training
images is very tedious and time consuming. For this very reason, there exists
a free and open-source box editor and training tool called jTessBoxEditor
which is created by vietOCR [32].

Figure 13: Screenshot of jTessBoxEditor [32].

The training images’ filename format should be ’fontname.imagename.exp0.extension’


and the box file’s format should have the same name as its training image

36
counterpart except for the extension part. So in our case, if the training im-
age’s file name is ’engh.aaronfont.exp0.tiff’, its box file counterpart should
have a file name ’engh.aaronfont.exp0.box’.
Note that we can create any number of image-box file matching pairs
depending on how many fonts you want to train Tesseract.
To make things a little easier, you can use Tesseract to automatically
create a box file for the training image. It will automatically detect the
bounding boxes of the characters for you, although if Tesseract is not yet
trained to that language, it is guaranteed to label all, if not most, of the
characters wrong. This is where jTessBoxEditor will come in handy. You
will manually relabel and correct the bounding box of the produced box file
of Tesseract.
The command for Tesseract to make a box file is: (Assuming that you
open CMD on the same directory as the binary files, and the images and
box files are also in the same directory)
’tesseract engh.aaronfont.exp0.tif engh.aaronfont.exp0 batch.nochop
makebox’
This will output an ’engh.aaronfont.exp0.box’ file.

4. Generating (.tr) training file


For each of your training image, boxfile pairs, run Tesseract in training
mode:
’tesseract engh.aaronfont.exp0.tif engh.aaronfont.exp0 box.train’

This will output an ’engh.aaronfont.exp0.tr’ file which contains the dif-


ferent features for each character being trained.

37
5. Computing the Character Set
Tesseract needs to know the set of possible characters it can output or
in other words, its unicharset. The unicharset extractor program is used on
the box files to generate the unicharset data file:
’unicharset extractor engh.aaronfont.exp0.box’

This will output a single unicharset data file. Unicharset data file con-
tains character properties isalpha, isdigit, isupper, islower, ispunctuation.
Each line of this file corresponds to one character. The character in UTF-8
is followed by a hexadecimal number representing a binary mask that en-
codes the properties. Each bit corresponds to a property. If the bit is set
to 1, it means that the property is true. The bit ordering is (from least
significant bit to most significant bit): isalpha, islower, isupper, isdigit.

6. Creating a font properties file


The purpose of this file is to provide font style information that will
appear in the output when the font is recognized. For windows, it is recom-
mended to save the font properties text file as front properties.sh.
Each line of the font properties file is formatted as follows:
<fontname><italic><bold><fixed><serif><fraktur>
In our case, since we are training for handwritten texts and do not need
any font properties, our font properties file contains:
aaronfont 0 0 0 0 0

7. Clustering
After all the character features have been extracted, we need to clus-
ter them to create prototypes. This can be done by using shapeclustering,
mftraining, and cntraining programs.
Although according to Google, shapeclustering should only be used on

38
Indic Languages because this program is still experimental[5]. For this rea-
son, shapeclustering program will not be used in training handwritten texts.
To perform mftraining:
’mftraining -F font properties.sh -U unicharset -O engh.unicharset
engh.aaronfont.exp0.tr’

where ’unicharset’ is the unicharset file we extracted using unicharset extractor,


’font properties.sh’ file is the file created earlier, and engh.unicharset is the
output modified unicharset.
This will output three additional files which are:

(a) shapetable file, which contains the master shape table.

(b) inttemp file which contains the shape prototypes.

(c) pffmtable file which contains the number of expected features for each
character.

Next is to perform cntraining:


’cntraining engh.aaronfont.exp0.tr’

This will output a normproto file which contains the character normal-
ization sensitivity prototypes.

8. Optional Files
A Directed Acyclic Word Graph (DAWG), is a data structure that per-
mits extremely fast word searches. Each nodes of the graph represents a
letter, and you can traverse from the node to two other nodes, until the
letter matches the one you are searching for. Note that since it’s Acyclic,
meaning that there are no cycles, You can move from node A to Node B,
but not the other way around. [33]

(a) config file (engh.config) which is a text file that contains different

39
configurations that Tesseract will use when using this trained data.

(b) word-dawg which is a DAWG made from dictionary words from the
language. It is produced by creating a list of words (dictionary) in
a text file which are separated by new line and using wordlist2dawg
program to convert the text file to a DAWG file.
wordlist2dawg wordlist.txt

(c) punc-dawg which is also a DAWG file similar to word-dawg. But


instead of listing words, we list pattern of punctuations. The ”word”
part is replaced by a single space i.e. ! ? indicates that words are
frequently in between exclamation point and question mark. It is also
created using the wordlist2dawg program.
wordlist2dawg punctuations.txt

(d) unicharambigs which is not a DAWG file. It is a text file which


describes possible ambiguities between characters or sets of characters.
It is manually generated and has a format in (Tesseract version 3.03):
<characters for match source><tab><characters for match
target><tab><type indicator>
i.e
v2
” ” 1 ->for all ’ ’ encountered, change it to ”
m rn 0 ->if m is encountered, consider checking rn.
iii m 0 ->if iii is encountered, consider checking m.

(e) number-dawg’s format is the same as punc-dawg, but instead of using


symbols, numbers are used.
wordlist2dawg numbers.txt

(f) freq-dawg’s format is the same as word-dawg, but instead of listing the
whole dictionary, we only list the most frequent words in the language.

(g) bigram-dawg is a DAWG of word bigrams – a pair of consecutive


written units such as letters, syllables, or words – which is also created

40
from text file using wordlist2dawg, where the words are separated by a
space and each digit is replaced by a ?.
wordlist2dawg bigrams.txt

(h) unambig-dawg is still currently undefined in Tesseract’s page.

(i) params-model is still currently undefined in Tesseract’s page.

(j) fixed-length-dawgs is deprecated.

(k) cube-unicharset is deprecated.

(l) cube-word-dawg is deprecated.

9. Combining Components to Produce Trained Data


This is the last step to produce a .traineddata for our language. To
combine all the components, we first need to add a prefix ’lang.’ (in our
case ’engh.’) in the beginning of all the generated components from the
previous steps. Then we will use the combine tessdata program to combine
all the files with the prefix ’engh.’ to produce the final training data.
This will produce a .traineddata file (in our case ’engh.traineddata’),
which is a data file for Tesseract. In order to use this data file, we need to
copy this file to the ’tessdata’ folder of Tesseract. After copying, Tesseract
can now detect and use your language for recognizing texts.
tesseract -l engh sampleimage.tif textoutput

D..4 Criteria for Finishing Tesseract’s Training

The research done by Rakshit S. and Basu, S. [3] only used a three user model,
which means that they only collected handwriting samples from three individuals.
There are two data sets for each individual which are the Isolated Characters and
Free-Flow Texts. The distribution of training test and samples can be seen in
Table 2:
Isolated characters are from test samples that has only letters from a-z in each
and every row of the paper. They should not form a word but letters only. Free

41
Table 2: Distribution of training and test samples of different users [3]

flow texts are test samples that contain words and sentences i.e. handwritten
journal article, book, etc.

Table 3: Result of the Rakshit and Basu’s experiment. [3]

OCR’s recognition accuracy is computed using the formula:


Ct − Ce
RecognitionAccuracy = ∗ 100
Ct
Where Ct = the total number of characters and Ce = the number of misclas-
sified character.
As shown in the tables (Table 3), the overall character-level recognition ac-
curacy of their trained Tesseract OCR is around 78.4%. The overall character
misclassification rate is observed around 11%. Segmentation failures in the docu-
ment pages account for around 10.6% error cases. The trained OCR also rejects
around 9.24% characters in the test data test due to the presence of multi-skewed

42
handwritten texts and cursive words.
These results can still improve by incorporating more training samples for
each users and implementing different training technique/s to at least reach 80%
accuracy on handwritten texts.

E. Text-to-Speech

The focus of this project is on Optical Character Recognition training, so the


installed Text-to-Speech (TTS) system will be used and no further improvement
of the TTS system will be done. Users are allowed to download any TTS Engines
that they prefer in Google Play Store.

43
IV. Design and Implementation

A. Diagrams

A..1 Block Diagram of Tess2Speech Mobile Application

Tess2Speech combines Google’s Tesseract [5], which converts the input images into
text, and then convert it to speech. The block diagram is shown in Figure 14

Figure 14: Block Diagram of Tess2Speech

Figure 15: Sub-Explosion of Image Preprocessing in Fig. 14

In figure 15, you will notice that there is an Image Rotation and Image Crop-
ping. Image rotation and image cropping are functionalities of Tess2Speech, which
means that they are manual and the users are the ones that will indicate on how
will they rotate or crop an image. Image rotation serves as an alternative for im-
age de-skewing, and image cropping can eliminate the border problems (discussed
in Scope and Limitations #7) for some images.

44
Figure 16: Sub-Explosion of Tesseract in Fig. 14

Figure 17: Sub-Explosion of Text-to-Speech in Fig. 14

45
A..2 Block Diagram of Tess2Speech Trainer Desktop Application

Tess2Speech Trainer is a user-friendy desktop application that allows users to train


or re-train Tess2Speech to recognize the desired font or handwriting. It automates
all of the required steps in training Tesseract except for the box file editing. Its
Block diagram is shown in figure 18. Tess2Speech Trainer needs an input image
(see figure 12 for sample training image) which is in TIFF format. After the
user inputted the image, the application will automatically produce a box file. A
Box Editor, which is a modified jTessBoxEditor [32], will then pop-up to allow
users to edit their box files. After editing the box files, the training will proceed
automatically. The application will produce a .traineddata which can be used by
Tess2Speech mobile application.
Since it needs to be user-friendly, Tesseract’s training is abstracted from the
user but its sub-explosion block diagram is shown in figure 19.

Figure 18: Block Diagram of Tesseract Trainer

46
A..3 Block Diagram of Tesseract’s Training

All of these components are discussed in Chapter 3 D..3.

Figure 19: Block Diagram of Tesseract’s Training[18]

A..4 Flowchart of Tess2Speech Mobile Application

Input file refers to the image/PDF/Ebook that contains the texts the user wants
to convert into an editable text and speech. Input files can be PNG, JPEG, BMP,
GIF, PDF, and EPUB for Ebooks.
Tess2Speech gives the users choices on what input they want to process. The
users can choose to browse their phone for an existing input file, use their camera
to capture an input image, or use the canvas to write on the screen.
After the input has been created or selected, the users can manually rotate or
crop the input image before passing it to other preprocessing techniques, specifi-
cally Grayscaling, Adjusting brightness and contrast, and Otsu’s Binarization.
After performing series of image preprocessing, the processed input will be fed
to Tesseract OCR and convert it to text that is displayed in an editable textbox.

47
The users can edit, modify, and save the generated editable text into .txt or .pdf.
Users are also notified words that are not in the dictionary by using Android’s
built-in spell-checker.
The generated editable texts can now be converted into speech by pressing
play button. The user can replay the speech by pressing the play button again.
The user also has a choice to save the converted speech in to an audio file with
.wav format. The flow chart of this application is shown in Figure 20.

48
Figure 20: Flowchart of Tess2Speech Mobile Application

49
A..5 Flowchart of Tess2Speech Trainer

The user browses any number of TIFF files, and then specify the name of the
output trained data. If the name of the trained data already exists, the old
training images that is used to train that trained data can be re-used. The user
can specify whether to overwrite the old box files of the old images or retain
it to avoid re-editing the same box file for the old images. jTessBoxEditor [32]
will pop-up and allows the user edit the box files of the images. After the user
has finished editing the box files, Tess2Speech trainer will automatically train
Tesseract and will automatically output a .traineddata file with the name that
the user specified. This .traineddata file can now be used in Tess2Speech mobile
application by copying the .traineddata to the Tessdata folder of Tess2Speech (see
section B..5 to find Tess2Speech tessdata folder). The flow chart of Tess2Speech
trainer can be seen in figure 21.

50
Figure 21: Flowchart of Tess2Speech Trainer

51
A..6 Use-Case Diagram

Tess2Speech features two types of users: The general users and the application
developers. The general users are the application users that uses the main func-
tionalities of Tess2Speech, while the application developers are those that perform
training on Tesseract and updates on the application.
Tess2Speech can use any language packs that the application developers cre-
ated. Language packs are trained data that were created by application develop-
ers. Example of a language pack is for handwritten English texts which I created
(engh.traineddata). Since Tesseract is still trainable even after the deployment
of this application, application developers can still create handwritten language
packs for Chinese, Korean, Arabic etc. language packs in the future and add those
to Tess2Speech.
It is also important to note that since Tess2Speech can use any .traineddata
files on the internet, users can download them and copy it to Tess2Speech’ tessdata
folder. This will make Tess2Speech recognize that language (can be anything that
is currently existing i.e. Computer typed texts for Chinese, Korean, Arabic, etc.).
These added language packs can be implemented through future updates or
by manually downloading the file from a host server.
The use-case diagram of Tess2Speech is can be seen on Figure 22.

52
Figure 22: Use-Case diagram of Tess2Speech

53
B. System Architecture

B..1 Android OS

Android is a mobile operating system (OS) which was developed and currently
being developed by Google [6]. Its operating system is based on the Linux kernel
and is primarily designed for smart phones and tablets. Android applications are
developed using Java Programming Language (see B..2) and Android Software
Development Kit (SDK). Android OS will be used as the platform for this ap-
plication because aside from the fact that Tesseract is now being developed by
google [5]; Tesseract can now be used as a library for Android by using Tess-Two
(see B..4).

B..2 Java Programming Language

Java Programming Language is a general-purpose, concurrent, class-based, object-


oriented language. Its syntax is somewhat related to C and C++ but is organized
differently. Java language is strongly typed which means that it has a strict set
of rules when it comes to programming syntax. Java programming language also
distinguishes run-time errors and compile-time errors. It is also a relatively high-
level programming language since it includes automatic storage management and
garbage collectors which automatically performs deallocation unlike in C and C++
which uses explicit deallocation [34]. Java needs Java Virtual Machine (JVM)
installed on the computer to work. Java Programming Language is also used in
Android application development alongside other Android SDKs. Java version
1.8.0 66 is used in the development of both Tess2Speech mobile application and
Tess2Speech Trainer desktop application.

B..3 Android Studio

Android Studio is the official Integrated Development Environment (IDE) for An-
droid Application Development. Android Studio version 1.5.1 is used in the de-
velopment of Tess2Speech mobile application.

54
B..4 Tess-Two

Since Tesseract OCR is compiled using C++, Tess-Two is a free open-source


Android library project that provides a Java API for accessing natively-compiled
Tesseract and Leptonica APIs [35].

B..5 Tess2Speech’ Tessdata folder

Data files (.traineddata) for Tesseract OCR should be placed in Tesseract’s ’tess-
data’ folder in order for it to detect the trained data. It is the same for Tess2Speech.
In order for a trained data be used in Tess2Speech, it should be located in
Tess2Speech’ ’tessdata’ folder. It is usually located on
’Phone Storage/Android/Data/anteraaron.tess2speech/files’ directory.

B..6 Text-to-Speech System

Any Text-to-Speech system installed can be used on Tess2Speech. This means


that the performance of Tess2Speech’ TTS is based on the TTS being used on the
phone. Text-to-Speech systems can be downloaded on Google Play Store. TTS
settings can be changed on Android’s phone settings.

B..7 Tess2Speech’ Canvas

As we stated on Background of the Study, stylus-based applications are mostly


proprietary and expensive. As a solution to that, I developed a pseudo stylus-
based application. In the canvas part of Tess2Speech, I created a Canvas object
on the phone’s screen, which is similar to how MS Paint works, and then convert
the content of that canvas to image every time I want to convert that handwriting
to text or speech. The performance of this canvas is dependent on the hardware
of the phone (touchscreen capability).

55
B..8 Tess2Speech’ Image Viewer

The reason why Tess2Speech is only accepting input images of format PNG, JPEG,
GIF, and BMP is because Android’s ImageView Object accepts these same image
formats. In order to support pinch-zoom, double-tap zoom, and pan functionalities
in the ImageView, I used an open-source Android View class called GestureIm-
ageView by jasonpolites [36].

B..9 Tess2Speech’ Camera

Almost all smart phones have a camera, and it is accessible by all of the appli-
cations installed on the phone. The problem is that not all camera resolutions
are equal. It varies from phone-to-phone. Since Tess2Speech relies mostly on the
quality of images, an image taken from a high-resolution camera will most likely
yield a better accuracy.

B..10 Image Cropping and Rotation

It is stated in Scope and Limitations no.7 that the border of the paper should not
be seen as it adds noise to the image and may be interpreted as a character such
as ’l’ (small L) or ’1’ (one). As a solution, I implemented a choice for the user
to crop the image and only select which part of the image is relevant. I used an
open-source image cropper library by ArthurHub [37], and edited it a bit to fit
my personal preferences.
Since Image De-Skewing is hard to implement without the use of large libraries,
I also provided an alternative solution by allowing the user to manually rotate the
image allowing them to correctly align the texts on the image.

B..11 Tess2Speech’ PDF Viewer

Android supports viewing of PDF starting from API level 21. Since the minimum
API level of Tess2Speech will be API level 16, I used an open-source PDF Viewer to
support lower API levels. Android-pdfview is a library created by Joan Zapata [38]

56
which provides fast PDFView component for Android, with animations, gestures,
and Zoom. It is based on VuDroid [39], which is a PDF decoder made by google.

B..12 PDF to Image and Vice-Versa

It is stated in B..11 that the PDF Viewer uses VuDroid [39]. Since VuDroid is a
PDF Decoder, it should have a functionality of converting a PDF to an Image.
After studying the source code of VuDroid, I found a method on how to convert
PDF to Image and vice-versa. To maximize the use of the library, I will incorporate
these functionalities in Tess2Speech.

B..13 Tess2Speech’ Ebook Viewer

Ebooks with .epub extensions are essentialy a zip of html files. Since Android does
not have an innate capability to display Ebook, I used an open-source library called
EPubLib by Paul Siegman [40]. EPubLib is a Java Library for reading, writing,
and manipulating epub files. The problem is that the formatting of epub is not
acquired when using EPubLib. By creating a workaround, I eventually displayed
the proper formatting of the Ebook.

B..14 Tess2Speech’s Built-in File Picker

I also incorporated a built-in File Picker for Tess2Speech in-case that the user does
not have a compatible File Picker installed on their phone. The file picker I used
is an open-source file picker library by Anders Kaloer [41].

B..15 Saving Files

Converted texts can be saved as a text file (.txt), or a PDF file (.pdf) by using
VuDroid [39]. An SD Card is required in order to save Tess2Speech files. If an
SD Card is not present, Tess2Speech will prompt the user and automatically close
the application.

57
B..16 Settings

The Preference Screen of Tess2Speech contains different settings for Tess2Speech


such as the option to whether turn-on Image Preprocessing, Automatic Image
Resizing (for faster conversion), Tesseract language, help, and Licenses.

B..17 Tess2Speech Trainer

Tess2Speech Trainer is a user-friendly desktop application which allows the users


to personalize and train Tess2Speech to recognize a new font or handwriting in just
a click of a button. It produces a .traineddata file that can be used by Tess2Speech.
The Box Editor of Tess2Speech trainer is an edited jTessBoxEditor by Vi-
etOCR [32]. I added an indicator on which box files have already been visited
to help users know if they missed editing some characters. I removed other func-
tionalities of jTessBoxEditor that are not needed and integrated it to Tess2Speech
Trainer’s Graphical User Interface.
Tess2Speech Trainer is programmed using Java and is a .jar executable. Tess2Speech
Trainer is also a stand-alone application, which means that there is no installation
required for the application itself. The user just needs a Java installed to run
the .jar executable inside the Tess2Speech Trainer. It is important to know that
’Tess2Speech Trainer.jar’ file cannot be moved outside the folder or it will not run.
Only ’create shortcut’ method is allowed.

58
C. Technical Architecture

C..1 Development Environment

These applications were created in these following environments:

1. Windows 7 Ultimate SP1

R CoreTM i3 CPU
(a) Intel

(b) RAM: 4 GB (2.80GB usable)

(c) 32-bit Operating System

2. Android Studio 1.5.1 for the Mobile Application

3. Eclipse IDE 4.5 (Mars) for the Desktop Applicaiton

4. Java version 1.8.0 60

(a) JavaTM SE Runtime Environment (build 1.8.0 66-b18)

(b) Java HotSpotTM Client VM (build 25.66-b18, mixed mode)

5. Trained using Tesseract OCR [5].

(a) Tesseract version 3.05.00dev

(b) Leptonica version 1.73

(c) jTessBoxEditor version 1.5 [32]

6. Tested using:

(a) Lenovo S820 (Android 4.4.2/Kitkat/API level 19)

(b) Genymotion Android Emulator (Google Nexus 5X/Android 6.0.0/Marsh-


mallow/API level 23)

(c) Android Studio Emulater (Google Nexus 5X/Android 6.0.0/Marshmal-


low/API level 23)

59
C..2 Minimum System Requirements

The minimum system requirements for Tess2Speech mobile application:

1. Android 4.1/Jelly Bean/API level 16

2. 120 MB free space (50+ MB for application itself and 50+ MB for built-in
trained data and other files)

3. Wi-Fi 802.11 connectivity (optional for updates)

4. 2MP primary camera

5. Mounted 1GB SD card

6. 100 MB free RAM

7. An existing .traineddata in tessdata folder

8. A Text-to-Speech Engine is installed

The minimum requirements Tess2Speech Trainer desktop application are:

1. Windows 7

R CoreTM i3 CPU
(a) Intel

(b) RAM: 2GB

(c) 32-bit Operating System (can also be run on 64-bit)

2. Java version 1.7

3. 110MB free space (excluding the size of generated trained data)

Tesseract and jTessBoxEditor does not need to be installed because it is already


included in Tess2Speech trainer.

60
D. Training Methodology

In training Tesseract, there are no required format or template for the training
datasets, although the performance of the resulting trained data will be dependent
on the training datasets that you used in training.
In creating a trained data for handwritten texts, I considered using Basu and
Rakshit’s training method which they used in training Tesseract for handwritten
lower case Roman script [3]. They used an n-user model where n is the number of
persons they collected handwriting from. The training dataset templates for each
user/individual is divided into two, namely isolated characters and free-flow text.
See figure 40 for sample training dataset.
Isolated Characters are datasets that contains one repeated character per line,
both the upper case and lower case of the character. The characters should not be
very close to each other. Figure 40a and 40b are samples of Isolated Characters
dataset.
Free-flow texts are datasets that contain a paragraph/s that has all of the
desired characters you want to recognize. This is important because sometimes a
person’s handwriting in free-flow text is different from their handwriting in isolated
characters. This is also to simulate the realistic frequency of each characters.
Figure 40c and 23d is a sample of free-flow texts dataset.
Using these training datasets, training is then done either manually or by using
Tess2Speech Trainer which automates the training process of Tesseract.
The test set for the trained data is also a free-flow text which is also written
by at least on of the n individuals in the n-user model.
In Basu and Rakshit’s experiment [3], they only used a three-user model but
still managed to get at least 78% accuracy. By increasing the number of user and
training sets, the accuracy can further increase.

61
Figure 23: Training Images Sample
(a) Page 1 (Isolated Characters) (b) Page 2 (Isolated Characters)

(c) Page 3 (Free-flow texts) (d) Page 4 (Free-flow texts)

62
V. Results

A. Tess2Speech Mobile Application

A..1 Splash Screen

Figure 24: Splash Screen of Tess2Speech

The splash screen shown in figure 24 is shown to the user while Tess2Speech
is loading required resources.

A..2 Home Screen/Canvas

Figure 25: Home Screen/Canvas of Tess2Speech

The home screen of Tess2Speech is shown in figure 25. It is also the canvas
functionality of Tess2Speech. The user can write anything on the Canvas and

63
convert it to text or speech. If the ’Clear’ button in the upper-left corner of
the screen is pressed, it will clear the whole canvas into a white blank page. The
button next to it, which is ’Erase’ replaces the touch functionality of the user from
writing to erasing. The button on the lower left corner of the screen is the ’Play’
button which converts the words written on the screen into speech (see figure 30).
The button on the lower right corner of the screen is the ’Convert Text’ button
which converts the words written on the screen into an editable text (see figure
29).

A..3 Camera

Figure 26: Camera Functionality of Tess2Speech


(a) Camera Button in Tool- (b) After Camera Button is
bar Pressed

The camera button is the first button in Tess2Speech’ toolbar (figure 26a). It
allows the user to use the phone’s camera to take pictures of the desired input
image that will be displayed on the screen (see figure 28a). The camera interface
(figure 27b) is based according to your phone’s camera interface.

64
A..4 Browsing Image

Figure 27: Browse Image Functionality of Tess2Speech


(a) Browse Image Button in
Toolbar (b) File Chooser Dialog

(c) Selecting File

’Browse Image’ button is the button next to ’Camera’ (figure 27a). After
pressing ’Browse Image’ button, a Chooser Dialog (figure 27b) will pop-up and
gives the user choices of available applications installed on the phone that can
open images. Figure 27b is the result of picking Gallery as a file picker. The user
can now pick their desired input image and will be displayed on the phone’s screen
(see figure 28a).

65
A..5 Displaying, Rotating, and Cropping Images

Figure 28: Displaying an image


(a) Image being displayed (b) Image Rotation

(c) Image Cropping

After browsing an image or taking a picture of an image, it will be displayed


on the screen just like in figure 28a. New buttons in the upper-right part of
the screen will be available if an image is being displayed. These are the ’Crop’
and ’Rotate’ Buttons. ’Rotate’ button allows the user to rotate an image in any
angle by adjusting the seek bar below the image (figure 28b). This serves as an
alternative for de-skewing an image. The ’Crop’ button allows the user to crop

66
the unnecessary part of the image that Tess2Speech may read (figure 28c). The
image displayed can now be converted to text or to speech (see figure 29).

A..6 Converting to Text

Figure 29: Converting to Text


(a) Loading Screen while (b) Converted text of the
Converting Text image in 28a

The button in the lower-right corner of the screen is the ’Convert Text’ button
which converts the displayed image, text, canvas, pdf, or epub to text. After
pressing the ’Convert Text’ button, a loading screen (figure 29a) will appear while
converting the displayed image to text. The converted text (displayed on figure
29b) is editable and can be copied. If you press the lower-right button again, it
will bring you back to the displayed image. That’s why after pressing ’Convert
Text’ button, its label change to ’Back to Input’. If the ’Append Text’ switch in
figure 29b is enabled, the current text displayed will not be erased and the next
converted texts will be appended to it as long as it is enabled.

67
A..7 Converting to Speech

Figure 30: Converting the image in 28a to Speech

The button in the lower-left corner of the screen is the ’Convert to Speech’
button which converts the displayed image (editable text, pdf, or epub depending
on which is being displayed) into speech. If you will notice, the button in the
lower-left corner in figure 30 became ’Stop’ after pressing the ’Play’ button. This
is to allow the users to stop Tess2Speech from speaking. Note that converting an
image to text will also produce a loading screen just like in figure 29a.

68
A..8 Browse an Input PDF

The button after the browse image in the tool bar is the overflow menu which
contains other functionalities of Tess2Speech (31a). The first item in the overflow
menu is the ’Browse input PDF...’ which allows the user to use PDF as their input
image. After pressing that option, a File Chooser Dialog will pop-up (figure 31b)
which gives the user choices on which installed application to use in browsing PDF.
In figure 31c, WPS office is used in browsing PDF. After browsing for the desired
PDF, it will be displayed on the screen just like in figure 31d. When converting
a PDF to text or speech, a pop-up dialog will appear (figure 31e) which gives the
user choice on what pages of the PDF Tess2Speech convert.

69
Figure 31: Browsing a PDF
(a) Overflow Menu (b) File Chooser Dialog

(c) Browsing PDF using


WPS Office (d) PDF Being Displayed

(e) Converting PDF to


Text

70
A..9 Browse an Input Epub

Figure 32: Displaying Epub


(a) Table of Contents (b) Epub content

Browsing an epub is the same as browsing a PDF. First step is selecting ’Browse
an input Epub...’ from figure 31a. A pop-up menu will also open just like in figure
31b. Applications that can open epub will be displayed instead of displaying
applications that can open PDF. After browsing for the desired epub, a table of
contents for the selected epub will be displayed (figure 32a). Here, the user can
choose which part or chapter of the epub they like to view. It will be displayed
just like in figure 32b. The user can go back to the table of contents by pressing
the upper-left button ’Table of Contents’. The user has a choice to convert the
displayed chapter to text or speech by pressing the corresponding button.

71
A..10 Saving

Figure 33: Saving Files to .txt, .pdf, or .wav


(a) Saving as .txt (b) Saving as .pdf

(c) Saving as .wav

72
Saving can be done by selecting the save options in the overflow menu (figure
31a). The figures 33a, 33b, and 33c shows the pop-up dialog that asks for a file
name for saving the .txt, .pdf, or .wav respectively.

A..11 Converting Image to PDF and Vice-versa

Figure 34: Converting Image to PDF and Vice-versa


(a) Converting Image to (b) Converting PDF to Im-
PDf age

Conversion can be done by selecting the ’Convert Image to searchable PDF’ or


’Convert PDF to Image’ in the overflow menu in figure 31a. Figure 34a shows the
pop-up dialog when the user chooses to convert an image to PDF. It asks for a file
name for the resulting PDF. Figure 34b shows the pop-up dialog when the user
chooses to convert a PDF to image. It asks for a folder name that the extracted
images will be saved since one page from a PDF file corresponds to one image. If
there are 50 pages in a PDF, 50 images will be produced. The user will also be
prompted on what pages will be saved just like in figure 31e.

73
A..12 Settings

When ’Settings’ is selected from the overflow menu in 31a, the preference screen
in figure 35a will be shown. This preference screen contains different settings for
Tess2Speech.
The first item is ’Image Pre-processing’ which gives the user an option to
turn-on Grayscaling and illumination fixing of images before converting to text or
speech.
The next item is ’Re-scale image’ which reduces the size of the image to convert
to speed-up conversion time. It is not recommended for images with small texts
sizes since Tess2Speech might not be able to recognize very small texts.
The next item is ’Tesseract Trained Data’ which allows the user to select which
trained data Tess2Speech will use. All trained data files in the ’tessdata’ directory
will be shown here (figure 35b The user can choose more than one trained data.
The next item is ’TTS Settings’ in which the user will be redirected to TTS
settings of the phone (figure 35c).
The next item is ’Spell-Checker Settings’ in which the user will be redirected
to ’Language and Input’ settings of their phone (figure 35d). Here they can change
the Spell-Checker settings of their phone.
The last two items are Help and Licenses. Help displays different tips and
helps the user become familiar with the application (figure 35e). Licenses shows
different licenses and credits for the Open-Source libraries used in Tess2Speech
(figure 35f).

74
Figure 35: Settings
(a) Preference Screen (b) Selecting Trained Data

(c) TTS Settings (d) Spell-Checker Settings

(e) View Help (f) View Licenses

75
B. Tess2Speech Trainer

Since Tess2Speech Trainer needs to be user-friendly, its UI is very straight forward


and contains minimal functionality.

B..1 Graphical User Interface

Figure 36: GUI of Tess2Speech Trainer

The GUI of Tess2Speech Trainer can be seen in figure 36. The ’Browse TIFF/s’
button opens a File Chooser (see 37) that allows the user to browse for existing
TIFF files in the computer which will be your training set. The user can either
type the absolute path of the TIFF file (separated by ; if there are multiple TIFF
files) or just use the Browse button. The user can choose as many TIFF files as
they want.

76
The ’Trained Data Name’ field will contain the name of the output Trained
Data. If the user specifies an existing trained data, the old training files that were
used in developing that trained data will be re-used.
The ’Box Maker’ field is the trained data that Tess2Speech trainer will use in
making the initial boxes of the input TIFF files. Choosing a trained data that is
familiar with your input training images will minimize the errors in the initial box
files and minimize the number editing in box files later.

B..2 File Picker Dialog

Figure 37: File Picker Dialog of Tess2Speech Trainer

Figure 37 shows the File Picker dialog when ’Browse TIFF/s’ is clicked. Mul-
tiple TIFF files can be selected at once.

77
B..3 Box Editor

Figure 38: Box Editor (edited jTessBoxEditor [32])

After clicking the ’Start Training’ button in figure 36, Tess2Speech will gener-
ate the initial box file using the trained data you selected in the ’Box Maker’ field.
After creating the box files automatically, a box editor will pop-up which allows
the user to edit and correct the bounding boxes in the box file. It is an edited
jTessBoxEditor by VietOCR [32].

B..4 Automatic Training

Figure 39: Automated Training

After the user finished editing the box files using the editor (figure 39), a

78
command prompt will automatically pop-up and will perform the training auto-
matically. The user will only need to wait until the command prompt closes and
finishes training. After finishing the training, Tess2Speech Trainer will ask the
user whether to open the tessdata folder since the output file will be located in
Tess2Speech Trainer’s tessdata folder.

79
VI. Discussions

A. Tesseract Training

A..1 Training Results

Using the training methodology discussed in Chapter 4 D., I used a 6-user model
training dataset for developing my experimental trained data. These training
dataset’s character distribution is shown in the table 4. White spaces and new
lines are not included in counting the number of characters.

Table 4: Character Distribution of Training Dataset

After training Tesseract using these training datasets, I tested the performance
of the resulting experimental trained data using the test datasets in figure 40.
These test datasets are from the handwriting of user 1, 2, and 3.

80
Figure 40: Test Data
(a) Test Data 1 (b) Test Data 2

(c) Test Data 3

81
The summary of the test results of the experimental trained data is shown in
table 6. I compared the experimental trained data that I created to the default
trained data of Tesseract (table 5 shows summary of the default Tesseract).
Ct − Ce
CharacterAccuracy = ∗ 100
Ct
Where Ct = the total number of characters and Ce = the number of misclas-
sified character.
Cw − Ce
W ordAccuracy = ∗ 100
Cw
Where Cw = the total number of words and Ce = the number of misclassified
words.

Table 5: Summary of the results of the default Tesseract trained data.

Table 6: Summary of the results of the experimental trained data that I created.

As you can see in tables 5 and 6, there is a huge improvement on the accuracy
in recognizing handwritten texts in figure 40 after training. The following are the
information that we gathered after training:

1. In Test Data 1, there is a 45.5% improvement in the character recognition


accuracy and a 69.9% improvement on word recognition accuracy.

2. In Test Data 2, there is a 37.22% improvement in the character recognition


accuracy and a 67.03% improvement on word recognition accuracy.

82
3. In Test Data 3, there is a 45.68% improvement in the character recognition
accuracy and a 54.97% improvement on word recognition accuracy.

4. The average character and word accuracy of the default Tesseract trained
data are 54.45% and 33.61% respectively. On the other hand, the average
character and word accuracy of the experimental trained data are 99.18%
and 97.58% respectively. These show an average increase on the the char-
acter and word accuracy by 44.73% and 63.97% respectively.

A..2 Problems Encountered in Training

1. If the training image is noisy i.e. taken from the phone’s camera, Tesseract
can’t recognize some of the characters in the training image. This leads to
’APPLY BOXES FAIL!’ error on Tesseract during training. The solution is
to use a scanner and save the image file as a 300dpi black and white image
in TIFF format for the most optimal training image format.

2. If you are training manually, Tesseract’s accuracy may drop if you include
symbols and numbers to the training dataset. The solution to this is to create
the optional files punc-dawg and number-dawg to give Tesseract a guideline
on when to use numbers or symbols in a word. It also helps Tesseract to
avoid confusing symbols from letters such as ’t’ form ’+’, etc. It is discussed
in chapter 3 D..3.

3. Tesseract frequently mis-classify these characters:

(a) ’i’ is recognized as ’l.’ or ’l”

(b) ’l l’ is recognized as ’H’

(c) ’t’ is recognized as ’+’

(d) ’l’ is recognized as ’/’, ’\’ or ’,’

(e) ’O’ is recognized as ’0’

(f) ’e’ is recognized as ’6’

83
(g) Characters that have similar capital and small letters such as handwrit-
ten ’A’, ’C’, ’J’, ’K’, ’M’, ’N’, ’O’, ’P’, ’S’, ’U’, ’V’, ’W’, ’X’, ’Y’, and
’Z’.
The workaround for this is to use the set unicharset properties.exe
and create wordlist-dawg, bigram-dawg, and freq-dawg when you are
training manually. Another workaround is to increase the frequencies
of these frequent mis-classified characters in the training images.

4. Although the average character and word accuracy that I got is 99.18% and
97.58% respectively, there is still no conclusion that the trained data really
achieved those accuracy FOR ALL handwritings since the handwritings used
for the training images are only 6. The solution for this is to create an auto-
mated Tesseract trainer in which the users can easily train and personalize
Tesseract for their own handwritings. With this, anyone can train Tesseract
and if proper training is done for the user’s handwriting, this will fulfill the
objective to reach at least 80% accuracy for all handwritings.

B. Developing Tess2Speech Trainer

B..1 Tess2Speech Trainer Results

As stated before, in order for Tess2Speech to become useful for everyone, it still
needs to have the training capability of Tesseract even after the application has
been deployed. It’s because there is still no guarantee that the trained data that
I created will also be usable to other users. Because of this, I developed an
automatic Tesseract trainer which is user-friendly and can be used by any user
having minimal knowledge about computers. This allows the users to personalize
their Tess2Speech and allows it to learn their handwritings if the trained data I
created does not produce satisfactory results for their handwritings. This solves
the problem of generalizing the handwritings and fulfills my objective to create a
user-friendly application that automates Tesseract’s training.

84
The training results using this application will be the same as the manual
training method. The only disadvantage of using this application is that the user
can only edit the box files. I provided the default values for the dawg files, config
file, and other optional files since it will be too complicated for the user to do.
The default values is based on my initial experimental trained data that yield the
best results.

B..2 Problems Encountered in Developing Tess2Speech Trainer

1. Tesseract cannot run the training tools on the phone. As a workaround,


I made Tess2Speech Trainer as a desktop application that is bundled with
Tess2Speech mobile application.

2. There are box editors that are already existing. The problem is that I need
to integrate it to my Tess2Speech Trainer application. In order to do this,
I used an open-source box editor by vietOCR which is the jTessBoxEditor
[32]. Since it is open-source, I managed to edit its source code and integrate
it into my application.

C. Tess2Speech Mobile Application

C..1 Tess2Speech Results

Since Tess2Speech uses Tesseract as its OCR Engine, I can use the .trained-
data files that are produced from Tesseract’s training in desktop computers using
Tess2Speech Trainer. Because of this, I managed to create an Android Applica-
tion that fulfills the objectives I specified. The user can upload an image that
contains the handwriting (can also be computer printed texts) or write the hand-
written text itself on the mobile’s screen through a canvas, and convert it to text
or speech. The user can also personalize Tess2Speech by training their own hand-
writing using Tess2Speech Trainer and used the output .traineddata files to their
application.

85
The user can also download other .traineddata files from Tesseract’s home
page, through updates, or by downloading from a host site.
The user can also save the converted text into a .txt or .pdf file. The user
can also save the converted speech into a .wav file. Since there are a lot of other
functionalities that can be done, I tried maximizing the capability of Tess2Speech
by adding more functionalities such as PDF-to-Image and vice-versa, Ebook-to-
Speech, and PDF-to-Speech.

C..2 Problems Encountered in Tess2Speech Application

1. Tesseract-OCR [5] is programmed in C++ which means it is not compatible


with the programming language that I will use which is Java. As a solution, I
used tess-two [35] which contains tools for compiling Tesseract and Leptonica
for use on the Android Platform. It provides a Java API for accessing
natively-compiled Tesseract and Leptonica APIs.

2. Text-to-Speech systems on Android only supports up to 4000 Characters at


a time. As a solution, if a paragraph is more than 4000 characters long,
I chopped the paragraph into strings of 4000 length and saved it into an
ArrayList. I then used this ArrayList as input since Text-to-Speech system
supports an ArrayList of strings as input. As a consequence, when saving a
paragraph with greater than 4000 characters into a .wav file, the number of
.wav files that will be created will be the same as the number of elements in
the ArrayList.

3. Tesseract does not support PDF as an input and Android cannot display
PDF files for API below 21. As a solution, I used PDFViewer library by
Joan Zapata [38] in order to view PDFs for APIs below 21. I also examined
the library and found a workaround for using PDF as a Tesseract input. The
workaround is that I converted PDF to images first by using VuDroid [39],
which is included in the PDFViewer library, before feeding it to Tesseract.

4. Since Android stylus functionalities like those in Galaxy Notes are propri-

86
etary, I need to create my own canvas for supporting handwritings that are
written in the mobile’s screen. As a workaround, I managed to create a can-
vas by imitating how MS Paint works, although writing is not that smooth
and versatile unlike in Galaxy Note. The performance of the canvas is also
dependent on the hardware (screen capability).

5. Tess2Speech is very hardware dependent. The quality of the image depends


on the phone’s camera (unless it was scanned and then sent to phone). Since
images taken from the low quality camera is usually noisy, it is very hard
to get an image that Tess2Speech can read. As a solution, I implemented
the capability on Tess2Spech to perform image pre-processing to an image
before converting the image to text or speech.

Figure 41: Image Pre-processing


(a) Raw Image

(b) Image processed only by Tesseract’s Otsu Binarization

(c) Image processed by GrayScaling, Brightness and Contrast ad-


justment, and Tesseract’s Otsu Binarization

87
6. If the image is too large, processing time can take a very long time. Large
images with large texts can also confuse Tesseract since it will treat the
letters as a background and it will try look for texts inside the letters. As
a solution, I implemented the capability to rescale the image into a smaller
dimension before converting the image to text or speech.

7. Since De-skewing is hard to implement, I implemented an alternative which


allows the users to manually rotate an image. I also implemented the crop
functionality to allow the users to remove unnecessary parts of the image
that can produce garbage texts.

8. The trained data for handwritten texts yields low accuracy when used to
recognize computer typed texts. As a solution, since Tesseract can use mul-
tiple trained data at the same time, the user can choose any combination
of .traineddata files including ’eng.traineddata’ in the Tesseract Language
settings of Tess2Speech.

88
D. Significance of Tess2Speech

Since Tess2Speech is free and open-source, it provides users with a free, portable,
non-proprietary, and trainable Intelligent Character Recognition Engine. This
also means that Tess2Speech can still improve over time by re-training over and
over again.
Tess2Speech can also read images of computer-typed texts aside from the abil-
ity to read handwritten texts which makes it both and OCR and ICR engine.
Since the users can write on the mobile phone’s screen, it can help people with
speech impairments and help them communicate. Tess2Speech is cheap, easy
to use, and inexpensive unlike other speech synthesizers and handwritten-to-text
applications. It can also help pre-school students to know the proper pronunciation
of words that they write on the mobile phone’s screen. Tess2Speech can also help
users to proof-read their written works by listening to the voice equivalent of their
written works.
Tess2Speech also has many functionalities like saving the converted text or
speech into a .txt, .pdf, or .wav file, Ebook-to-Speech (Audio book), Converting
Image-to-PDF and vice-versa, and PDF-to-Speech functionalities.

89
VII. Conclusions

Tess2Speech is an Intelligent Character Recognition Android application which can


recognize both computer-typed and non-cursive handwritten texts and convert it
to either text or speech. With the help of Tess2Speech Trainer, which is a desktop
application, Tess2Speech is re-trainable and can be personalized by the users with
minimal effort.
Tess2Speech is developed to provide the speech impaired a way to commu-
nicate, and also to provide researchers a free, open-source, non-proprietary ICR
which is trainable.
This application also proves that Tesseract is indeed trainable for handwritten
texts. Although, it is only limited to non-cursive handwritten texts since Tesseract
relies on segmentation of characters. Because of this, it can be said that it is almost
impossible to recognize cursive texts using Tesseract.
The development of this application also helped to determine the limitations
and capabilities of Tesseract, and what training methods and configurations are
effective for achieving high accuracy with Tesseract.
This application is currently at its Beta stage. Once it gains popularity, differ-
ent users and researchers may collaborate to improve the trained data for hand-
writing until such time that they create a generalized trained data for most, if not
all, handwritten texts.

90
VIII. Recommendations

It is suggested that in order to further improve the accuracy of Tess2Speech’


handwriting recognition, a higher number of sample handwritings (n-users) should
be used. A higher number of characters and words are also suggested when creating
training datasets.
Improving the canvas functionality of Tess2Speech that can rival Galaxy Note’s
can greatly improve the accuracy of Tess2Speech when recognizing handwritten
texts on the phone’s screen.
One of the main reason why the accuracy of Tesseract drops is because of
image noises. Using open-source libraries for image pre-processing or developing
an algorithm that can greatly reduce image noises can drastically improve Tesser-
act’s accuracy. Such algorithms are adaptive thresholding and applying different
binarization techniques.
Another improvement would be finding a way to train Tesseract in a smart
phone so that Tess2Speech Trainer will not be needed. It can open a possibilty
for Tesseract to learn handwritings dynamically without user intervention.
Adding functionality like language translator can also add usability to Tess2Speech.
Lastly, if there is an open-source OCR Engine which is better than Tesseract, you
can completely replace the OCR engine of this application.

91
IX. Bibliography

[1] P. Christensson, “Character Encoding Definition.” http://techterms.com,


September 2010.

[2] K. Kumar.K, M. V. S. Muvvala, P. S. D. Sruthi, and P. Dinesh, “Intelligent


Character Recognition (ICR): A Novel Algorithm to Extract Text from a
Scanned Form Based Image,” International Journal of Advanced Trends in
Computer Science and Engineering, vol. 2, no. 6, pp. 47–55, 2013.

[3] S. Rakshit and S. Basu, “Development of a Multi-User Handwriting Recog-


nition System Using Tesseract Open Source OCR Engine,” PROC. Interna-
tional Conference on C3IT, pp. 240–247, 2009.

[4] S. Ch, S. Mahna, and N. Kashyap, “Optical Character Recognition on


Handheld Devices,” International Journal of Computer Applications IJCA,
vol. 115, no. 22, pp. 10–13, 2015.

[5] Google, “Tesseract-OCR.” https://code.google.com/p/tesseract-ocr/,


2006 - 2016.

[6] Google, “Android OS.” http://www.android.com/ or http://developer.


android.com/, 2008.

[7] American Speech-Language-Hearing Association, “Aphasia.” http://www.


asha.org/public/speech/disorders/Aphasia/.

[8] Stroke Association, “Communication Aids and Computer-Based Therapy af-


ter Stroke.” http://www.stroke.org.uk/, 2013.

[9] Free Press Journal, “2.5 bn smartphone users globally by 2015,” The Free
Press Journal, July 2014.

[10] Stefan, “Samsung just bought 5stylus!,” Android Authority, January 2013.

92
[11] S. Vijiyarani and A. Sakila, “Performance Comparison of OCR Tools,” In-
ternational Journal of UbiComp (IJU), vol. 6, pp. 19 – 30, July 2015.

[12] B. Verma, M. Blumenstein, and S. Kulkarni, “Recent Achievements in Off-


line Handwriting Recognition Systems,”

[13] A2iA, “A2iA document reader ICR for handwritten text.”


http://www.a2ia.com/sites/default/files/product_files/a2ia_
documentreader_datasheet_en.pdf/, 2015.

[14] Y. Williams, “What is Speech impairment? - Defenitions, Causes and Charac-


teristics.” http://www.a2ia.com/sites/default/files/product_files/
a2ia_documentreader_datasheet_en.pdf/.

[15] iSpeak4U, “Handyspeech.” https://itunes.apple.com/us/app/


handyspeech/id563600464?mt=8, 2014.

[16] A. Christie, “Multiple Benefits of Text to


Speech Applications.” http://www.lc2.ca/item/
85-multiple-benefits-of-text-to-speech-applications, Novem-
ber 2012.

[17] A. Aparna and I. Muthumani, “Optical Character Recognition for Handwrit-


ten Cursive English characters,” International Journal of Computer Science
and Information Technologies (IJCSIT), vol. 5, no. 1, pp. 847 – 848, 2014.

[18] R. Smith, “An Overview of the Tesseract OCR Engine.” http:


//static.googleusercontent.com/media/research.google.com/en/
/pubs/archive/33418.pdf.

[19] S. Singh, “Optical Character Recognition Techniques: A Survey,” Journal of


Emerging Trends in Computing and Information Sciences, vol. 4, pp. 545 –
550, June 2013.

93
[20] S. Dhiman and A. Singh, “Tesseract Vs Gocr A Comparative Study,” In-
ternational Journal of Recent Technology and Engineering (IJRTE), vol. 2,
pp. 80 – 83, September 2013.

[21] M. Nayak and A. K. Nayak, “Odia Characters Recognition by Training


Tesseract OCR Engine,” International Journal of Computer Applications
(IJCA), pp. 25 – 30, December 2013.

[22] C. Patel, A. Patel, and D. Patel, “Optical Character Recognition by Open


Source OCR Tool Tesseract: A Case Study,” International Journal of Com-
puter Applications, vol. 55, pp. 50–56, October 2012.

[23] K. Ntirogiannis, “Performance Evaluation Methodology for Historical Docu-


ment Image Binarization,” Institute of Electrical and Electronics Engineers
(IEEE), vol. 22, pp. 595 – 609, September 2012.

[24] D. sasirekha and E. Chandra, “Text-to-Speech: A Simple Tutorial,” Interna-


tional Journal of Soft Computing and Engineering (IJSCE), vol. 2, pp. 275 –
278, March 2012.

[25] R. Mithe and N. D. Supriya Indalkar, “Optical Character Recognition,” In-


ternational Journal of Recent Technology and Engineering (IJRTE)), vol. 2,
pp. 72 – 75, March 2013.

[26] S. Barve, “Optical Character Recognition Using Artificial Neural Network,”


International Journal of Advanced Research in Computer Engineering &
Technology), vol. 1, pp. 131 – 133, June 2012.

[27] S. Vijayarani and A. Sakila, “Performance Comparison of OCR Tools,” In-


ternational Journal of UbiComp (IJU)), vol. 6, pp. 19 – 29, July 2015.

[28] R. Urbanowicz and J. Moore, “Learning Classier Systems: A Complete In-


troduction, Review, and Roadmap,” Journal of Articial Evolution and Ap-
plications, vol. 2009, June 2009.

94
[29] J. Brownlee, “Clever Algorithms: Nature-Inspired Programming Recipes.”
http://www.cleveralgorithms.com/nature-inspired/evolution/
learning_classifier_system.html, 2015.

[30] T. Helland, “Seven grayscale conversion.” http://www.tannerhelland.com/


3643/grayscale-image-algorithm-vb6/.

[31] B. Cigan, “Java image binarization using Otsu’s algorithm.” http:


//developer.bostjan-cigan.com/java-image-binarization/, December
2012.

[32] VietOCR, “jTessBoxEditor.” http://vietocr.sourceforge.net/


training.html, 2008 - 2016.

[33] Wutka, “Directed Acyclic Word Graphs.” http://www.wutka.com/dawg.


html.

[34] J. Gosling and et al., Java Language Specification. Java SE 8 Edition,


Addison-Wesley Professional, 2014.

[35] R. Theis, “Tess-Two [Eclipse Android Library for Tesseract].” https://


github.com/rmtheis/tess-two, 2011.

[36] J. Polites, “GestureImageView.” https://github.com/jasonpolites/


gesture-imageview, 2012.

[37] ArthurHub, “Android-Image-Cropper.” https://github.com/ArthurHub/


Android-Image-Cropper/wiki, 2013.

[38] J. Zapata, “Android-pdfview.” https://github.com/JoanZapata/


android-pdfview, 2014.

[39] Google, “VuDroid.” https://code.google.com/archive/p/vudroid/.

[40] P. Siegman, “EPubLib.” https://github.com/psiegman/epublib.

95
[41] A. Kaloer, “Android-File-Picker-Activity.” https://github.com/
AndersKaloer/Android-File-Picker-Activity/tree/master/src/
com/kaloer/filepicker, 2011.

96
X. Appendix

A. Box File

A 283 3208 372 3329 0 f 1917 2357 1986 2466 0 k 2038 1424 2112 1507 0
A 440 3213 529 3343 0 f 2064 2345 2118 2464 0 k 2192 1424 2261 1499 0
A 605 3220 689 3353 0 f 2205 2357 2259 2468 0 k 2322 1406 2391 1491 0
A 767 3223 857 3353 0 f 2320 2349 2382 2472 0 L 279 1273 353 1403 0
A 930 3240 1016 3365 0 f 2420 2357 2498 2466 0 L 443 1285 516 1396 0
A 1092 3258 1181 3370 0 G 273 2129 361 2267 0 L 594 1279 679 1395 0
a 1282 3267 1371 3339 0 G 458 2130 534 2264 0 L 756 1282 834 1389 0
a 1415 3265 1510 3339 0 G 620 2136 697 2267 0 L 902 1282 977 1397 0
a 1550 3265 1642 3340 0 G 797 2135 873 2268 0 L 1027 1277 1091 1395 0
a 1704 3270 1789 3349 0 G 948 2128 1019 2271 0 L 1142 1269 1199 1392 0
a 1840 3287 1929 3350 0 G 1085 2122 1164 2259 0 l 1295 1274 1318 1376 0
a 1995 3281 2085 3356 0 h 1294 2160 1368 2268 0 l 1380 1265 1404 1373 0
a 2128 3285 2216 3357 0 h 1424 2147 1483 2277 0 l 1480 1272 1522 1361 0
a 2271 3293 2351 3357 0 h 1542 2158 1617 2280 0 l 1585 1279 1606 1366 0
a 2386 3301 2478 3371 0 h 1672 2157 1727 2284 0 l 1660 1265 1719 1361 0
B 287 3042 364 3166 0 h 1796 2149 1862 2287 0 l 1787 1267 1806 1368 0
B 454 3052 527 3168 0 h 1924 2156 1986 2283 0 l 1878 1269 1902 1369 0
B 609 3059 688 3172 0 h 2056 2145 2124 2287 0 l 1988 1270 2013 1373 0
B 773 3069 865 3183 0 h 2191 2146 2270 2277 0 l 2110 1283 2132 1370 0
B 946 3083 1029 3203 0 h 2315 2152 2383 2268 0 l 2236 1275 2268 1378 0
B 1109 3083 1195 3205 0 h 2425 2146 2508 2283 0 l 2362 1274 2381 1369 0
b 1299 3101 1369 3214 0 H 282 1947 366 2090 0 M 273 1095 370 1225 0
b 1434 3093 1506 3217 0 H 453 1949 536 2077 0 M 439 1114 539 1231 0
b 1573 3098 1641 3205 0 H 610 1953 729 2081 0 M 603 1106 702 1238 0
b 1711 3094 1780 3211 0 H 796 1947 894 2086 0 M 776 1098 886 1220 0
b 1851 3096 1925 3210 0 H 948 1933 1036 2082 0 M 942 1115 1048 1225 0
b 2001 3086 2072 3206 0 H 1090 1952 1174 2086 0 M 1095 1107 1197 1232 0
b 2137 3072 2213 3200 0 g 1285 1913 1358 2030 0 m 1286 1109 1379 1188 0
b 2282 3067 2354 3181 0 g 1407 1920 1475 2042 0 m 1428 1099 1526 1178 0
b 2407 3048 2487 3177 0 g 1548 1909 1622 2035 0 m 1582 1090 1689 1178 0
C 272 2852 360 2967 0 g 1669 1913 1749 2043 0 m 1749 1089 1856 1172 0
C 443 2857 530 2973 0 g 1800 1932 1869 2045 0 m 1909 1086 2020 1169 0
C 606 2858 690 2978 0 g 1931 1922 2000 2039 0 m 2090 1075 2193 1157 0
C 774 2865 870 2985 0 g 2056 1930 2129 2044 0 m 2256 1071 2361 1158 0
C 940 2867 1035 2990 0 g 2195 1930 2257 2046 0 N 263 907 350 1035 0
C 1106 2878 1205 2993 0 g 2304 1917 2382 2045 0 N 436 911 541 1029 0
c 1303 2896 1370 2967 0 g 2430 1922 2497 2048 0 N 609 911 685 1031 0
c 1432 2904 1498 2975 0 I 280 1783 355 1892 0 N 775 901 858 1044 0
c 1568 2911 1637 2980 0 I 444 1779 530 1889 0 N 944 923 1022 1071 0
c 1699 2909 1772 2983 0 I 610 1798 704 1891 0 N 1083 917 1170 1066 0
c 1838 2899 1908 2976 0 I 789 1794 874 1885 0 n 1269 947 1343 1023 0
c 1986 2907 2054 2974 0 I 942 1788 1030 1886 0 n 1425 950 1516 1031 0
c 2131 2917 2201 2988 0 I 1077 1771 1160 1887 0 n 1588 943 1669 1028 0
c 2271 2921 2341 2986 0 i 1307 1799 1329 1884 0 n 1755 950 1845 1031 0
c 2402 2918 2483 2984 0 i 1404 1792 1424 1885 0 n 1929 947 2002 1039 0
D 285 2675 354 2800 0 i 1494 1789 1523 1892 0 n 2093 946 2176 1037 0
D 454 2674 523 2802 0 i 1577 1774 1628 1880 0 n 2269 934 2361 1026 0
D 614 2680 688 2804 0 i 1672 1773 1698 1889 0 O 260 725 358 870 0
D 779 2687 851 2821 0 i 1773 1789 1800 1895 0 O 424 723 535 863 0
D 937 2690 1007 2818 0 i 1863 1796 1885 1901 0 O 591 718 704 858 0
D 1113 2686 1181 2822 0 i 1948 1803 1988 1897 0 O 765 721 885 861 0
d 1287 2702 1354 2824 0 i 2058 1795 2099 1888 0 O 938 719 1056 853 0
d 1409 2705 1476 2824 0 i 2146 1806 2178 1895 0 O 1085 734 1207 857 0
d 1545 2695 1619 2813 0 i 2223 1811 2257 1899 0 o 1274 734 1346 812 0
d 1678 2701 1751 2832 0 i 2309 1806 2355 1892 0 o 1439 737 1507 806 0
d 1836 2708 1907 2835 0 i 2415 1800 2444 1902 0 o 1596 727 1668 799 0
d 1972 2705 2049 2836 0 J 290 1643 346 1740 0 o 1765 727 1837 798 0
d 2115 2694 2192 2839 0 J 461 1633 524 1744 0 o 1922 725 1998 790 0
d 2240 2714 2310 2845 0 J 618 1640 693 1739 0 o 2087 713 2160 783 0
d 2354 2708 2430 2840 0 J 803 1640 861 1733 0 o 2289 708 2359 774 0
E 275 2504 352 2617 0 J 953 1611 1009 1736 0 P 279 501 343 662 0
E 449 2503 534 2621 0 J 1091 1628 1146 1736 0 P 435 496 502 670 0
E 621 2512 710 2622 0 j 1292 1622 1324 1721 0 P 599 477 671 663 0
E 793 2515 875 2629 0 j 1370 1609 1410 1721 0 P 779 475 850 668 0
E 949 2512 1033 2625 0 j 1469 1595 1512 1729 0 P 959 493 1033 674 0
E 1110 2516 1189 2640 0 j 1583 1588 1627 1714 0 P 1120 504 1198 668 0
e 1279 2531 1354 2606 0 j 1688 1583 1721 1721 0 p 1292 467 1365 602 0
e 1404 2537 1479 2610 0 j 1758 1586 1816 1718 0 P 1445 466 1517 610 0
e 1548 2543 1622 2634 0 j 1897 1569 1944 1726 0 P 1605 490 1681 604 0
e 1690 2548 1761 2620 0 j 2012 1572 2048 1723 0 P 1772 465 1845 597 0
e 1827 2545 1898 2630 0 j 2115 1577 2160 1737 0 P 1926 471 2000 594 0
e 1951 2548 2026 2642 0 j 2214 1590 2256 1697 0 P 2104 473 2171 592 0
e 2073 2550 2136 2637 0 j 2313 1583 2353 1728 0 P 2283 471 2350 601 0
e 2191 2546 2270 2624 0 j 2395 1583 2436 1733 0 Q 80 3248 171 3362 1
e 2300 2549 2379 2624 0 K 286 1435 360 1565 0 Q 270 3242 367 3361 1
e 2421 2561 2499 2634 0 K 454 1441 543 1554 0 Q 455 3258 552 3366 1
F 293 2312 359 2440 0 K 624 1442 712 1552 0 Q 637 3270 737 3378 1
F 445 2324 538 2423 0 K 788 1431 890 1552 0 Q 801 3277 914 3382 1
F 627 2316 703 2414 0 K 950 1430 1037 1552 0 Q 990 3283 1087 3386 1
F 812 2319 884 2431 0 K 1084 1435 1166 1553 0 q 1186 3228 1268 3352 1
F 964 2329 1036 2443 0 k 1260 1426 1320 1512 0 q 1330 3243 1428 3363 1
F 1109 2312 1176 2443 0 k 1359 1430 1416 1495 0 q 1500 3269 1587 3370 1
f 1282 2346 1338 2457 0 k 1454 1420 1507 1492 0 q 1646 3254 1746 3367 1
f 1408 2353 1473 2464 0 k 1553 1426 1608 1498 0 q 1800 3261 1900 3378 1
f 1522 2347 1595 2461 0 k 1649 1426 1716 1502 0 q 1956 3252 2042 3374 1
f 1651 2352 1723 2460 0 k 1764 1432 1834 1506 0 q 2112 3253 2196 3369 1
f 1785 2355 1846 2468 0 k 1885 1427 1969 1507 0 R 85 3035 170 3130 1

97
R 273 3026 356 3133 1 Y 93 1427 191 1591 1 # 1721 3072 1807 3148 2
R 462 3038 551 3143 1 Y 227 1461 320 1594 1 9 1833 3068 1887 3150 2
R 641 3042 732 3152 1 Y 382 1484 494 1598 1 0 1887 3070 1944 3136 2
R 807 3048 891 3157 1 Y 610 1464 705 1597 1 d 1994 3049 2050 3146 2
R 974 3065 1060 3169 1 Y 795 1472 906 1602 1 o 2058 3047 2108 3099 2
r 1207 3061 1258 3124 1 Y 973 1466 1064 1612 1 g 2116 3014 2170 3099 2
r 1352 3074 1411 3137 1 y 1130 1494 1200 1607 1 & 2230 3048 2288 3141 2
r 1505 3084 1567 3144 1 y 1280 1498 1349 1602 1 d 124 2870 176 2987 2
r 1650 3087 1710 3147 1 y 1429 1510 1496 1607 1 u 213 2872 260 2932 2
r 1804 3103 1867 3166 1 y 1571 1498 1637 1598 1 o 285 2873 336 2928 2
r 1975 3120 2041 3189 1 y 1694 1487 1768 1593 1 k 355 2866 426 2962 2
r 2113 3126 2176 3193 1 y 1834 1482 1901 1580 1 , 474 2848 498 2891 2
S 101 2811 172 2917 1 y 1961 1470 2019 1563 1 d 589 2860 643 2968 2
S 279 2808 348 2921 1 y 2078 1475 2154 1581 1 u 669 2851 725 2919 2
S 468 2809 529 2916 1 y 2220 1460 2282 1576 1 c 748 2868 797 2917 2
S 661 2834 728 2933 1 Z 82 1274 159 1387 1 k 822 2870 889 2948 2
S 834 2840 891 2945 1 Z 242 1279 315 1388 1 / 885 2833 995 2941 2
S 991 2843 1047 2945 1 Z 395 1263 466 1378 1 g 1024 2841 1086 2925 2
s 1198 2849 1247 2918 1 Z 591 1268 669 1372 1 o 1091 2861 1142 2927 2
s 1352 2859 1392 2927 1 Z 749 1252 845 1370 1 o 1156 2861 1218 2919 2
s 1502 2870 1554 2934 1 Z 906 1249 994 1362 1 s 1241 2865 1283 2925 2
s 1641 2872 1687 2940 1 z 1139 1235 1197 1311 1 e 1288 2857 1357 2916 2
s 1780 2874 1825 2946 1 z 1260 1237 1312 1303 1 , 1394 2837 1413 2876 2
s 1926 2871 1979 2955 1 z 1375 1228 1425 1297 1 a 1493 2851 1573 2918 2
s 2076 2877 2121 2960 1 z 1487 1220 1543 1294 1 s 1599 2836 1645 2910 2
T 90 2586 182 2681 1 z 1587 1231 1649 1291 1 l 1740 2842 1760 2920 2
T 254 2598 355 2685 1 z 1700 1234 1754 1291 1 2 1761 2842 1816 2920 2
T 427 2597 524 2694 1 z 1783 1228 1834 1295 1 . 1823 2857 1841 2873 2
T 634 2585 720 2693 1 z 1888 1231 1961 1297 1 5 1879 2840 1934 2917 2
T 801 2599 902 2711 1 z 2003 1232 2066 1291 1 % 1980 2839 2079 2933 2
T 969 2602 1072 2708 1 z 2113 1233 2170 1292 1 o 2173 2848 2225 2900 2
t 1183 2608 1266 2735 1 z 2212 1228 2271 1292 1 f 2242 2848 2289 2930 2
t 1320 2611 1381 2711 1 Z 65 1021 147 1135 1 E 130 2654 192 2756 2
t 1477 2620 1531 2711 1 Z 217 1022 313 1130 1 − 227 2688 263 2700 2
t 1619 2609 1673 2722 1 Z 383 1029 504 1126 1 m 302 2652 371 2720 2
t 1763 2623 1831 2718 1 Z 569 1023 662 1128 1 a 391 2645 440 2700 2
t 1922 2616 1977 2720 1 Z 746 1021 856 1129 1 i 449 2646 468 2723 2
t 2071 2614 2128 2704 1 Z 892 1012 1006 1132 1 l 497 2635 513 2743 2
U 94 2367 178 2471 1 z 1108 1005 1165 1077 1 f 665 2638 732 2750 2
U 261 2378 358 2480 1 z 1222 994 1285 1073 1 r 741 2650 794 2693 2
U 447 2378 535 2487 1 z 1342 1003 1410 1072 1 o 815 2647 863 2701 2
U 643 2381 732 2481 1 z 1460 998 1528 1070 1 m 884 2656 960 2702 2
U 819 2368 913 2487 1 z 1595 1002 1656 1069 1 a 1046 2644 1111 2711 2
U 991 2379 1085 2496 1 z 1705 1005 1779 1071 1 s 1119 2638 1155 2708 2
u 1190 2388 1245 2441 1 z 1825 1010 1906 1076 1 p 1161 2613 1216 2708 2
u 1316 2378 1376 2439 1 z 1943 1015 2014 1082 1 a 1216 2648 1277 2702 2
u 1444 2384 1513 2436 1 z 2060 1018 2133 1085 1 m 1279 2652 1352 2712 2
u 1578 2392 1653 2448 1 z 2163 1014 2258 1078 1 m 1356 2651 1442 2708 2
u 1710 2388 1785 2444 1 T 90 3320 141 3418 2 e 1457 2646 1514 2706 2
v 1830 2393 1872 2445 1 h 172 3311 223 3418 2 r 1519 2652 1578 2702 2
v 1911 2389 1962 2446 1 e 237 3311 295 3367 2 @ 1617 2628 1702 2720 2
u 1992 2387 2061 2439 1 ( 399 3314 448 3408 2 w 1731 2635 1805 2691 2
u 2091 2388 2145 2451 1 q 472 3273 536 3363 2 e 1803 2642 1849 2693 2
V 89 2133 168 2247 1 u 533 3313 584 3363 2 b 1858 2633 1915 2723 2
V 259 2144 335 2240 1 i 597 3318 615 3382 2 . 1926 2648 1944 2667 2
V 430 2134 511 2253 1 c 638 3306 695 3361 2 c 1978 2631 2028 2687 2
V 637 2136 724 2254 1 k 703 3316 781 3414 2 o 2031 2625 2077 2674 2
V 808 2142 895 2261 1 ) 802 3301 853 3417 2 m 2084 2623 2185 2676 2
V 985 2141 1084 2267 1 b 948 3299 1009 3408 2 i 2271 2621 2300 2693 2
v 1168 2145 1226 2204 1 r 1020 3306 1067 3352 2 s 2305 2619 2342 2669 2
v 1273 2144 1334 2203 1 o 1075 3303 1122 3352 2 s 121 2447 160 2517 2
v 1387 2143 1450 2209 1 w 1141 3305 1213 3354 2 p 175 2410 228 2496 2
v 1517 2147 1582 2213 1 n 1239 3302 1295 3360 2 a 229 2431 291 2487 2
v 1633 2149 1706 2218 1 f 1388 3301 1436 3400 2 m 296 2432 379 2496 2
v 1744 2154 1818 2226 1 o 1443 3303 1494 3357 2 ? 397 2437 450 2530 2
v 1876 2159 1944 2224 1 x 1507 3294 1547 3352 2 L 506 2431 556 2520 2
v 1997 2160 2065 2233 1 j 1628 3236 1664 3357 2 o 560 2425 616 2473 2
v 2097 2164 2164 2227 1 w 1693 3291 1760 3341 2 l 642 2426 662 2527 2
v 2206 2161 2261 2220 1 u 1797 3277 1859 3357 2 ’ 688 2497 706 2539 2
v 2297 2151 2345 2212 1 m 1885 3301 1961 3360 2 s 739 2439 778 2497 2
W 61 1919 178 2028 1 p 1979 3248 2032 3359 2 815 2424 926 2441 2
W 231 1915 352 2039 1 s 2033 3294 2068 3353 2 W 983 2432 1069 2500 2
W 403 1923 538 2040 1 ! 2080 3290 2102 3383 2 o 1087 2433 1145 2483 2
W 606 1929 720 2058 1 o 2156 3296 2202 3349 2 w 1166 2432 1253 2488 2
W 783 1937 904 2061 1 v 2209 3299 2254 3350 2 ! 1287 2406 1309 2498 2
W 958 1941 1081 2058 1 e 2253 3293 2294 3349 2 ? 1355 2402 1400 2499 2
w 1146 1956 1233 2009 1 r 2310 3300 2349 3347 2 ” 1431 2466 1477 2510 2
w 1283 1958 1375 2009 1 { 115 3095 171 3209 2 ˆ 1532 2456 1596 2502 2
w 1436 1959 1533 2011 1 t 201 3115 243 3201 2 + 1635 2388 1702 2476 2
w 1585 1969 1686 2019 1 h 255 3112 308 3192 2 ˜ 1766 2414 1859 2457 2
w 1750 1974 1859 2027 1 e 316 3113 372 3160 2 − 1927 2432 1971 2446 2
w 1917 1974 2028 2032 1 } 386 3089 429 3194 2 = 2038 2398 2102 2442 2
w 2084 1974 2179 2035 1 $ 555 3086 623 3212 2 : 2163 2389 2180 2454 2
w 2223 1984 2316 2044 1 3 652 3097 697 3190 2 ; 2234 2369 2257 2445 2
X 82 1703 181 1819 1 , 715 3079 730 3123 2 [ 2319 2374 2361 2472 2
X 233 1693 342 1829 1 4 752 3089 805 3181 2 ] 2419 2365 2462 2461 2
X 403 1698 498 1829 1 5 832 3093 875 3184 2 H 134 2207 187 2313 2
X 634 1691 721 1833 1 6 882 3098 940 3177 2 e 196 2213 243 2259 2
X 785 1702 895 1825 1 . 967 3109 984 3128 2 i 261 2213 280 2284 2
X 969 1718 1072 1833 1 7 1015 3093 1068 3177 2 k 294 2213 339 2294 2
x 1161 1713 1223 1790 1 8 1088 3092 1136 3175 2 o 353 2207 395 2260 2
x 1287 1704 1357 1790 1 1 1146 3088 1197 3171 2 , 440 2176 458 2216 2
x 1432 1702 1497 1791 1 2 1224 3091 1276 3164 2 f 512 2207 561 2300 2
x 1573 1717 1635 1798 1 < 1339 3094 1391 3152 2 e 566 2212 611 2257 2
x 1696 1723 1767 1799 1 l 1413 3088 1432 3165 2 i 625 2207 645 2275 2
x 1836 1701 1904 1801 1 a 1448 3082 1508 3138 2 g 662 2170 711 2257 2
x 1969 1720 2049 1810 1 z 1519 3082 1569 3139 2 n 721 2207 765 2255 2
x 2094 1722 2181 1807 1 y 1576 3049 1629 3133 2 i 776 2206 796 2267 2
x 2223 1702 2301 1797 1 > 1638 3088 1681 3145 2 n 811 2207 865 2251 2

98
g 867 2159 926 2247 2 t 1176 1537 1220 1638 2 b 2027 884 2081 973 2
s 988 2200 1031 2262 2 i 1243 1538 1262 1606 2 e 2094 882 2138 935 2
l 1051 2202 1069 2277 2 n 1282 1536 1338 1586 2 i 2163 884 2181 955 2
e 1087 2199 1134 2254 2 g 1355 1497 1412 1586 2 n 2202 884 2259 934 2
e 1150 2195 1204 2252 2 , 1455 1512 1475 1563 2 g 2279 835 2332 929 2
p 1230 2157 1279 2247 2 h 1539 1540 1594 1630 2 . 2370 889 2388 908 2
, 1307 2172 1324 2210 2 e 1605 1538 1652 1595 2 S 167 652 211 755 2
k 1384 2200 1436 2281 2 r 1665 1538 1717 1590 2 h 236 661 297 754 2
e 1454 2186 1501 2247 2 e 1771 1540 1817 1597 2 e 307 651 360 713 2
p 1507 2165 1558 2241 2 y 1829 1507 1878 1590 2 s 430 650 469 725 2
t 1565 2185 1617 2267 2 e 1896 1538 1944 1591 2 e 476 655 535 718 2
h 1696 2190 1751 2273 2 s 1956 1535 1992 1594 2 n 548 660 606 715 2
e 1759 2188 1806 2232 2 s 2072 1528 2105 1589 2 s 628 657 662 725 2
r 1811 2194 1857 2231 2 o 2120 1530 2174 1585 2 e 682 660 745 722 2
b 1942 2188 1994 2274 2 f 2186 1522 2229 1613 2 d 759 647 815 740 2
r 2002 2191 2062 2239 2 t 2247 1522 2298 1606 2 r 880 650 942 707 2
e 2058 2188 2108 2239 2 b 107 1319 170 1423 2 a 953 650 1016 708 2
a 2109 2184 2156 2234 2 e 187 1328 232 1380 2 t 1035 661 1078 758 2
t 2160 2181 2206 2260 2 n 254 1323 307 1382 2 h 1087 653 1150 750 2
h 2204 2193 2253 2272 2 e 323 1318 371 1380 2 e 1163 652 1223 715 2
i 2259 2188 2277 2243 2 a 385 1323 449 1375 2 r 1236 666 1283 710 2
n 2292 2182 2343 2231 2 t 467 1328 512 1413 2 t 1344 648 1396 756 2
g 2352 2151 2408 2227 2 h 525 1323 597 1420 2 h 1404 661 1462 753 2
d 118 1954 168 2068 2 u 720 1323 771 1380 2 a 1476 662 1539 713 2
e 199 1972 242 2033 2 n 776 1323 828 1379 2 n 1539 654 1597 710 2
e 267 1973 328 2054 2 f 848 1321 894 1408 2 f 1661 655 1715 752 2
p 356 1950 405 2038 2 l 910 1322 930 1411 2 e 1736 658 1785 722 2
a 499 1970 558 2025 2 u 957 1315 1014 1372 2 l 1804 658 1826 751 2
n 576 1972 631 2028 2 t 1014 1321 1050 1408 2 t 1850 655 1903 750 2
d 656 1970 710 2057 2 t 1062 1325 1097 1410 2 h 1955 669 2011 752 2
s 812 1965 856 2033 2 e 1111 1325 1161 1381 2 i 2021 666 2041 736 2
l 884 1977 902 2068 2 r 1171 1328 1213 1376 2 m 2060 653 2154 716 2
o 920 1965 978 2024 2 i 1222 1325 1240 1397 2 a 138 424 210 505 2
w 1005 1969 1088 2027 2 n 1257 1327 1315 1378 2 w 242 429 334 492 2
, 1120 1941 1143 1996 2 g 1338 1274 1391 1379 2 a 367 424 443 491 2
h 1207 1973 1259 2063 2 e 1457 1333 1505 1396 2 k 463 430 535 510 2
e 1268 1975 1317 2027 2 y 1508 1304 1560 1386 2 e 548 432 616 503 2
r 1331 1972 1391 2027 2 e 1567 1325 1622 1386 2 n 639 426 701 497 2
m 1456 1981 1547 2044 2 l 1632 1324 1652 1404 2 b 822 430 892 524 2
u 1559 1976 1613 2039 2 i 1659 1330 1677 1401 2 e 920 432 979 496 2
s 1617 1975 1656 2035 2 d 1696 1322 1748 1405 2 s 1032 431 1076 497 2
c 1667 1982 1721 2035 2 s 1772 1319 1804 1376 2 i 1104 436 1126 517 2
l 1736 1985 1754 2069 2 , 1838 1304 1863 1352 2 d 1164 432 1223 519 2
e 1774 1992 1832 2046 2 h 1926 1302 1990 1410 2 e 1255 429 1317 502 2
s 1846 1976 1889 2042 2 e 2005 1307 2054 1365 2 h 1420 436 1491 532 2
r 1963 1970 2014 2026 2 r 2066 1314 2116 1363 2 e 1504 432 1572 508 2
e 2015 1971 2063 2048 2 h 2189 1312 2244 1413 2 r 1593 443 1650 501 2
l 2081 1975 2100 2051 2 o 2256 1308 2309 1364 2 . 1673 457 1691 477 2
a 2114 1969 2164 2017 2 o 2320 1311 2366 1368 2 W 133 3310 233 3412 3
x 2174 1954 2225 2028 2 d 2383 1307 2433 1394 2 h 263 3304 317 3408 3
e 2233 1964 2284 2028 2 e 2434 1302 2483 1366 2 e 342 3308 394 3364 3
d 2284 1963 2335 2054 2 d 2485 1300 2533 1394 2 n 419 3314 480 3370 3
b 113 1742 169 1843 2 g 128 1051 191 1161 2 h 587 3315 644 3414 3
u 197 1741 255 1795 2 a 215 1089 280 1154 2 e 664 3311 718 3378 3
t 273 1747 313 1831 2 z 309 1091 376 1157 2 t 797 3315 841 3410 3
n 387 1754 442 1809 2 e 403 1087 466 1156 2 u 861 3306 908 3368 3
o 443 1746 484 1805 2 t 549 1086 598 1186 2 r 933 3316 988 3367 3
t 500 1743 534 1834 2 u 623 1091 676 1149 2 n 1009 3310 1071 3378 3
S 612 1750 650 1820 2 r 687 1094 729 1146 2 e 1081 3308 1132 3372 3
l 661 1746 678 1834 2 n 739 1092 789 1150 2 d 1140 3299 1186 3403 3
a 694 1744 748 1795 2 e 798 1090 851 1151 2 t 1265 3305 1309 3397 3
c 774 1750 820 1795 2 d 861 1087 917 1186 2 o 1325 3305 1376 3355 3
k 831 1756 892 1825 2 w 1008 1096 1100 1157 2 l 1472 3313 1494 3396 3
e 905 1753 957 1809 2 i 1137 1095 1160 1193 2 o 1520 3309 1564 3361 3
d 971 1740 1027 1833 2 t 1175 1081 1229 1182 2 o 1587 3300 1632 3359 3
, 1068 1724 1093 1771 2 h 1229 1095 1288 1194 2 k 1654 3303 1717 3383 3
h 1152 1753 1204 1839 2 i 1306 1099 1324 1171 2 a 1773 3298 1832 3356 3
e 1222 1748 1271 1802 2 n 1349 1102 1411 1156 2 t 1848 3301 1887 3387 3
r 1279 1754 1325 1801 2 , 1468 1064 1486 1130 2 h 1962 3298 2019 3394 3
l 1389 1746 1407 1837 2 t 1548 1094 1590 1182 2 e 2036 3297 2087 3358 3
i 1424 1741 1442 1815 2 o 1618 1097 1667 1155 2 r 2099 3303 2156 3354 3
p 1464 1706 1522 1806 2 t 1730 1101 1777 1179 2 , 2188 3281 2203 3318 3
s 1529 1742 1570 1805 2 h 1781 1100 1832 1186 2 s 2259 3291 2297 3367 3
, 1587 1712 1617 1764 2 e 1849 1103 1896 1161 2 h 2319 3298 2379 3380 3
c 1686 1754 1731 1806 2 c 1998 1100 2040 1160 2 e 2385 3291 2441 3351 3
l 1733 1747 1754 1832 2 a 2064 1099 2119 1154 2 h 125 3104 182 3210 3
o 1764 1745 1805 1793 2 l 2138 1095 2163 1185 2 o 187 3099 237 3155 3
s 1821 1745 1859 1797 2 m 2185 1098 2284 1150 2 p 251 3067 308 3158 3
e 1857 1741 1909 1790 2 p 139 833 198 939 2 e 319 3103 368 3173 3
d 1928 1735 1974 1824 2 l 212 876 230 963 2 d 388 3086 432 3179 3
, 2002 1721 2020 1766 2 a 264 873 325 931 2 h 467 3086 529 3174 3
a 2087 1744 2143 1801 2 c 346 873 394 932 2 e 537 3080 592 3150 3
t 2155 1743 2189 1830 2 e 416 876 469 942 2 w 682 3090 767 3152 3
t 2253 1751 2292 1837 2 a 590 874 654 933 2 o 777 3088 828 3146 3
h 2296 1745 2349 1832 2 t 681 872 725 962 2 u 842 3068 896 3141 3
e 2351 1740 2421 1815 2 t 805 864 860 975 2 l 913 3085 932 3170 3
v 110 1527 160 1602 2 h 869 882 927 975 2 d 948 3079 1000 3162 3
e 177 1541 220 1593 2 e 946 879 999 941 2 s 1050 3082 1086 3138 3
r 242 1542 282 1591 2 c 1111 886 1166 942 2 e 1102 3083 1156 3137 3
y 302 1506 365 1591 2 e 1168 882 1211 946 2 e 1165 3078 1225 3141 3
e 451 1534 501 1605 2 n 1230 884 1284 942 2 : 1247 3086 1273 3152 3
d 520 1516 574 1604 2 t 1303 888 1348 973 2 H 150 2865 226 2990 3
g 592 1501 650 1572 2 e 1355 883 1414 942 2 e 262 2880 309 2944 3
e 664 1532 719 1593 2 r 1439 884 1487 940 2 r 332 2888 376 2942 3
o 832 1542 876 1589 2 o 1594 878 1646 937 2 h 471 2880 530 2981 3
f 884 1539 932 1623 2 f 1657 876 1697 955 2 a 544 2876 594 2930 3
P 986 1506 1041 1594 2 h 1763 879 1823 963 2 i 612 2876 628 2956 3
a 1050 1536 1107 1586 2 e 1835 875 1889 930 2 r 646 2884 699 2929 3
r 1113 1546 1154 1592 2 r 1901 882 1958 931 2 : 728 2890 746 2952 3

99
t 805 2878 853 2964 3 l 503 1980 527 2075 3 r 1705 1294 1756 1343 3
h 868 2881 919 2965 3 i 538 1980 559 2050 3 l 1770 1293 1794 1378 3
e 926 2875 981 2939 3 g 586 1944 648 2035 3 y 1817 1257 1875 1346 3
u 1064 2861 1121 2930 3 h 644 1967 709 2061 3 e 1950 1275 2015 1343 3
t 1140 2866 1186 2960 3 t 715 1981 753 2069 3 m 2029 1269 2101 1338 3
t 1201 2875 1240 2949 3 s 846 1978 878 2043 3 b 2120 1275 2167 1361 3
e 1264 2867 1320 2926 3 t 894 1974 935 2075 3 r 2184 1274 2234 1327 3
r 1326 2876 1380 2918 3 o 957 1975 1000 2035 3 o 2247 1263 2290 1325 3
d 1478 2850 1529 2954 3 l 1033 1984 1051 2065 3 i 2304 1277 2322 1356 3
a 1543 2845 1601 2898 3 e 1071 1975 1134 2047 3 d 2345 1268 2390 1349 3
r 1613 2852 1671 2899 3 n 1145 1985 1203 2047 3 e 2397 1268 2445 1330 3
k 1692 2852 1762 2933 3 f 1282 1972 1336 2068 3 d 2452 1261 2500 1355 3
o 1851 2851 1892 2904 3 r 1340 1976 1390 2030 3 p 137 1042 194 1164 3
f 1915 2851 1954 2934 3 o 1394 1966 1443 2026 3 a 209 1085 274 1145 3
s 2032 2841 2079 2911 3 m 1457 1966 1533 2027 3 i 294 1089 322 1194 3
t 2092 2846 2132 2928 3 t 1605 1966 1657 2062 3 r 352 1090 410 1144 3
a 2142 2843 2201 2899 3 h 1660 1969 1712 2063 3 o 509 1075 560 1138 3
r 2204 2847 2258 2892 3 e 1717 1970 1773 2036 3 f 575 1070 616 1160 3
l 2286 2842 2307 2932 3 m 1846 1958 1951 2038 3 w 702 1075 784 1129 3
e 2321 2842 2379 2907 3 o 1977 1965 2029 2017 3 h 781 1075 839 1168 3
s 2396 2840 2432 2896 3 o 2052 1961 2107 2016 3 i 856 1072 877 1155 3
s 2437 2822 2476 2893 3 n 2126 1966 2196 2022 3 t 898 1074 943 1162 3
n 144 2664 212 2736 3 . 2228 1987 2243 2005 3 e 963 1073 1019 1142 3
i 227 2660 248 2735 3 H 156 1749 231 1862 3 c 1130 1072 1188 1145 3
g 277 2633 339 2713 3 e 248 1748 302 1824 3 r 1206 1077 1261 1131 3
h 347 2665 415 2748 3 r 308 1754 369 1807 3 a 1276 1071 1341 1129 3
t 434 2662 474 2747 3 b 426 1752 491 1854 3 n 1352 1075 1406 1133 3
s 591 2655 633 2718 3 o 510 1750 560 1806 3 e 1426 1072 1487 1133 3
p 660 2624 712 2713 3 d 590 1750 644 1841 3 s 1511 1068 1554 1139 3
i 743 2653 762 2725 3 y 669 1723 730 1807 3 , 1610 1055 1629 1099 3
l 790 2655 813 2731 3 : 743 1762 765 1835 3 t 1690 1064 1730 1160 3
l 820 2653 842 2744 3 s 855 1752 893 1829 3 h 1743 1057 1799 1158 3
i 867 2650 892 2719 3 u 904 1758 955 1808 3 e 1808 1058 1868 1123 3
n 925 2647 981 2695 3 g 968 1727 1030 1812 3 i 1895 1070 1915 1141 3
g 1001 2612 1055 2694 3 g 1045 1722 1100 1810 3 r 1927 1069 1982 1120 3
a 1152 2646 1223 2704 3 e 1118 1758 1174 1820 3 t 2087 1056 2126 1158 3
c 1240 2634 1292 2690 3 s 1194 1754 1233 1823 3 h 2139 1051 2206 1150 3
r 1302 2644 1349 2692 3 t 1250 1760 1297 1855 3 r 2210 1049 2258 1103 3
o 1360 2641 1403 2687 3 i 1319 1766 1337 1831 3 o 2276 1042 2315 1099 3
s 1422 2639 1456 2695 3 v 1361 1756 1413 1814 3 a 2330 1042 2382 1098 3
s 1471 2634 1503 2690 3 e 1418 1758 1475 1822 3 t 2387 1049 2428 1139 3
t 1588 2622 1634 2719 3 c 1569 1744 1620 1819 3 s 2449 1038 2480 1112 3
h 1656 2629 1707 2715 3 u 1629 1745 1693 1811 3 c 114 867 179 959 3
e 1720 2624 1770 2684 3 r 1714 1754 1775 1811 3 r 180 871 227 925 3
b 1847 2626 1909 2713 3 v 1796 1752 1849 1813 3 i 227 871 245 952 3
l 1924 2629 1942 2714 3 a 1853 1739 1916 1802 3 m 264 865 353 927 3
u 1973 2615 2030 2675 3 t 1932 1746 1975 1838 3 s 381 861 417 932 3
e 2053 2617 2104 2678 3 u 1995 1743 2057 1803 3 o 435 867 491 921 3
s 2160 2616 2198 2680 3 r 2077 1752 2128 1803 3 n 509 863 571 922 3
i 2234 2618 2251 2693 3 e 2139 1745 2188 1807 3 w 657 860 741 921 3
l 2281 2612 2309 2705 3 s 2205 1741 2241 1805 3 i 756 857 776 943 3
k 2321 2617 2384 2697 3 b 146 1529 212 1643 3 t 794 850 838 936 3
U 134 2441 203 2526 3 e 227 1526 280 1590 3 h 848 846 926 945 3
n 200 2437 257 2492 3 n 285 1534 345 1593 3 m 1008 842 1110 914 3
d 267 2429 307 2511 3 e 357 1534 409 1597 3 a 1124 845 1179 906 3
e 309 2435 351 2484 3 a 419 1534 481 1590 3 t 1198 843 1233 941 3
r 352 2440 397 2492 3 t 490 1535 532 1623 3 i 1262 850 1285 928 3
s 415 2439 448 2498 3 h 545 1525 610 1627 3 n 1311 845 1376 912 3
h 455 2442 507 2521 3 t 685 1524 747 1629 3 g 1393 817 1457 903 3
e 520 2445 563 2492 3 h 736 1524 799 1626 3 f 1554 837 1606 935 3
e 573 2443 613 2491 3 e 804 1517 873 1588 3 r 1622 841 1676 898 3
t 630 2440 668 2528 3 c 961 1520 1017 1590 3 e 1689 842 1748 904 3
. 688 2446 704 2463 3 o 1021 1521 1071 1576 3 n 1764 842 1821 903 3
H 153 2204 222 2324 3 v 1087 1524 1143 1584 3 z 1849 845 1907 905 3
e 244 2217 294 2288 3 e 1148 1524 1203 1586 3 y 1948 808 2012 899 3
r 323 2232 365 2283 3 r 1209 1529 1251 1577 3 , 2057 823 2075 862 3
f 427 2216 471 2316 3 l 1264 1525 1290 1613 3 d 2146 832 2200 924 3
a 490 2218 554 2279 3 e 1310 1521 1366 1585 3 a 2228 834 2286 892 3
c 562 2219 608 2277 3 t 1385 1527 1427 1608 3 n 2300 833 2352 891 3
e 617 2215 669 2279 3 , 1477 1503 1495 1539 3 c 2362 825 2412 890 3
: 682 2205 702 2259 3 a 1560 1509 1624 1583 3 i 2428 825 2449 905 3
p 765 2170 826 2270 3 l 1634 1523 1658 1608 3 n 117 647 182 718 3
a 836 2206 895 2259 3 s 1670 1506 1710 1581 3 g 204 614 271 712 3
l 905 2212 925 2294 3 o 1731 1506 1781 1566 3 a 412 644 487 712 3
e 938 2206 986 2273 3 o 1853 1499 1902 1558 3 n 505 649 567 704 3
a 1068 2200 1132 2255 3 f 1925 1506 1972 1596 3 d 599 631 651 729 3
s 1154 2195 1185 2254 3 s 2051 1503 2091 1569 3 d 779 630 835 736 3
s 1278 2180 1313 2254 3 i 2112 1501 2130 1588 3 u 842 625 923 690 3
p 1332 2160 1390 2255 3 l 2156 1502 2177 1587 3 e 939 627 988 691 3
r 1400 2199 1446 2249 3 k 2188 1504 2257 1588 3 l 1001 624 1024 726 3
i 1469 2200 1487 2264 3 , 2280 1482 2296 1512 3 i 1041 634 1067 709 3
n 1509 2199 1566 2249 3 e 162 1316 227 1389 3 n 1089 636 1151 690 3
g 1583 2159 1645 2248 3 m 259 1314 342 1385 3 g 1165 603 1223 689 3
s 1717 2192 1750 2259 3 b 368 1307 423 1406 3 i 1305 639 1326 723 3
n 1771 2185 1827 2241 3 l 441 1314 463 1412 3 n 1335 633 1396 696 3
o 1844 2186 1885 2237 3 a 495 1295 562 1364 3 m 1474 626 1566 694 3
w 1899 2188 1982 2236 3 z 582 1297 642 1369 3 i 1574 633 1595 713 3
, 2007 2164 2023 2206 3 o 661 1305 716 1363 3 d 1610 621 1660 710 3
g 2087 2152 2143 2232 3 n 724 1310 791 1370 3 a 1692 625 1754 685 3
l 2153 2178 2178 2263 3 e 807 1306 872 1368 3 i 1763 631 1784 694 3
o 2195 2171 2240 2227 3 d 895 1297 953 1390 3 r 1806 628 1868 679 3
w 2258 2172 2326 2226 3 w 1052 1298 1124 1359 3 , 1905 612 1922 648 3
i 2347 2178 2363 2246 3 i 1152 1304 1174 1397 3 a 2008 622 2074 684 3
n 2383 2172 2438 2230 3 t 1193 1302 1243 1385 3 g 2090 584 2152 674 3
g 2456 2140 2511 2219 3 h 1254 1293 1313 1391 3 a 2173 603 2240 666 3
w 165 1977 242 2042 3 a 1400 1303 1464 1354 3 i 2239 612 2264 690 3
i 263 1981 284 2063 3 f 1527 1288 1577 1385 3 n 2283 612 2341 670 3
t 297 1973 343 2059 3 a 1594 1293 1651 1345 3 s 2362 601 2395 666 3
h 346 1967 413 2067 3 i 1665 1293 1684 1362 3 t 2419 611 2460 698 3

100
a 138 442 209 503 3 d 491 420 535 509 3 l 986 405 1010 507 3
f 274 424 327 532 3 o 641 413 693 482 3 d 1041 402 1097 506 3
i 344 436 366 507 3 f 712 412 750 511 3
e 378 424 439 489 3 g 824 379 890 485 3
l 455 422 476 517 3 o 906 408 954 476 3

B. Source Codes

B..1 Tess2Speech Mobile Application

Base Path = Tess2Speech/

Path = Tess2Speech/build.gradle

// Top−l e v e l build file where you can add c o n f i g u r a t i o n o p t i o n s common t o all sub−p r o j e c t s / modules .

buildscript {
repositories {
jcenter ()
}
dependencies {
c l a s s p a t h ’ com . a n d r o i d . t o o l s . b u i l d : g r a d l e : 1 . 5 . 0 ’
// NOTE: Do n o t p l a c e y o u r a p p l i c a t i o n d e p e n d e n c i e s here ; they belong
// i n t h e i n d i v i d u a l module b u i l d . g r a d l e f i l e s
}
}

allprojects {
repositories {
jcenter ()
}
}

Path = Tess2Speech/settings.gradle

include ’: tess2speech ’
include ’: l i b r a r i e s : a n d r o i d −p d f v i e w −m a s t e r : a n d r o i d −p d f v i e w ’
include ’: l i b r a r i e s : t e s s −two ’
include ’: l i b r a r i e s : g e s t u r e −imageview ’
include ’: l i b r a r i e s : c r o p p e r −m a s t e r : c r o p p e r ’
include ’: l i b r a r i e s : a n d r o i d − f i l e −p i c k e r a c t i v i t y ’

101
Path = Tess2Speech/libraries
This folder contains different open-source libraries used in developing Tess2Speech:

1. android-file-picker activity by Anders Kaloer [41]

2. android-pdfview-master by Joan Zapata [38]

3. cropper-master by ArthurHub [37]

4. epublib by Paul Siegman [40]

5. gesture-imageview by Jason Polites [36]

6. tess-two by Robert Theis [35]

Path = Tess2Speech/tess2Speech/build.gradle

apply plugin : ’ com . a n d r o i d . a p p l i c a t i o n ’ //}

android { dependencies {
c o m p i l e S d k V e r s i o n 23 compile f i l e T r e e ( include : [ ’ ∗ . jar ’ ] , d i r :
buildToolsVersion ’23.0.2 ’ ’ libs ’)
defaultConfig { testCompile ’ j u n i t : j u n i t : 4 . 1 2 ’
applicationId ” anteraaron . tess2speech ” c o m p i l e p r o j e c t ( ’ : l i b r a r i e s : t e s s −two ’ )
m i n S d k V e r s i o n 16 compile p r o j e c t ( ’ : l i b r a r i e s : gesture −
t a r g e t S d k V e r s i o n 23 imageview ’ )
versionCode 1 compile p r o j e c t ( ’ : l i b r a r i e s : android−
versionName ” 1 . 0 ” p d f v i e w −m a s t e r : a n d r o i d −p d f v i e w ’ )
signingConfig signingConfigs . release c o m p i l e p r o j e c t ( ’ : l i b r a r i e s : c r o p p e r −m a s t e r
} : cropper ’ )
buildTypes { compile p r o j e c t ( ’ : l i b r a r i e s : android−f i l e −
release { picker activity ’)
debuggable f a l s e c o m p i l e ’ com . a n d r o i d . s u p p o r t : appcompat−v7
minifyEnabled f a l s e :23.1.1 ’
proguardFiles c o m p i l e ’ com . a n d r o i d . s u p p o r t : d e s i g n
getDefaultProguardFile ( ’ :23.1.1 ’
p r o g u a r d−a n d r o i d . t x t ’ ) , ’ c o m p i l e ’ com . a n d r o i d . s u p p o r t : s u p p o r t −v4
p r o g u a r d−r u l e s . pro ’ :23.1.1 ’
signingConfig signingConfigs . c o m p i l e ’ commons−i o : commons−i o : 2 . 4 ’
release c o m p i l e f i l e s ( ’ E : / Aaron / Dropbox / Workspace /
} Tess2Speech / l i b r a r i e s / epublib / epublib
} −c o r e −l a t e s t . j a r ’ )
productFlavors { c o m p i l e f i l e s ( ’ E : / Aaron / Dropbox / Workspace /
} Tess2Speech / l i b r a r i e s / epublib / s l f 4 j −
} a n d r o i d −1.6.1 −RC1 . j a r ’ )
}
// r e p o s i t o r i e s {
// m ave nCe ntr al ( )

Path = Tess2Speech/tess2Speech/proguard-rules.pro

# Add p r o j e c t s p e c i f i c ProGuard r u l e s h e r e . # Add any p r o j e c t specific keep o p t i o n s here :


# By d e f a u l t , t h e f l a g s i n t h i s f i l e a r e
appended t o f l a g s s p e c i f i e d # If y o u r p r o j e c t u s e s WebView w i t h JS ,
# i n E : \ Aaron \ Android \ sdk / t o o l s / p r o g u a r d / uncomment t h e f o l l o w i n g
p r o g u a r d−a n d r o i d . t x t # and s p e c i f y t h e f u l l y q u a l i f i e d c l a s s name
# You can e d i t t h e i n c l u d e path and o r d e r by to the JavaScript i n t e r f a c e
changing the proguardFiles # class :
# d i r e c t i v e in build . gradle . #−k e e p c l a s s m e m b e r s c l a s s f q c n . o f . j a v a s c r i p t .
# i n t e r f a c e . f o r . webview {
# For more d e t a i l s , s e e # public ∗;
# h t t p : / / d e v e l o p e r . a n d r o i d . com/ g u i d e / #}
d e v e l o p i n g / t o o l s / p r o g u a r d . html

102
Path = Tess2Speech/tess2Speech/src/main/AndroidManifest.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a c t i o n . MAIN” />


< !−− <c a t e g o r y a n d r o i d : n a m e=” a n d r o i d . i n t e n t
C o p y r i g h t 2016 Anter Aaron M. C u s t o d i o . c a t e g o r y .LAUNCHER” />
</ i n t e n t − f i l t e r >
L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n </ a c t i v i t y>
2.0 ( the ” License ” ) ;
you may n o t u s e t h i s f i l e e x c e p t i n < !−− Main A c t i v i t y −−>
compliance with the L i c e n s e . <a c t i v i t y
You may o b t a i n a copy o f t h e L i c e n s e a t a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
Activity Main ”
h t t p : //www. a p a c h e . o r g / l i c e n s e s /LICENSE−2.0 a n d r o i d : l a b e l=” @ s t r i n g / app name ”
a n d r o i d : t h e m e=” @ s t y l e /AppTheme .
U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d NoActionBar ”>
to in writing , software </ a c t i v i t y>
d i s t r i b u t e d under the L i c e n s e i s d i s t r i b u t e d
on an ”AS I S ” BASIS , < !−− R o t a t e A c t i v i t y −−>
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , < a c t i v i t y a n d r o i d : n a m e=” a n t e r a a r o n .
e i t h e r express or implied . tess2speech . Activity Rotate ”
See the L i c e n s e f o r the s p e c i f i c language a n d r o i d : l a b e l=” R o t a t e Image ”
g o v e r n i n g p e r m i s s i o n s and a n d r o i d : s c r e e n O r i e n t a t i o n=” p o r t r a i t ”>
l i m i t a t i o n s under the L i c e n s e . </ a c t i v i t y>
−−>
<m a n i f e s t x m l n s : a n d r o i d=” h t t p : // schemas . < !−− P r e f e r e n c e A c t i v i t y −−>
a n d r o i d . com/ apk / r e s / a n d r o i d ” < a c t i v i t y a n d r o i d : n a m e=” a n t e r a a r o n .
p a c k a g e=” a n t e r a a r o n . t e s s 2 s p e e c h ”> t e s s 2 s p e e c h . A c t i v i t y S e t t i n g s ”>
</ a c t i v i t y>
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d .
p e r m i s s i o n . READ EXTERNAL STORAGE” /> < !−− Crop A c t i v i t y −−>
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . < a c t i v i t y a n d r o i d : n a m e=” a n t e r a a r o n .
p e r m i s s i o n . WRITE EXTERNAL STORAGE” /> tess2speech . Activity Crop ”
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . a n d r o i d : l a b e l=” Crop Image ”>
p e r m i s s i o n . READ INTERNAL STORAGE” /> </ a c t i v i t y>
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d .
p e r m i s s i o n . WRITE INTERNAL STORAGE” /> < !−− F i l e Br ows er−−>
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . < a c t i v i t y a n d r o i d : n a m e=” k a l o e r . f i l e p i c k e r .
p e r m i s s i o n . READ USER DICTIONARY” /> FilePickerActivity ”
<u s e s −p e r m i s s i o n a n d r o i d : n a m e=” a n d r o i d . a n d r o i d : i c o n=”@mipmap/ l o g o ”
p e r m i s s i o n . READ PHONE STATE” /> a n d r o i d : e n a b l e d=” t r u e ”
<u s e s −f e a t u r e a n d r o i d : l a b e l=” Browse F i l e ”
a n d r o i d : n a m e=” a n d r o i d . h a r d w a r e . camera ” a n d r o i d : e x p o r t e d=” t r u e ”>
a n d r o i d : r e q u i r e d=” t r u e ” /> <i n t e n t − f i l t e r >
<a c t i o n a n d r o i d : n a m e=” a n d r o i d . i n t e n t .
<a p p l i c a t i o n a c t i o n .GET CONTENT” />
a n d r o i d : a l l o w B a c k u p=” t r u e ”
a n d r o i d : i c o n=”@mipmap/ l o g o ” <c a t e g o r y a n d r o i d : n a m e=” a n d r o i d . i n t e n t
a n d r o i d : l a b e l=” @ s t r i n g / app name ” . c a t e g o r y .DEFAULT” />
a n d r o i d : l a r g e H e a p=” t r u e ” <c a t e g o r y a n d r o i d : n a m e=” a n d r o i d . i n t e n t
a n d r o i d : s u p p o r t s R t l=” t r u e ” . c a t e g o r y .OPENABLE” />
a n d r o i d : t h e m e=” @ s t y l e /AppTheme”>
<d a t a android:mimeType=” ∗/∗ ” />
< !−− S p l a s h S c r e e n A c t i v i t y −−> </ i n t e n t − f i l t e r >
< a c t i v i t y a n d r o i d : n a m e=” a n t e r a a r o n . </ a c t i v i t y>
tess2speech . Activity SplashScreen ”
a n d r o i d : t h e m e=” @ s t y l e /AppTheme . </ a p p l i c a t i o n>
NoActionBar ”
a n d r o i d : s c r e e n O r i e n t a t i o n=” p o r t r a i t ”> </ m a n i f e s t>
<i n t e n t − f i l t e r >
<a c t i o n a n d r o i d : n a m e=” a n d r o i d . i n t e n t .

103
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Activity\_Crop.java

package anteraaron . t e s s 2 s p e e c h ; @O verr ide


p u b l i c v o i d o n C l i c k ( View v ) {
import android . content . I n t e n t ; // C a l l s an AsyncTask t h a t s a v e s t h e
import android . net . Uri ; c r o p p e d image t o a f i l e
i m p o r t a n d r o i d . s u p p o r t . v7 . app . new Task SaveCroppedImage ( A c t i v i t y C r o p .
AppCompatActivity ; t h i s , new Task SaveCroppedImage .
i m p o r t a n d r o i d . o s . Bundle ; AsyncResponse ( ) {
i m p o r t a n d r o i d . v i e w . View ; @O verr ide
i m p o r t a n d r o i d . w i d g e t . Button ; public void processFinished ( F i l e f i l e ) {
i m p o r t com . t h e a r t o f d e v . edmodo . c r o p p e r . // Return f i l e a f t e r s a v i n g t h e c r o p p e d
CropImageView ; image t o g e t f i l e path .
import java . i o . F i l e ; f i n a l Uri f i l e U r i = Uri . fromFile ( f i l e ) ;
//Add t h e c r o p p e d image f i l e t o g a l l e r y .
/∗ ∗ L i b r a r i e s . galleryAddPic ( f i l e U r i ) ;
∗ A c t i v i t y f o r c r o p p i n g I mages u s i n g Edmodo // P a s s t h e f i l e u r i back t o
Cropper ( s e e . . . h t t p s : / / g i t h u b . com/ A c t i v i t y M a i n w i t h OK r e s u l t .
ArthurHub / Android−Image−Cropper / w i k i ) . f i n a l I n t e n t i n t e n t = new I n t e n t ( ) ;
∗ @author Anter Aaron M. C u s t o d i o i n t e n t . putExtra ( ” imageUri ” , f i l e U r i ) ;
∗ @version 2016.3.22 s e t R e s u l t (RESULT OK, i n t e n t ) ;
∗/ // C l e a r imageView
public c l a s s Activity Crop extends imageView crop . clearImage ( ) ;
AppCompatActivity { imageView crop . destroyDrawingCache ( ) ;
imageView crop . removeAllViews ( ) ;
@O verr ide finish () ;
p r o t e c t e d v o i d o n C r e a t e ( f i n a l Bundle }
savedInstanceState ) { } ) . e x e c u t e ( i m a g e V i e w c r o p . g et C r o pp e d I ma g e
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; ( ) ) ; // t h e p a r a m e t e r f o r doInBackground i n
s e t C o n t e n t V i e w (R . l a y o u t . a c t i v i t y c r o p ) ; Task Crop i s t h e c r o p p e d image .
// R e t r i e v e U r i o f t h e p a s s e d image from }
Activity Main . }) ;
f i n a l Uri imageUri = g e t I n t e n t ( ) . // C r e a t e c a n c e l c r o p b u t t o n .
g e t P a r c e l a b l e E x t r a ( ” imageUri ” ) ; f i n a l Button b u t t o n c r o p c a n c e l = ( Button )
// C r e a t e Edmodo Cropper ImageView . f i n d V i e w B y I d (R . i d . b u t t o n c r o p c a n c e l ) ;
f i n a l CropImageView i m a g e V i e w c r o p = ( b u t t o n c r o p c a n c e l . s e t O n C l i c k L i s t e n e r ( new
CropImageView ) f i n d V i e w B y I d (R . i d . View . O n C l i c k L i s t e n e r ( ) {
CropImageView ) ; @O verr ide
imageView crop . setFixedAspectRatio ( f a l s e ) ; p u b l i c v o i d o n C l i c k ( View v ) {
i m a g e V i e w c r o p . s e t G u i d e l i n e s ( CropImageView . // R e t u r n s c a n c e l r e s u l t t o A c t i v i t y M a i n .
G u i d e l i n e s .ON TOUCH) ; s e t R e s u l t (RESULT CANCELED) ;
imageView crop . setImageUriAsync ( imageUri ) ; finish () ;
// C r e a t e c o n f i r m c r o p b u t t o n }
f i n a l Button b u t t o n c r o p c o n f i r m = ( Button ) }) ;
f i n d V i e w B y I d (R . i d . b u t t o n c r o p c o n f i r m ) ; }
b u t t o n c r o p c o n f i r m . s e t O n C l i c k L i s t e n e r ( new }
View . O n C l i c k L i s t e n e r ( ) {

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Activity\_Main.java

/∗ i m p o r t a n d r o i d . s u p p o r t . v4 . app .
∗ C o p y r i g h t 2016 Anter Aaron M. C u s t o d i o FragmentTransaction ;
∗ i m p o r t a n d r o i d . s u p p o r t . v7 . app . A c t i o n B a r ;
∗ L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n i m p o r t a n d r o i d . o s . Bundle ;
2.0 ( the ” License ”) ; i m p o r t a n d r o i d . s u p p o r t . v7 . app .
∗ you may n o t u s e t h i s f i l e e x c e p t i n AppCompatActivity ;
compliance with the L i c e n s e . i m p o r t a n d r o i d . s u p p o r t . v7 . w i d g e t . T o o l b a r ;
∗ You may o b t a i n a copy o f t h e L i c e n s e a t i m p o r t a n d r o i d . u t i l . Log ;
∗ i m p o r t a n d r o i d . v i e w . Menu ;
∗ h t t p : / /www. a p a c h e . o r g / l i c e n s e s /LICENSE i m p o r t a n d r o i d . v i e w . MenuItem ;
−2.0 i m p o r t a n d r o i d . v i e w . View ;
∗ i m p o r t a n d r o i d . w i d g e t . Button ;
∗ U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d i m p o r t a n d r o i d . w i d g e t . ImageView ;
to in writing , software i m p o r t a n d r o i d . w i d g e t . T o a st ;
∗ d i s t r i b u t e d under the L i c e n s e i s i m p o r t com . j o a n z a p a t a . p d f v i e w . PDFView ;
d i s t r i b u t e d on an ”AS I S ” BASIS , i m p o r t com . p o l i t e s . a n d r o i d . GestureImageView ;
∗ WITHOUT WARRANTIES OR CONDITIONS OF ANY import java . i o . F i l e ;
KIND , e i t h e r e x p r e s s o r i m p l i e d . i m p o r t j a v a . n e t . MalformedURLException ;
∗ See the L i c e n s e f o r the s p e c i f i c language import k a l o e r . f i l e p i c k e r . F i l e P i c k e r A c t i v i t y ;
g o v e r n i n g p e r m i s s i o n s and
∗ l i m i t a t i o n s under the L i c e n s e . /∗ ∗
∗/ ∗ Main A c t i v i t y f o r T e s s 2 S p e e c h .
∗ I n c l u d e s d i s p l a y i n g o f Fragments , T o o l b a r ,
package anteraaron . t e s s 2 s p e e c h ; Logo , c a l l i n g I n t e n t s , I n t e n t R e s u l t s
etc .
import android . app . A c t i v i t y ; ∗
import android . content . Intent ; ∗ @author Anter Aaron M. C u s t o d i o
import android . g r a p h i c s . Bitmap ; ∗ U n i v e r s i t y o f the P h i l i p p i n e s Manila
import android . media . AudioManager ; ∗ B . S . Computer S c i e n c e S t u d e n t
import android . net . Uri ; ∗ @since 2 0 1 6 . 3 . 2 2
import android . o s . AsyncTask ; ∗/
import android . o s . S ys t em C lo c k ; public c l a s s Activity Main extends

104
AppCompatActivity { // I n i t i a l i z e v a r i a b l e s
/∗ ∗ s t a t e = S t a t e . IS CANVAS ;
∗ An i n n e r c l a s s t h a t c o n t a i n s C o n s t a n t s this . lastClickTime = 0;
for activity Results .
∗/ // a l w a y s c h a n g e t h e mu s i c volume when
public static f i n a l class Activity Result { p r e s s i n g button
public static f i n a l int s e t V o l u m e C o n t r o l S t r e a m ( AudioManager .
CAPTURE IMAGE ACTIVITY REQUEST CODE = STREAM MUSIC) ;
1 0 0 ; // R e q u e s t c o d e f o r c a p t u r e image
public static f i n a l int // Cast UIs
BROWSE IMAGE ACTIVITY REQUEST CODE = 2 0 0 ; createUI () ;
// R e q u e s t c o d e f o r b r o w s e image }
public static f i n a l int
BROWSE MULTIPLE IMAGE ACTIVITY REQUEST CODE @O verr ide
= 2 0 1 ; // R e q u e s t c o d e f o r b r o w s e public void onStart () {
m u l t i p l e image // c o n s t r u c t l i b r a r i e s
public static f i n a l int new L i b r a r i e s ( t h i s ) ;
BROWSE PDF ACTIVITY REQUEST CODE = 2 0 2 ; super . onStart () ;
// R e q u e s t c o d e f o r b r o w s e p d f }
public static f i n a l int
BROWSE PDF CONVERT TO IMAGE ACTIVITY REQUEST CODE
@O verr ide
= 2 0 3 ; // R e q u e s t c o d e f o r b r o w s e p d f p u b l i c b o o l e a n onCreateOptionsMenu ( f i n a l Menu
public static f i n a l int menu ) {
BROWSE EPUB ACTIVITY REQUEST CODE = 2 0 4 ; // I n f l a t e t h e menu ; t h i s adds i t e m s t o t h e
// R e q u e s t c o d e f o r b r o w s e p d f a c t i o n bar i f i t i s p r e s e n t .
public static f i n a l int g e t M e n u I n f l a t e r ( ) . i n f l a t e (R . menu . menu main ,
ROTATE BITMAP ACTIVITY REQUEST CODE = menu ) ;
3 0 0 ; // R e q u e s t c o d e f o r r o t a t e image f i n a l MenuItem s a v e T e x t = menu . f i n d I t e m (R . i d
public static f i n a l int . saveText ) ;
CROP IMAGE ACTIVITY REQUEST CODE = 4 0 0 ; f i n a l MenuItem s a v e P d f = menu . f i n d I t e m (R . i d .
// R e q u e s t c o d e f o r c r o p image savePdf ) ;
} f i n a l MenuItem s a v e A u d i o = menu . f i n d I t e m (R .
i d . saveAudio ) ;
/∗ ∗
∗ An i n n e r c l a s s t h a t c o n t a i n s C o n s t a n t s if ( s t a t e == S t a t e . IS CANVAS | | s t a t e ==
for Application States . S t a t e . IS IMAGE | | s t a t e == S t a t e . IS PDF
∗/ | | s t a t e == S t a t e . IS EPUB ) {
public s t a t i c f i n a l c l a s s State { // D i s a b l e s a v e a s . t x t menu
p u b l i c s t a t i c f i n a l i n t IS CANVAS = 0 ; // saveText . setEnabled ( f a l s e ) ;
Application i s d i s p l a y i n g the converted s a v e T e x t . s e t T i t l e ( ” Save a s . t x t ( C o n v e r t
text . text f i r s t )”) ;
p u b l i c s t a t i c f i n a l i n t IS IMAGE = 1 ; // // D i s a b l e s a v e a s . p d f menu
A p p l i c a t i o n i s d i s p l a y i n g t h e i n p u t image savePdf . setEnabled ( f a l s e ) ;
p u b l i c s t a t i c f i n a l i n t IS PDF = 2 ; // s a v e P d f . s e t T i t l e ( ” Save a s . p d f ( C o n v e r t
A p p l i c a t i o n i s d i s p l a y i n g PDF text f i r s t )”) ;
p u b l i c s t a t i c f i n a l i n t IS EPUB = 3 ; // // D i s a b l e s a v e a u d i o menu
A p p l i c a t i o n i s d i s p l a y i n g EPUB saveAudio . setEnabled ( f a l s e ) ;
p u b l i c s t a t i c f i n a l i n t IS TEXT FROM CANVAS s a v e A u d i o . s e t T i t l e ( ” Save Audio ( C o n v e r t
= 4 ; // A p p l i c a t i o n i s d i s p l a y i n g t h e text f i r s t )”) ;
c o n v e r t e d t e x t from c a n v a s . } else {
p u b l i c s t a t i c f i n a l i n t IS TEXT FROM IMAGE = // E n a b l e s a v e a s . t x t menu
5 ; // A p p l i c a t i o n i s d i s p l a y i n g t h e saveText . setEnabled ( t ru e ) ;
c o n v e r t e d t e x t from image f r a g m e n t . s a v e T e x t . s e t T i t l e ( ” Save a s . t x t ” ) ;
p u b l i c s t a t i c f i n a l i n t IS TEXT FROM PDF = // E n a b l e s a v e a s . p d f menu
6 ; // A p p l i c a t i o n i s d i s p l a y i n g t h e savePdf . setEnabled ( true ) ;
c o n v e r t e d t e x t from PDF f r a g m e n t . s a v e P d f . s e t T i t l e ( ” Save a s . p d f ” ) ;
p u b l i c s t a t i c f i n a l i n t IS TEXT FROM EPUB = // E n a b l e s a v e a u d i o menu
7 ; // A p p l i c a t i o n i s d i s p l a y i n g t h e saveAudio . setEnabled ( t r u e ) ;
c o n v e r t e d t e x t from Epub f r a g m e n t . s a v e A u d i o . s e t T i t l e ( ” Save Audio ” ) ;
} }
return true ;
public static Button b u t t o n p l a y , button text }
;
@O verr ide
p r i v a t e AsyncTask<Boolean , Boolean , Boolean> public boolean onOptionsItemSelected ( f i n a l
save ; MenuItem i t e m ) {
p r i v a t e AsyncTask<S t r i n g , Void , Void> s p e a k ; /∗ Handle a c t i o n b a r i t e m c l i c k s h e r e . The
a c t i o n bar w i l l
p r i v a t e s t a t i c Uri imageUri , pdfUri , epubUri ; a u t o m a t i c a l l y h a n d l e c l i c k s on t h e
// Image , PDF or , Epub u r i b e i n g Home/Up button , s o l o n g
displayed a s you s p e c i f y a p a r e n t a c t i v i t y i n
p u b l i c s t a t i c i n t s t a t e ; // D e t e r m i n e t h e A n d r o i d M a n i f e s t . xml . ∗/
c u r r e n t s t a t e o r Fragment d i s p l a y e d i n
t h e App // Stop t e x t t o s p e e c h and t e s s e r a c t
L i b r a r i e s . t t s . stop () ;
p r i v a t e l o n g l a s t C l i c k T i m e ; // v a r i a b l e that Libraries . tesseract . clear () ;
s a v e s the l a s t c l i c k e d time . b u t t o n p l a y . s e t T e x t (R . s t r i n g . b u t t o n p l a y ) ;

@O verr ide final int i d = item . getItemId ( ) ;


p r o t e c t e d v o i d o n C r e a t e ( f i n a l Bundle
savedInstanceState ) { switch ( id ) {
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; // T o o l b a r camera i c o n on C l i c k
s e t C o n t e n t V i e w (R . l a y o u t . a c t i v i t y m a i n ) ; c a s e R . i d . camera : {
// i f camera b u t t o n i s c l i c k e d
f i n a l Toolbar t o o l b a r = ( Toolbar ) f i n a l I n t e n t C a m e r a camera = new
f i n d V i e w B y I d (R . i d . t o o l b a r ) ; Intent Camera ( t h i s ) ;
toolbar . setNavigationIcon ( null ) ; f i n a l I n t e n t i n t e n t = camera . t a k e P i c t u r e ( )
setSupportActionBar ( toolbar ) ; ;

// l o g o i n a c t i o n b a r i f ( i n t e n t != n u l l ) {
f i n a l A c t i o n B a r ab = g e t S u p p o r t A c t i o n B a r ( ) ; // S t a r t i n t e n t a c t i v i t y f o r camera
i f ( ab != n u l l ) { startActivityForResult ( intent ,
ab . s e t L o g o (R . mipmap . l o g o ) ; Activity Result .
ab . s e t D i s p l a y U s e L o g o E n a b l e d ( t r u e ) ; CAPTURE IMAGE ACTIVITY REQUEST CODE) ;
// remove back b u t t o n i n t o o l b a r } else {
ab . setDisplayHomeAsUpEnabled ( f a l s e ) ; // E r r o r n o t i f i c a t i o n
ab . setHomeButtonEnabled ( f a l s e ) ; T o as t . makeText ( t h i s , ”An e r r o r h a s
} o c c u r e d ” , To a s t . LENGTH SHORT) . show ( ) ;
}

105
break ; } else {
} // E r r o r n o t i f i c a t i o n
T o as t . makeText ( t h i s , ”An e r r o r h a s
// T o o l b a r b r o w s e image i c o n on C l i c k o c c u r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ;
c a s e R. i d . browse : { }
// I f b r o w s e image b u t t o n i s c l i c k e d break ;
f i n a l Intent intent = Intent BrowseFiles . }
browseImage ( ) ;
i f ( i n t e n t != n u l l ) { // T o o l b a r C o n v e r t PDF t o image on c l i c k
// S t a r t i n t e n t a c t i v i t y f o r b r o w s i n g f i l e c a s e R . i d . pdfToImage : {
startActivityForResult ( Intent . // Choose which PDF t o c o n v e r t
c r e a t e C h o o s e r ( i n t e n t , ” Complete a c t i o n f i n a l Intent intent = Intent BrowseFiles .
using ”) , Activity Result . browsePdf ( ) ;
BROWSE IMAGE ACTIVITY REQUEST CODE) ; i f ( i n t e n t != n u l l ) {
} else { // S t a r t i n t e n t a c t i v i t y f o r b r o w s i n g p d f
// E r r o r n o t i f i c a t i o n startActivityForResult ( Intent .
T o as t . makeText ( t h i s , ”An e r r o r h a s c r e a t e C h o o s e r ( i n t e n t , ” Complete a c t i o n
o c c u r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ; using ”) , Activity Result .
} BROWSE PDF CONVERT TO IMAGE ACTIVITY REQUEST CODE
break ; );
} } else {
// E r r o r n o t i f i c a t i o n
// T o o l b a r b r o w s e p d f on C l i c k T o as t . makeText ( t h i s , ”An e r r o r h a s
c a s e R. i d . browsePdf : { o c c u r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ;
// I f b r o w s e PDF b u t t o n i s c l i c k e d }
f i n a l Intent intent = Intent BrowseFiles . break ;
browsePdf ( ) ; }
i f ( i n t e n t != n u l l ) {
// S t a r t i n t e n t a c t i v i t y f o r b r o w s i n g p d f // T o o l b a r S e t t i n g s on c l i c k
startActivityForResult ( Intent . case R. id . s e t t i n g s : {
c r e a t e C h o o s e r ( i n t e n t , ” Complete a c t i o n // S t a r t t h e p r e f e r e n c e s c r e e n
using ”) , Activity Result . f i n a l I n t e n t i n t e n t = new I n t e n t ( t h i s ,
BROWSE PDF ACTIVITY REQUEST CODE) ; Activity Settings . class ) ;
} else { s t a r t A c t i v i t y F o r R e s u l t ( intent , 0) ;
// E r r o r n o t i f i c a t i o n break ;
T o as t . makeText ( t h i s , ”An e r r o r h a s }
o c c u r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ;
} // T o o l b a r E x i t on C l i c k
break ; case R. id . e x i t : {
} // E x i t a c t i v i t y
finish () ;
// T o o l b a r b r o w s e epub on C l i c k break ;
c a s e R . i d . browseEpub : { }
// I f b r o w s e epub b u t t o n i s c l i c k e d
f i n a l Intent intent = Intent BrowseFiles . // d e f a u l t
browseEpub ( ) ; default : {
i f ( i n t e n t != n u l l ) { break ;
// S t a r t i n t e n t a c t i v i t y f o r b r o w s i n g p d f }
startActivityForResult ( Intent .
c r e a t e C h o o s e r ( i n t e n t , ” Complete a c t i o n }
using ”) , Activity Result . return super . onOptionsItemSelected ( item ) ;
BROWSE EPUB ACTIVITY REQUEST CODE) ; }
} else {
// E r r o r n o t i f i c a t i o n /∗ ∗
T o as t . makeText ( t h i s , ”An e r r o r h a s ∗ C r e a t e UI f o r t h e A p p l i c a t i o n .
o c c u r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ; ∗/
} public void createUI () {
break ; // C r e a t e imageView f o r PDFs .
} L i b r a r i e s . pdfView = ( PDFView ) f i n d V i e w B y I d (R
. i d . pdfView ) ;
// T o o l b a r s a v e a s . t x t on c l i c k // C r e a t e imageView f o r I n p u t I m a g e s .
case R. id . saveText : { L i b r a r i e s . imageView = ( GestureImageView )
// Launch SaveText AsyncTask f i n d V i e w B y I d (R . i d . imageView ) ;
new T a s k S a v e T e x t ( t h i s ) ;
break ; // I f c o n v e r t e d t e x t b u t t o n i s p r e s s e d .
} b u t t o n t e x t = ( Button ) f i n d V i e w B y I d (R . i d .
button text ) ;
// T o o l b a r s a v e a u d i o on c l i c k b u t t o n t e x t . s e t O n C l i c k L i s t e n e r ( new View .
c a s e R. i d . saveAudio : { OnClickListener () {
// Launch SaveAudio AsyncTask @O verr ide
new T a s k S a v e A u d i o ( t h i s ) ; p u b l i c v o i d o n C l i c k ( View v ) {
break ;
} // d o u b l e −c l i c k i n g p r e v e n t i o n , u s i n g
t h r e s h o l d o f 1000 ms
// T o o l b a r s a v e PDF on c l i c k i f ( S ys t em C lo c k . e l a p s e d R e a l t i m e ( ) −
case R. id . savePdf : { lastClickTime < 1000) {
// Launch SavePdf AsyncTask return ;
new T a s k S a v e P d f ( t h i s ) ; }
// u s e f r a g m e n t p d f a s Fragment l a s t C l i c k T i m e = S y st e mC l oc k .
s t a t e = S t a t e . IS PDF ; elapsedRealtime () ;
// D i s p l a y PDFViewer Fragment
displayFragment ( ) ; // Check i f t h e u s e r wants t o r e t a i n t h e
break ; previous converted text .
} i f ( b u t t o n t e x t . getText ( ) . e q u al s (
g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g .
// T o o l b a r C o n v e r t image t o s e a r c h a b l e PDF button text ) ) ) {
on c l i c k F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
c a s e R . i d . imageToPdf : {
// U s e r h a s an o p t i o n t o c h o o s e m u l t i p l e switch ( state ) {
i m a g e s and c o m p i l e them t o one p d f // C o n v e r t image t o t e x t , but do n o t p l a y
f i n a l Intent intent = Intent BrowseFiles . .
browseMultipleImages () ; c a s e S t a t e . IS IMAGE : {
i f ( i n t e n t != n u l l ) { new ToText ( A c t i v i t y M a i n . t h i s ) . e x e c u t e (
// S t a r t i n t e n t a c t i v i t y f o r b r o w s i n g f i l e imageUri , f a l s e ) ;
startActivityForResult ( Intent . break ;
c r e a t e C h o o s e r ( i n t e n t , ” Complete a c t i o n }
using ”) , Activity Result .
BROWSE MULTIPLE IMAGE ACTIVITY REQUEST CODE // I n PDF Fragment
); c a s e S t a t e . IS PDF : {

106
L i b r a r i e s . pdfToText ( f a l s e ) ; }
break ; l a s t C l i c k T i m e = S y st e mC l oc k .
} elapsedRealtime () ;

// I n EPUB Fragment // C a n c e l s p e a k i n g when back b u t t o n i s


c a s e S t a t e . IS EPUB : { pressed .
new Task WebViewToText ( A c t i v i t y M a i n . i f ( s a v e != n u l l ) {
t h i s ) . execute ( f a l s e ) ; save . cancel ( true ) ;
break ; } e l s e i f ( s p e a k != n u l l ) {
} speak . c a n c e l ( true ) ;
}
// I n Canvas L i b r a r i e s . t t s . stop () ;
c a s e S t a t e . IS CANVAS : { Libraries . tesseract . clear () ;
// Save t e x t i n c a n v a s but do n o t p l a y . b u t t o n p l a y . s e t T e x t (R . s t r i n g . b u t t o n p l a y ) ;
new Task SaveCanvas ( A c t i v i t y M a i n . t h i s )
. execute ( f a l s e ) ; // s e t s t a t e
break ; s t a t e = S t a t e . IS CANVAS ;
}
L i b r a r i e s . imageView . s e t I m a g e D r a w a b l e ( n u l l )
default : ;
break ; displayFragment ( ) ;
} // Check i f t h e u s e r wants t o r e t a i n t h e
previous converted text .
// S e t c u r r e n t s t a t e F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
switch ( state ) { }
c a s e S t a t e . IS CANVAS : }) ;
s t a t e = S t a t e . IS TEXT FROM CANVAS ;
break ; // I f p l a y b u t t o n i s p r e s s e d
c a s e S t a t e . IS IMAGE : b u t t o n p l a y = ( Button ) f i n d V i e w B y I d (R . i d .
s t a t e = S t a t e . IS TEXT FROM IMAGE ; button play ) ;
break ; b u t t o n p l a y . s e t O n C l i c k L i s t e n e r ( new View .
c a s e S t a t e . IS PDF : OnClickListener () {
s t a t e = S t a t e . IS TEXT FROM PDF ; @O verr ide
break ; p u b l i c v o i d o n C l i c k ( View v ) {
c a s e S t a t e . IS EPUB :
s t a t e = S t a t e . IS TEXT FROM EPUB ; // a l l o w d o u b l e c l i c k on p l a y .
break ; l a s t C l i c k T i m e = S y st e mC l oc k .
default : elapsedRealtime () ;
break ;
} switch ( state ) {
// D i s p l a y Text Fragment // P l a y o n l y i f i t i s i n DrawingCanvas
displayFragment ( ) ; mode .
c a s e S t a t e . IS CANVAS : {
button text . // I f u s e r i s on Canvas .
setCompoundDrawablesWithIntrinsicBounds F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
( 0 , R . mipmap . i c a c t i o n e y e c l o s e d , 0 , 0 ) ; i f ( button play . getText ( ) . e q ua l s (
b u t t o n t e x t . s e t T e x t (R . s t r i n g . g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g .
button text back ) ; button play ) ) ) {
Fragment ConvertedText . e d i t T e x t . s a v e = new Task SaveCanvas (
requestFocus () ; Activity Main . t h i s ) ;
save . execute ( true ) ;
} else { } else {
// S e t c u r r e n t s t a t e save . cancel ( true ) ;
switch ( state ) { L i b r a r i e s . t t s . stop () ;
c a s e S t a t e . IS TEXT FROM CANVAS : Libraries . tesseract . clear () ;
s t a t e = S t a t e . IS CANVAS ;
break ; //Re−e n a b l e b u t t o n s
c a s e S t a t e . IS TEXT FROM IMAGE : Activity Main . button text . setEnabled (
s t a t e = S t a t e . IS IMAGE ; true ) ;
break ; Activity Main . button text . setClickable (
c a s e S t a t e . IS TEXT FROM PDF : true ) ;
s t a t e = S t a t e . IS PDF ; button play .
break ; setCompoundDrawablesWithIntrinsicBounds
c a s e S t a t e . IS TEXT FROM EPUB : ( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 ,
s t a t e = S t a t e . IS EPUB ; 0) ;
break ; b u t t o n p l a y . s e t T e x t (R . s t r i n g .
default : button play ) ;
break ; }
} break ;
// D i s p l a y Canvas Fragment / I n p u t I m a g e }
Fragment .
displayFragment ( ) ; // I f u s e r i s on d i s p l a y p d f f r a g m e n t .
button text . c a s e S t a t e . IS PDF : {
setCompoundDrawablesWithIntrinsicBounds F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
( 0 , R . mipmap . i c a c t i o n e y e o p e n , 0 , 0 ) ; i f ( button play . getText ( ) . e q ua l s (
b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g .
; button play ) ) ) {
Fragment DrawingCanvas . drawingView . L i b r a r i e s . pdfToText ( t r u e ) ;
requestFocus () ; } else {
} L i b r a r i e s . t t s . stop () ;
// r e f r e s h a c t i v i t y menu Libraries . tesseract . clear () ;
invalidateOptionsMenu () ;
} //Re−e n a b l e b u t t o n s
}) ; Activity Main . button text . setEnabled (
true ) ;
// I f back b u t t o n i n p d f i s p r e s s e d . Activity Main . button text . setClickable (
F r a g m e n t P d f V i e w e r . b u t t o n p d f b a c k = ( Button true ) ;
) f i n d V i e w B y I d (R . i d . b u t t o n p d f b a c k ) ; button play .
Fragment PdfViewer . b u t t o n p d f b a c k . setCompoundDrawablesWithIntrinsicBounds
s e t O n C l i c k L i s t e n e r ( new View . ( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 ,
OnClickListener () { 0) ;
@O verr ide b u t t o n p l a y . s e t T e x t (R . s t r i n g .
p u b l i c v o i d o n C l i c k ( View v ) { button play ) ;
}
// d o u b l e −c l i c k i n g p r e v e n t i o n , u s i n g break ;
t h r e s h o l d o f 1000 ms }
i f ( S ys t em C lo c k . e l a p s e d R e a l t i m e ( ) −
lastClickTime < 1000) { // I f t h e u s e r i s on C o n v e r t Image .
return ; case S t a t e . IS IMAGE : {

107
F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
i f ( button play . getText ( ) . e q ua l s ( // C r e a t e i n t e n t t o l a u n c h
g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g . f i n a l I n t e n t i n t e n t = new I n t e n t (
button play ) ) ) { Activity Main . this , Activity Rotate . c l a s s
new ToText ( A c t i v i t y M a i n . t h i s ) . e x e c u t e ( );
imageUri , t r u e ) ; i n t e n t . putExtra ( ” imageUri ” , imageUri ) ;
} else { startActivityForResult ( intent ,
L i b r a r i e s . t t s . stop () ; Activity Result .
Libraries . tesseract . clear () ; ROTATE BITMAP ACTIVITY REQUEST CODE) ;
}
//Re−e n a b l e b u t t o n s }) ;
Activity Main . button text . setEnabled (
true ) ; // I f c r o p b u t t o n i n i n p u t image i s p r e s s e d
Activity Main . button text . setClickable ( Fragment InputImage . b u t t o n c r o p .
true ) ; s e t O n C l i c k L i s t e n e r ( new View .
button play . OnClickListener () {
setCompoundDrawablesWithIntrinsicBounds @O verr ide
( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 , p u b l i c v o i d o n C l i c k ( View v ) {
0) ; // d o u b l e −c l i c k i n g p r e v e n t i o n , u s i n g
b u t t o n p l a y . s e t T e x t (R . s t r i n g . t h r e s h o l d o f 1000 ms
button play ) ; i f ( S ys t em C lo c k . e l a p s e d R e a l t i m e ( ) −
} lastClickTime < 1000) {
break ; return ;
} }
l a s t C l i c k T i m e = S y st e mC l oc k .
// I f t h e u s e r i s on Epub elapsedRealtime () ;
c a s e S t a t e . IS EPUB : {
i f ( button play . getText ( ) . e q ua l s ( // C r e a t e i n t e n t t o l a u n c h
g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g . I n t e n t i n t e n t = new I n t e n t ( A c t i v i t y M a i n .
button play ) ) ) { this , Activity Crop . c l a s s ) ;
new Task WebViewToText ( A c t i v i t y M a i n . i n t e n t . putExtra ( ” imageUri ” , imageUri ) ;
t h i s ) . execute ( true ) ; startActivityForResult ( intent ,
} else { Activity Result .
L i b r a r i e s . t t s . stop () ; CROP IMAGE ACTIVITY REQUEST CODE) ;
Libraries . tesseract . clear () ; }
}) ;
//Re−e n a b l e b u t t o n s
Activity Main . button text . setEnabled ( // I f back b u t t o n i n i n p u t image i s pressed
true ) ; Fragment InputImage . button back .
Activity Main . button text . setClickable ( s e t O n C l i c k L i s t e n e r ( new View .
true ) ; OnClickListener () {
button play . @O verr ide
setCompoundDrawablesWithIntrinsicBounds p u b l i c v o i d o n C l i c k ( View v ) {
( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 ,
0) ; // d o u b l e −c l i c k i n g p r e v e n t i o n , u s i n g
b u t t o n p l a y . s e t T e x t (R . s t r i n g . t h r e s h o l d o f 1000 ms
button play ) ; i f ( S ys t em C lo c k . e l a p s e d R e a l t i m e ( ) −
} lastClickTime < 1000) {
break ; return ;
} }
l a s t C l i c k T i m e = S y st e mC l oc k .
// P l a y d i r e c t l y i f i t ’ s a c o n v e r t e d t e x t elapsedRealtime () ;
fragment .
default : { // C a n c e l s p e a k i n g when back b u t t o n is
i f ( button play . getText ( ) . e q ua l s ( pressed
g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g . i f ( s a v e != n u l l ) {
button play ) ) ) { save . cancel ( true ) ;
s p e a k = new ToSpeech ( ) ; } e l s e i f ( s p e a k != n u l l ) {
speak . e x e c u t e ( Fragment ConvertedText . speak . c a n c e l ( true ) ;
editText . getText ( ) . t o S t r i n g ( ) ) ; }
} else { L i b r a r i e s . t t s . stop () ;
speak . c a n c e l ( true ) ; Libraries . tesseract . clear () ;
L i b r a r i e s . t t s . stop () ;
Libraries . tesseract . clear () ; b u t t o n p l a y . s e t T e x t (R . s t r i n g . b u t t o n p l a y ) ;

//Re−e n a b l e b u t t o n s // s e t s t a t e
Activity Main . button text . setEnabled ( s t a t e = S t a t e . IS CANVAS ;
true ) ;
Activity Main . button text . setClickable ( L i b r a r i e s . imageView . s e t I m a g e D r a w a b l e ( n u l l )
true ) ; ;
button play . displayFragment ( ) ;
setCompoundDrawablesWithIntrinsicBounds // Check i f t h e u s e r wants t o r e t a i n t h e
( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 , previous converted text
0) ; F r a g m e n t C o n v e r t e d T e x t . checkAppend ( ) ;
b u t t o n p l a y . s e t T e x t (R . s t r i n g . }
button play ) ; }) ;
}
break ; // Hide o t h e r f r a g m e n t s . Only show c a n v a s
} fragment
displayFragment ( ) ;
} }
}
}) ; @O verr ide
protected void onSaveInstanceState ( f i n a l
// I f r o t a t e b u t t o n i s p r e s s e d . Bundle s a v e d I n s t a n c e S t a t e ) {
Fragment InputImage . b u t t o n r o t a t e . super . onSaveInstanceState ( savedInstanceState
s e t O n C l i c k L i s t e n e r ( new View . );
OnClickListener () { // Save t h e App ’ s s t a t e when App s t a t e i s
@O verr ide changed .
p u b l i c v o i d o n C l i c k ( View v ) {
if ( D i r e c t o r i e s . imageFromCameraUri != n u l l )
// d o u b l e −c l i c k i n g p r e v e n t i o n , u s i n g {
t h r e s h o l d o f 1000 ms // Save image t a k e n by camera a f t e r r o t a t i o n
i f ( S ys t em C lo c k . e l a p s e d R e a l t i m e ( ) − .
lastClickTime < 1000) { savedInstanceState . putString (”
return ; cameraImageUri ” , D i r e c t o r i e s .
} imageFromCameraUri . t o S t r i n g ( ) ) ;
l a s t C l i c k T i m e = S y st e m Cl o ck . }
elapsedRealtime () ; if ( i m a g e U r i != n u l l && s t a t e == S t a t e .

108
IS IMAGE ) { ) . toURI ( ) . toURL ( ) . t o S t r i n g ( ) + F i l e .
// Save image i n imageView a f t e r r o t a t i o n . s e p a r a t o r + ”OEBPS” + F i l e . s e p a r a t o r ;
savedInstanceState . putParcelable (” } c a t c h ( MalformedURLException e ) {
imageDisplayed ” , imageUri ) ; Log . e ( ” U r l e r r o r ” , ” S t a c k t r a c e : ” , e ) ;
} e l s e i f ( p d f U r i != n u l l && s t a t e == S t a t e . }
IS PDF ) { Fragment EPubViewer . webView .
// Save PDF i n imageView a f t e r r o t a t i o n . loadDataWithBaseURL ( u r l , htmlContent , ”
savedInstanceState . putParcelable (” t e x t / html ” , ” u t f −8” , n u l l ) ;
pdfDisplayed ” , pdfUri ) ;
} e l s e i f ( e p u b U r i != n u l l && s t a t e == S t a t e // Hide c u r r e n t f r a g m e n t and d i s p l a y
. IS EPUB ) { fragment epub
savedInstanceState . putParcelable (” f i n a l FragmentTransaction f t =
epubDisplayed ” , epubUri ) ; getSupportFragmentManager ( ) .
i f ( getSupportFragmentManager ( ) . beginTransaction () ;
findFragmentByTag ( ” f r a g m e n t e p u b ” ) . f t . h i d e ( getSupportFragmentManager ( ) .
isVisible () ) { findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
s a v e d I n s t a n c e S t a t e . p u t S t r i n g ( ” htmlContent ” f t . show ( getSupportFragmentManager ( ) .
, Fragment EPubViewer TOC . h t m l C o n t e n t ) ; findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
} f t . commit ( ) ;
} }
// Save c u r r e n t s t a t e o f f r a g m e n t s a f t e r }
rotation . }
savedInstanceState . putInt ( ” state ” , state ) ;
// Save t e x t s i n EditTextView a f t e r r o t a t i o n . @O verr ide
savedInstanceState . putString ( ” editText ” , protected void onActivityResult ( f i n a l i n t
Fragment ConvertedText . e d i t T e x t . getText ( ) requestCode , f i n a l i n t resultCode , f i n a l
. toString () ) ; I n t e n t data ) {
super . o n A c t i v i t y R e s u l t ( requestCode ,
} resultCode , data ) ;

@SuppressWarnings ( ” C o n s t a n t C o n d i t i o n s ” ) switch ( requestCode ) {


@O verr ide // R e s u l t from Camera A c t i v i t y .
protected void onRestoreInstanceState ( f i n a l case Activity Result .
Bundle s a v e d I n s t a n c e S t a t e ) { CAPTURE IMAGE ACTIVITY REQUEST CODE : {
// R e s t o r e t h e App ’ s s t a t e when App s t a t e i s i f ( r e s u l t C o d e == RESULT OK) {
changed . // Use f r a g m e n t i m a g e a s Fragment .
super . onRestoreInstanceState ( s t a t e = S t a t e . IS IMAGE ;
savedInstanceState ) ; // D i s p l a y I n p u t I m a g e .
i f ( savedInstanceState . containsKey ( ” s t a t e ” ) ) displayFragment ( ) ;
{ // Put image i n I n p u t I m a g e f r a g m e n t .
// R e s t o r e s t a t e o f f r a g m e n t s a f t e r r o t a t i o n i m a g e U r i = D i r e c t o r i e s . imageFromCameraUri
. ;
state = savedInstanceState . getInt (” state ”) ; setImage ( ) ;
displayFragment ( ) ; L i b r a r i e s . galleryAddPic ( imageUri ) ;
} // Image c a p t u r e d and s a v e d on t h e
i f ( savedInstanceState . containsKey ( ” directory .
cameraImageUri ” ) ) { T o as t . makeText ( t h i s , ” Image s a v e d t o : ” +
// R e s t o r e image t a k e n by camera a f t e r i m a g e U r i . g e t P a t h ( ) , T o as t . LENGTH LONG) .
rotation show ( ) ;
D i r e c t o r i e s . imageFromCameraUri = U r i . p a r s e ( } e l s e i f ( r e s u l t C o d e == RESULT CANCELED)
savedInstanceState . getString (” {
cameraImageUri ” ) ) ; // Image c a p t u r e c a n c e l l e d by t h e u s e r .
} T o as t . makeText ( t h i s , ” Image c a p t u r e
i f ( savedInstanceState . containsKey ( ” editText c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ;
”) ) { } else {
// R e s t o r e t e x t i n EditTextView a f t e r //An e r r o r h a s o c c u r e d d u r i n g s a v i n g .
rotation T o as t . makeText ( t h i s , ”An e r r o r h a s
Fragment ConvertedText . e d i t T e x t . setText ( o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ;
savedInstanceState . getString ( ” editText ” ) ) }
; break ;
} }
i f ( savedInstanceState . containsKey ( ”
i m a g e D i s p l a y e d ” ) && s t a t e == S t a t e . // R e s u l t from b r o w s e image .
IS IMAGE ) { case Activity Result .
// R e s t o r e image i n imageView a f t e r r o t a t i o n BROWSE IMAGE ACTIVITY REQUEST CODE : {
imageUri = s a v e d I n s t a n c e S t a t e . g e t P a r c e l a b l e i f ( r e s u l t C o d e == RESULT OK) {
( ” imageDisplayed ” ) ;
setImage ( ) ; i f ( d a t a . g e t D a t a ( ) == n u l l && d a t a .
} e l s e i f ( savedInstanceState . containsKey ( ” hasExtra ( F i l e P i c k e r A c t i v i t y .
i m a g e D i s p l a y e d ” ) && s t a t e == S t a t e . IS PDF EXTRA FILE PATH) ) {
) { // I f b u i l t −i n f i l e b r o w s e r i s u s e d (
// R e s t o r e PDF i n imageView a f t e r r o t a t i o n a n d r o i d − f i l e −p i c k e r a c t i v i t y ) .
pdfUri = savedInstanceState . getParcelable ( ” i m a g e U r i = U r i . f r o m F i l e ( new F i l e ( d a t a .
pdfDisplayed ” ) ; getStringExtra ( FilePickerActivity .
L i b r a r i e s . displayPdf ( pdfUri ) ; EXTRA FILE PATH) ) ) ;
} e l s e i f ( savedInstanceState . containsKey ( ” } else {
e p u b D i s p l a y e d ” ) && s t a t e == S t a t e . IS EPUB // I f o t h e r f i l e b r o w s e r s a r e u s e d .
) { imageUri = data . getData ( ) ;
epubUri = s a v e d I n s t a n c e S t a t e . g e t P a r c e l a b l e ( }
” epubDisplayed ” ) ;
// R e c r e a t e EPUB t a b l e o f c o n t e n t s // Check i f i m a g e U r i i s n o t n u l l and h a s
f i n a l Fragment EPubViewer TOC f r a g m e n t = ( p r o p e r image f o r m a t , r e t u r n e r r o r n o t i c e
Fragment EPubViewer TOC ) i f i t i s n u l l o r i n wrong f o r m a t .
getSupportFragmentManager ( ) . i f ( i m a g e U r i != n u l l &&
findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ; I n t e n t B r o w s e F i l e s . checkImageExtension (
f r a g m e n t . c r e a t e A d a p t e r ( epubUri , D i r e c t o r i e s t h i s , imageUri ) ) {
. EPUB CACHE DIR) ; // Use f r a g m e n t i m a g e a s Fragment .
s t a t e = S t a t e . IS IMAGE ;
// D i s p l a y webView // D i s p l a y I n p u t I m a g e .
i f ( savedInstanceState . containsKey ( ” displayFragment ( ) ;
htmlContent ” ) ) { // S e t image t o imageView
f i n a l S t r i n g htmlContent = setImage ( ) ;
s a v e d I n s t a n c e S t a t e . g e t S t r i n g ( ” htmlContent } else {
”) ; T oa s t . makeText ( t h i s , ” S e l e c t an image
w i t h t h e a p p r o p r i a t e f o r m a t . ” , T o a st .
// C o n v e r t EPUB CACHE DIR t o URL s t r i n g LENGTH LONG) . show ( ) ;
String url = null ; }
try {
u r l = new F i l e ( D i r e c t o r i e s . EPUB CACHE DIR } else if ( r e s u l t C o d e == RESULT CANCELED)

109
{ }
// Image c a p t u r e c a n c e l l e d by t h e u s e r . } ) . e x e c u t e ( epubUri , D i r e c t o r i e s .
T o as t . makeText ( t h i s , ” Browse Image EPUB CACHE DIR) ;
c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ; } else {
} else { T oa s t . makeText ( t h i s , ” S e l e c t an Epub
//An e r r o r h a s o c c u r e d d u r i n g s a v i n g . w i t h an a p p r o p r i a t e f o r m a t . ” , To a s t .
T o as t . makeText ( t h i s , ”An e r r o r h a s LENGTH LONG) . show ( ) ;
o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ; }
}
break ; } e l s e i f ( r e s u l t C o d e == RESULT CANCELED)
} {
// Image c a p t u r e c a n c e l l e d by t h e u s e r .
// R e s u l t from b r o w s e PDF . T o as t . makeText ( t h i s , ” Browse Epub
case Activity Result . c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ;
BROWSE PDF ACTIVITY REQUEST CODE : { } else {
i f ( r e s u l t C o d e == RESULT OK) { //An e r r o r h a s o c c u r e d d u r i n g s a v i n g .
T o as t . makeText ( t h i s , ”An e r r o r h a s
i f ( d a t a . g e t D a t a ( ) == n u l l && d a t a . o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ;
hasExtra ( F i l e P i c k e r A c t i v i t y . }
EXTRA FILE PATH) ) { break ;
// I f b u i l t −i n f i l e b r o w s e r i s u s e d ( }
a n d r o i d − f i l e −p i c k e r a c t i v i t y ) .
p d f U r i = U r i . f r o m F i l e ( new F i l e ( d a t a . // R e s u l t from r o t a t e bitmap .
getStringExtra ( FilePickerActivity . case Activity Result .
EXTRA FILE PATH) ) ) ; ROTATE BITMAP ACTIVITY REQUEST CODE : {
} else { i f ( r e s u l t C o d e == RESULT OK) {
// I f o t h e r f i l e b r o w s e r s a r e u s e d . // I f r o t a t i n g and s a v i n g i s s u c c e s s f u l ,
pdfUri = data . getData ( ) ; d i s p l a y t h e r o t a t e d image on image v i e w
} imageUri = data . g e t P a r c e l a b l e E x t r a ( ”
// Check i f p d f U r i i s n o t n u l l and h a s imageUri ” ) ;
proper format , r e t u r n e r r o r n o t i c e i f i t setImage ( ) ;
i s n u l l o r i n wrong f o r m a t . } e l s e i f ( r e s u l t C o d e == RESULT CANCELED)
i f ( p d f U r i != n u l l && I n t e n t B r o w s e F i l e s . {
checkPdfExtension ( this , pdfUri ) ) { // Image r o t a t i o n i s c a n c e l l e d
// u s e f r a g m e n t p d f a s Fragment . T o as t . makeText ( t h i s , ” Image r o t a t i o n
s t a t e = S t a t e . IS PDF ; c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ;
// D i s p l a y PDF i n PDFViewer }
L i b r a r i e s . displayPdf ( pdfUri ) ; break ;
// D i s p l a y PDFViewer . }
displayFragment ( ) ;
} else { // R e s u l t from c r o p image .
T oa s t . makeText ( t h i s , ” S e l e c t a PDF w i t h case Activity Result .
an a p p r o p r i a t e f o r m a t . ” , T o a st . CROP IMAGE ACTIVITY REQUEST CODE : {
LENGTH LONG) . show ( ) ; i f ( r e s u l t C o d e == RESULT OK) {
} // I f c r o p p i n g and s a v i n g i s s u c c e s s f u l ,
d i s p l a y t h e c r o p p e d image on image v i e w
} e l s e i f ( r e s u l t C o d e == RESULT CANCELED) imageUri = data . g e t P a r c e l a b l e E x t r a ( ”
{ imageUri ” ) ;
// Image c a p t u r e c a n c e l l e d by t h e u s e r . T o as t . makeText ( A c t i v i t y M a i n . t h i s , ”
T o as t . makeText ( t h i s , ” Browse PDF Cropped image s a v e d t o : ” + i m a g e U r i .
c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ; g e t P a t h ( ) , T o a st . LENGTH LONG) . show ( ) ;
} else { setImage ( ) ;
//An e r r o r h a s o c c u r e d d u r i n g s a v i n g . } e l s e i f ( r e s u l t C o d e == RESULT CANCELED)
T o as t . makeText ( t h i s , ”An e r r o r h a s {
o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ; // Crop p i c t u r e c a n c e l l e d by u s e r
} T o as t . makeText ( t h i s , ” Crop c a n c e l l e d ” ,
break ; T oa s t . LENGTH SHORT) . show ( ) ;
} } else {
//An e r r o r h a s o c c u r e d d u r i n g c r o p
// R e s u l t from b r o w s e Epub . T o as t . makeText ( t h i s , ”An e r r o r h a s
case Activity Result . o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ;
BROWSE EPUB ACTIVITY REQUEST CODE : { }
i f ( r e s u l t C o d e == RESULT OK) { break ;
Fragment EPubViewer . clearWebView ( ) ; }

i f ( d a t a . g e t D a t a ( ) == n u l l && d a t a . // R e s u l t from Image t o PDF


hasExtra ( F i l e P i c k e r A c t i v i t y . case Activity Result .
EXTRA FILE PATH) ) { BROWSE MULTIPLE IMAGE ACTIVITY REQUEST CODE
// I f b u i l t −i n f i l e b r o w s e r i s u s e d ( : {
a n d r o i d − f i l e −p i c k e r a c t i v i t y ) . i f ( r e s u l t C o d e == RESULT OK) {
e p u b U r i = U r i . f r o m F i l e ( new F i l e ( d a t a .
getStringExtra ( FilePickerActivity . // c a l l s a v e PDF c l a s s ( AsyncTask a u t o
EXTRA FILE PATH) ) ) ; execute )
} else { new T a s k S a v e P d f ( t h i s , d a t a ) ;
// I f o t h e r f i l e b r o w s e r s a r e u s e d . // u s e f r a g m e n t p d f a s Fragment
epubUri = data . getData ( ) ; s t a t e = S t a t e . IS PDF ;
}
// D i s p l a y PDFViewer
// Check i f e p u b U r i i s n o t n u l l and h a s displayFragment ( ) ;
proper format , r e t u r n e r r o r n o t i c e i f i t } e l s e i f ( r e s u l t C o d e == RESULT CANCELED)
i s n u l l o r i n wrong f o r m a t . {
i f ( e p u b U r i != n u l l && I n t e n t B r o w s e F i l e s // Image c a p t u r e c a n c e l l e d by t h e u s e r
. checkEpubExtension ( t h i s , epubUri ) ) { T o as t . makeText ( t h i s , ” Browse F i l e
new Task UnzipEpub ( t h i s , new c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ;
Task UnzipEpub . AsyncResponse ( ) { } else {
@O verr ide //An e r r o r h a s o c c u r e d d u r i n g s a v i n g
p u b l i c v o i d p r o c e s s F i n i s h e d ( U r i epubUri T o as t . makeText ( t h i s , ”An e r r o r h a s
, S t r i n g cachePath ) { o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ;
// R e c r e a t e EPUB t a b l e o f c o n t e n t s }
f i n a l Fragment EPubViewer TOC f r a g m e n t break ;
= ( Fragment EPubViewer TOC ) }
getSupportFragmentManager ( ) .
findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ; // R e s u l t from PDF t o Image
f r a g m e n t . c r e a t e A d a p t e r ( epubUri , case Activity Result .
cachePath ) ; BROWSE PDF CONVERT TO IMAGE ACTIVITY REQUEST CODE
// u s e f r a g m e n t e p u b a s Fragment . : {
s t a t e = S t a t e . IS EPUB ; i f ( r e s u l t C o d e == RESULT OK) {
// D i s p l a y EpubViewer .
displayFragment ( ) ; if ( d a t a . g e t D a t a ( ) == n u l l && d a t a .

110
hasExtra ( F i l e P i c k e r A c t i v i t y . findFragmentByTag ( ” f r a g m e n t t e x t ” ) ) ;
EXTRA FILE PATH) ) { f t . h i d e ( getSupportFragmentManager ( ) .
// I f b u i l t −i n f i l e b r o w s e r i s u s e d ( findFragmentByTag ( ” f r a g m e n t i m a g e ” ) ) ;
a n d r o i d − f i l e −p i c k e r a c t i v i t y ) . f t . h i d e ( getSupportFragmentManager ( ) .
p d f U r i = U r i . f r o m F i l e ( new F i l e ( d a t a . findFragmentByTag ( ” f r a g m e n t p d f ” ) ) ;
getStringExtra ( FilePickerActivity . f t . h i d e ( getSupportFragmentManager ( ) .
EXTRA FILE PATH) ) ) ; findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
} else { f t . h i d e ( getSupportFragmentManager ( ) .
// I f o t h e r f i l e b r o w s e r s a r e u s e d . findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
pdfUri = data . getData ( ) ; f t . show ( getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) ;
// Check i f p d f U r i i s n o t n u l l and h a s break ;
proper format , r e t u r n e r r o r n o t i c e i f i t }
i s n u l l o r i n wrong f o r m a t .
i f ( p d f U r i != n u l l && I n t e n t B r o w s e F i l e s . // D i s p l a y i m a g e v i e w e r Fragment
checkPdfExtension ( this , pdfUri ) ) { c a s e S t a t e . IS IMAGE : {
// u s e f r a g m e n t p d f a s Fragment L i b r a r i e s . pdfView . r e c y c l e ( ) ;
s t a t e = S t a t e . IS PDF ; Fragment DrawingCanvas . drawingView .
// c a l l PDF t o Image c l a s s destroyDrawingCache ( ) ;
L i b r a r i e s . pdfToImage ( p d f U r i ) ; Fragment EPubViewer . clearWebView ( ) ;
// D i s p l a y PDFViewer
displayFragment ( ) ; f t . h i d e ( getSupportFragmentManager ( ) .
} else { findFragmentByTag ( ” f r a g m e n t t e x t ” ) ) ;
T oa s t . makeText ( t h i s , ” S e l e c t a PDF w i t h f t . h i d e ( getSupportFragmentManager ( ) .
an a p p r o p r i a t e f o r m a t . ” , T o a st . findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
LENGTH LONG) . show ( ) ; f t . h i d e ( getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t p d f ” ) ) ;
f t . h i d e ( getSupportFragmentManager ( ) .
} e l s e i f ( r e s u l t C o d e == RESULT CANCELED) findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
{ f t . h i d e ( getSupportFragmentManager ( ) .
// Image c a p t u r e c a n c e l l e d by t h e u s e r findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
T o as t . makeText ( t h i s , ” C o n v e r t t o PDF f t . show ( getSupportFragmentManager ( ) .
c a n c e l l e d ” , T o a st . LENGTH SHORT) . show ( ) ; findFragmentByTag ( ” f r a g m e n t i m a g e ” ) ) ;
} else {
//An e r r o r h a s o c c u r e d d u r i n g s a v i n g b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) ;
T o as t . makeText ( t h i s , ”An e r r o r h a s break ;
o c c u r e d ” , To a s t . LENGTH LONG) . show ( ) ; }
}
break ; // D i s p l a y PDFViewer Fragment
} c a s e S t a t e . IS PDF : {
L i b r a r i e s . imageView . s e t R e c y c l e ( t r u e ) ;
default : { L i b r a r i e s . imageView . r e c y c l e ( ) ;
break ; Fragment DrawingCanvas . drawingView .
} destroyDrawingCache ( ) ;
} Fragment EPubViewer . clearWebView ( ) ;

displayFragment ( ) ; f t . h i d e ( getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t t e x t ” ) ) ;
/∗ ∗ f t . h i d e ( getSupportFragmentManager ( ) .
∗ S e t t h e image t o be d i s p l a y e d i n t h e findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
imageView . f t . h i d e ( getSupportFragmentManager ( ) .
∗ T h i s i s n e e d e d t o be a b l e t o d i s p l a y findFragmentByTag ( ” f r a g m e n t i m a g e ” ) ) ;
l a r g e bitmaps without l a g g i n g . f t . h i d e ( getSupportFragmentManager ( ) .
∗/ findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
p r i v a t e void setImage ( ) { f t . h i d e ( getSupportFragmentManager ( ) .
findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
// Save t h e copy o f t h e o r i g i n a l f i l e t o f t . show ( getSupportFragmentManager ( ) .
cache . findFragmentByTag ( ” f r a g m e n t p d f ” ) ) ;
new T a s k F i l e F r o m U r i ( t h i s , ” c a c h e . ” +
I n t e n t B r o w s e F i l e s . getMimeType ( t h i s , b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) ;
i m a g e U r i ) , new T a s k F i l e F r o m U r i . break ;
AsyncResponse ( ) { }
@O verr ide
public void processFinished ( F i l e f i l e ) { // D i s p l a y Epub Fragment
// Reduce t h e d i m e n s i o n & s i z e o f t h e c a s e S t a t e . IS EPUB : {
bitmap copy . L i b r a r i e s . pdfView . r e c y c l e ( ) ;
f i n a l Bitmap image = BitmapLoader . L i b r a r i e s . imageView . s e t R e c y c l e ( t r u e ) ;
decodeSampledBitmap ( f i l e , L i b r a r i e s . L i b r a r i e s . imageView . r e c y c l e ( ) ;
imageView . getWidth ( ) , L i b r a r i e s . imageView
. getHeight () ) ; f t . h i d e ( getSupportFragmentManager ( ) .
// D i s p l a y t h e bitmap copy . findFragmentByTag ( ” f r a g m e n t t e x t ” ) ) ;
L i b r a r i e s . imageView . s e t I m a g e B i t m a p ( image ) ; f t . h i d e ( getSupportFragmentManager ( ) .
L i b r a r i e s . imageView . s e t S c a l e T y p e ( ImageView findFragmentByTag ( ” f r a g m e n t i m a g e ” ) ) ;
. S c a l e T y p e . FIT CENTER) ; f t . h i d e ( getSupportFragmentManager ( ) .
// Change t h e d i s p l a y e d t e x t on b u t t o n t e x t findFragmentByTag ( ” f r a g m e n t p d f ” ) ) ;
b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) ; f t . h i d e ( getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
}) . execute ( imageUri ) ; f t . h i d e ( getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
f t . show ( getSupportFragmentManager ( ) .
/∗ ∗ findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
∗ A c a l l to t h i s f un c ti o n determines
which Fragment w i l l be d i s p l a y e d b u t t o n t e x t . s e t T e x t (R . s t r i n g . b u t t o n t e x t ) ;
b a s e d on t h e App ’ s s t a t e . break ;
∗/ }
p r i v a t e void displayFragment ( ) {
f i n a l FragmentTransaction f t = // D i s p l a y Text Fragment
getSupportFragmentManager ( ) . c a s e S t a t e . IS TEXT FROM CANVAS :
beginTransaction () ; c a s e S t a t e . IS TEXT FROM IMAGE :
switch ( state ) { c a s e S t a t e . IS TEXT FROM PDF :
// D i s p l a y Canvas Fragment c a s e S t a t e . IS TEXT FROM EPUB : {
c a s e S t a t e . IS CANVAS : {
L i b r a r i e s . pdfView . r e c y c l e ( ) ; f t . h i d e ( getSupportFragmentManager ( ) .
L i b r a r i e s . imageView . s e t R e c y c l e ( t r u e ) ; findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
L i b r a r i e s . imageView . r e c y c l e ( ) ; f t . h i d e ( getSupportFragmentManager ( ) .
Fragment EPubViewer . clearWebView ( ) ; findFragmentByTag ( ” f r a g m e n t i m a g e ” ) ) ;
f t . h i d e ( getSupportFragmentManager ( ) .
f t . h i d e ( getSupportFragmentManager ( ) . findFragmentByTag ( ” f r a g m e n t p d f ” ) ) ;

111
f t . h i d e ( getSupportFragmentManager ( ) . s u p e r . onStop ( ) ;
findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ; }
f t . h i d e ( getSupportFragmentManager ( ) .
findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ; @O verr ide
f t . show ( getSupportFragmentManager ( ) . p r o t e c t e d void onDestroy ( ) {
findFragmentByTag ( ” f r a g m e n t t e x t ” ) ) ; super . onDestroy ( ) ;
// Garbage C o l l e c t
b u t t o n t e x t . s e t T e x t (R . s t r i n g . L i b r a r i e s . t t s . stop () ;
button text back ) ; L i b r a r i e s . t t s . shutdown ( ) ;
break ; Libraries . tesseract . clear () ;
} L i b r a r i e s . t e s s e r a c t . end ( ) ;
Fragment DrawingCanvas . drawingView .
default : { destroyDrawingCache ( ) ;
break ; Fragment DrawingCanvas . drawingView .
} invalidate () ;
} L i b r a r i e s . imageView . s e t R e c y c l e ( t r u e ) ;
// commit Fragment c h a n g e s . L i b r a r i e s . imageView . r e c y c l e ( ) ;
f t . commit ( ) ; L i b r a r i e s . pdfView . r e c y c l e ( ) ;
} Fragment EPubViewer . clearWebView ( ) ;
Fragment EPubViewer . webView . d e s t r o y ( ) ;
@O verr ide // D e l e t e epubCache and c a c h e D i r
p r o t e c t e d v o i d onPause ( ) { i f ( isFinishing () ) {
L i b r a r i e s . t t s . stop () ; D i r e c t o r i e s . d e l e t e ( new F i l e ( D i r e c t o r i e s .
s u p e r . onPause ( ) ; EPUB CACHE DIR) ) ;
} D i r e c t o r i e s . d e l e t e ( getCacheDir ( ) ) ;
}
@O verr ide }
p r o t e c t e d v o i d onStop ( ) { }
L i b r a r i e s . t t s . stop () ;
L i b r a r i e s . t t s . shutdown ( ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Activity\_Rotate.java

package anteraaron . t e s s 2 s p e e c h ; f i n a l S t r i n g a n g l e L a b e l = LABEL + ” 0 ” ;


t h i s . t e x t V i e w r o t a t e = ( TextView )
import android . content . I n t e n t ; f i n d V i e w B y I d (R . i d . t e x t V i e w r o t a t e ) ;
i m p o r t a n d r o i d . g r a p h i c s . Bitmap ; t h i s . textView rotate . setText ( angleLabel ) ;
import android . g r a p h i c s . Matrix ;
i m p o r t a n d r o i d . g r a p h i c s . RectF ; // Cast imageView
import android . net . Uri ; t h i s . i m a g e V i e w r o t a t e = ( ImageView )
i m p o r t a n d r o i d . s u p p o r t . v7 . app . f i n d V i e w B y I d (R . i d . i m a g e V i e w r o t a t e ) ;
AppCompatActivity ; setImage ( u r i ) ;
i m p o r t a n d r o i d . o s . Bundle ;
i m p o r t a n d r o i d . v i e w . View ; // Cast s e e k B a r
i m p o r t a n d r o i d . w e b k i t . MimeTypeMap ; f i n a l SeekBar s e e k B a r = ( SeekBar )
i m p o r t a n d r o i d . w i d g e t . Button ; f i n d V i e w B y I d (R . i d . s e e k B a r r o t a t e ) ;
i m p o r t a n d r o i d . w i d g e t . ImageView ; s e e k B a r . setMax (MAX ANGLE) ;
i m p o r t a n d r o i d . w i d g e t . SeekBar ; s e e k B a r . s e t P r o g r e s s (STARTING ANGLE) ;
i m p o r t a n d r o i d . w i d g e t . TextView ; s e e k B a r . s e t O n S e e k B a r C h a n g e L i s t e n e r ( new
SeekBar . O n S e e k B a r C h a n g e L i s t e n e r ( ) {
import java . i o . F i l e ; @O verr ide
p u b l i c v o i d o n P r o g r e s s C h a n g e d ( f i n a l SeekBar
/∗ ∗ seekBar , f i n a l i n t p r o g r e s s , f i n a l
∗ A c t i v i t y f o r R o t a t i n g Images . boolean fromUser ) {
∗ @author Anter Aaron M. C u s t o d i o // The c u r r e n t a n g l e i s c u r r e n t s e e k B a r
∗ @since 2 0 1 6 . 3 . 2 2 p r o g r e s s − 180 ( r e a s o n f o r −180 i n t h e
∗/ c o n s t a n t v a l u e above ) .
public c l a s s Activity Rotate extends angle = progress − 180;
AppCompatActivity { rotateImage ( angle ) ;
}
p r i v a t e s t a t i c f i n a l i n t STARTING ANGLE = @O verr ide
1 8 0 ; // S t a r t i n g a n g l e i s a n g l e − 1 8 0 . p u b l i c v o i d o n S t a r t T r a c k i n g T o u c h ( SeekBar
T h i s i m p l i e s t h a t t h e amount o f s t a r t i n g s e e k B a r ) {}
rotation is 0.
p r i v a t e s t a t i c f i n a l i n t MAX ANGLE = 3 6 0 ; // @O verr ide
360 − 180 = 1 8 0 . T h i s i m p l i e s t h a t t h e p u b l i c v o i d o n S t o p T r a c k i n g T o u c h ( SeekBar
max r o t a t i o n can o n l y be a t −180 t o 1 8 0 . s e e k B a r ) {}
p r i v a t e s t a t i c f i n a l S t r i n g LABEL = ” R o t a t e d }) ;
a n g l e : ” ; // R o t a t i o n v a l u e i n d i c a t o r
// C r e a t e s a v e c a n v a s b u t t o n .
p r i v a t e ImageView i m a g e V i e w r o t a t e ; f i n a l Button b u t t o n r o t a t e s a v e = ( Button )
p r i v a t e TextView t e x t V i e w r o t a t e ; f i n d V i e w B y I d (R . i d . b u t t o n r o t a t e s a v e ) ;
private s t a t i c int angle ; b u t t o n r o t a t e s a v e . s e t O n C l i c k L i s t e n e r ( new
p r i v a t e s t a t i c S t r i n g imagePath , imageName ; View . O n C l i c k L i s t e n e r ( ) {
@O verr ide
@O verr ide p u b l i c v o i d o n C l i c k ( View v ) {
p r o t e c t e d v o i d o n C r e a t e ( f i n a l Bundle // C a l l s an AsyncTask t h a t s a v e s t h e
savedInstanceState ) { r o t a t e d image t o a f i l e .
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; new T a s k S a v e R o t a t e d B i t m a p ( A c t i v i t y R o t a t e
s e t C o n t e n t V i e w (R . l a y o u t . a c t i v i t y r o t a t e ) ; . t h i s , new T a s k S a v e R o t a t e d B i t m a p .
// g e t u r i o f t h e image d i s p l a y e d AsyncResponse ( ) {
f i n a l Uri u r i = g e t I n t e n t ( ) . @O verr ide
g e t P a r c e l a b l e E x t r a ( ” imageUri ” ) ; p u b l i c void p r o c e s s F i n i s h e d ( Uri u r i ) {
// g e t t h e o r i g i n a l name o f t h e image // Return f i l e a f t e r s a v i n g t h e r o t a t e d
imageName = new F i l e ( u r i . g e t P a t h ( ) ) . getName image t o g e t f i l e path .
() ; f i n a l I n t e n t i n t e n t = new I n t e n t ( ) ;
// c r e a t e UI f o r t h i s a c t i v i t y i n t e n t . putExtra ( ” imageUri ” , u r i ) ;
s e t R e s u l t (RESULT OK, i n t e n t ) ;
// S e t initial t e x t on t e x t V i e w imageView rotate . destroyDrawingCache ( ) ;

112
finish () ; // S e t t h e v i e w and d r a w a b l e ’ s bound .
} t h i s . i m a g e V i e w r o t a t e . s e t S c a l e T y p e ( ImageView
} ) . e x e c u t e ( imagePath , a n g l e , imageName ) ; . S c a l e T y p e .MATRIX) ;
} f i n a l RectF d r a w a b l e R e c t = new RectF ( 0 , 0 ,
}) ; t h i s . imageView rotate . getDrawable ( ) .
getBounds ( ) . w i d t h ( ) , t h i s .
// C r e a t e r e s e t b u t t o n . i m a g e V i e w r o t a t e . g e t D r a w a b l e ( ) . getBounds
f i n a l Button b u t t o n r o t a t e r e s e t = ( Button ) () . height () ) ;
f i n d V i e w B y I d (R . i d . b u t t o n r o t a t e r e s e t ) ; f i n a l RectF v i e w R e c t = new RectF ( 0 , 0 , t h i s .
b u t t o n r o t a t e r e s e t . s e t O n C l i c k L i s t e n e r ( new i m a g e V i e w r o t a t e . getWidth ( ) −
View . O n C l i c k L i s t e n e r ( ) { widthAdjustment , t h i s . i m a g e V i e w r o t a t e .
@O verr ide getHeight ( ) − heightAdjustment ) ;
p u b l i c v o i d o n C l i c k ( View v ) {
// R e s e t s t h e a n g l e . R e t u r n s t h e r o t a t i o n // Use M a t r i x f o r r o t a t i o n
o f t h e image t o i t s o r i g i n a l o r i e n t a t i o n . f i n a l M a t r i x m a t r i x = new M a t r i x ( ) ;
angle = 0; m a t r i x . s e t R e c t T o R e c t ( d r a w a b l e R e c t , viewRect ,
seekBar . s e t P r o g r e s s (180) ; M a t r i x . S c a l e T o F i t .CENTER) ;
rotateImage ( angle ) ; matrix . postRotate ( angle , ( t h i s .
} i m a g e V i e w r o t a t e . getWidth ( ) −
}) ; widthAdjustment ) / 2 , ( t h i s .
imageView rotate . getHeight () −
// C r e a t e c a n c e l b u t t o n . heightAdjustment ) / 2) ;
f i n a l Button b u t t o n r o t a t e c a n c e l = ( Button ) matrix . p o s t T r a n s l a t e ( widthAdjustment /2 ,
f i n d V i e w B y I d (R . i d . b u t t o n r o t a t e e x i t ) ; heightAdjustment /2) ;
b u t t o n r o t a t e c a n c e l . s e t O n C l i c k L i s t e n e r ( new t h i s . imageView rotate . setImageMatrix ( matrix )
View . O n C l i c k L i s t e n e r ( ) { ;
@O verr ide
p u b l i c v o i d o n C l i c k ( View v ) { // R e f r e s h t h e image v i e w
// R e t u r n s c a n c e l r e s u l t t o A c t i v i t y M a i n . t h i s . imageView rotate . i n v a l i d a t e () ;
s e t R e s u l t (RESULT CANCELED) ;
finish () ; // Change t h e v a l u e o f r o t a t i o n v a l u e
} indicator .
}) ; f i n a l S t r i n g a n g l e L a b e l = LABEL + a n g l e ;
} t h i s . textView rotate . setText ( angleLabel ) ;
}
/∗ ∗
∗ Method t h a t a c c e p t s a r o t a t i o n v a l u e , /∗ ∗
and r o t a t e t h e image d i s p l a y e d i n ∗ A method t h a t a c c e p t s an u r i , and
i m a g e V i e w r o t a t e and a d j u s t s i t s d i s p l a y s i t to i mageView rotate view
s i z e a c c o r d i n g l y so t h a t the whole .
image i s s t i l l d i s p l a y e d . ∗ @param u r i u r i o f t h e image t h a t w i l l
∗ @param a n g l e a f l o a t v a l u e from −180 t o be d i s p l a y e d i n i m a g e V i e w r o t a t e .
180. ∗ @since 2 0 1 6 . 3 . 2 2
∗ @since 2 0 1 6 . 3 . 2 2 ∗/
∗/ p r i v a t e void setImage ( f i n a l Uri u r i ) {
private void rotateImage ( f i n a l f l o a t angle ) { // Get f i l e e x t e n s i o n o f image from u r i .
f i n a l MimeTypeMap mime = MimeTypeMap .
// Pre−compute some t r i g f u n c t i o n s . getSingleton () ;
f i n a l d o u b l e r a d i a n s = Math . t o R a d i a n s ( a n g l e ) f i n a l S t r i n g e x t e n s i o n = mime .
; getExtensionFromMimeType (
f i n a l d o u b l e s i n = Math . a b s ( Math . s i n ( r a d i a n s g e t C o n t e n t R e s o l v e r ( ) . getType ( u r i ) ) ;
)); // Get r e s i z e d f i l e path from u r i .
f i n a l d o u b l e c o s = Math . a b s ( Math . c o s ( r a d i a n s new T a s k F i l e F r o m U r i ( t h i s , ” c a c h e . ” +
)); e x t e n s i o n , new T a s k F i l e F r o m U r i .
AsyncResponse ( ) {
// F i g u r e o u t t o t a l w i d t h and h e i g h t o f new @O verr ide
bitmap u s i n g t r i g c o m p u t a t i o n s . public void processFinished ( F i l e f i l e ) {
f i n a l f l o a t newWidth = ( f l o a t ) ( t h i s . // D i s p l a y t h e image t o i m a g e V i e w r o t a t e .
i m a g e V i e w r o t a t e . getWidth ( ) ∗ c o s + t h i s . f i n a l Bitmap image = BitmapLoader .
imageView rotate . getHeight () ∗ sin ) ; decodeSampledBitmap ( f i l e ,
f i n a l f l o a t newHeight = ( f l o a t ) ( t h i s . i m a g e V i e w r o t a t e . getWidth ( ) ,
i m a g e V i e w r o t a t e . getWidth ( ) ∗ s i n + t h i s . imageView rotate . getHeight () ) ;
imageView rotate . getHeight () ∗ cos ) ; i m a g e V i e w r o t a t e . s e t I m a g e B i t m a p ( image ) ;
i m a g e V i e w r o t a t e . s e t S c a l e T y p e ( ImageView .
// F i g u r e o u t t h e amount o f a d j u s t m e n t o f S c a l e T y p e . FIT CENTER) ;
imageView t o f i t t h e r o t a t e d bitmap . imagePath = f i l e . g e t A b s o l u t e P a t h ( ) ;
f i n a l f l o a t w i d t h A d j u s t m e n t = ( newWidth − }
t h i s . i m a g e V i e w r o t a t e . getWidth ( ) ) / 2 ; }) . execute ( u r i ) ;
f i n a l f l o a t h e i g h t A d j u s t m e n t = ( newHeight − }
t h i s . imageView rotate . getHeight () ) /2; }

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Activity\_Settings.java

package anteraaron . t e s s 2 s p e e c h ; p u b l i c v o i d o n C r e a t e ( f i n a l Bundle


savedInstanceState ) {
import android . content . I n t e n t ; super . onCreate ( s a v e d I n s t a n c e S t a t e ) ;
i m p o r t a n d r o i d . c o n t e n t . pm . PackageManager ; // c h e c k i f t h e r e i s a b u i l t i n s p e l l −c h e c k e r
i m p o r t a n d r o i d . c o n t e n t . pm . R e s o l v e I n f o ; f i n a l PackageManager pm = g e tP a ck a ge M an a g er
i m p o r t a n d r o i d . o s . Bundle ; () ;
import android . p r e f e r e n c e . P r e f e r e n c e A c t i v i t y ; f i n a l I n t e n t s p e l l = new I n t e n t (
import android . s e r v i c e . t e x t s e r v i c e . S p e l l C h e c k e r S e r v i c e . SERVICE INTERFACE) ;
SpellCheckerService ; f i n a l R e s o l v e I n f o i n f o = pm . r e s o l v e S e r v i c e (
s p e l l , 0) ;
/∗ ∗ // S e t s p e l l C h e c k e r P r e s e n t t o f a l s e i f
∗ Activity for Preferences Settings . s p e l l C h e c k e r i s not p r e s e n t
∗ @author Anter Aaron M. C u s t o d i o s p e l l C h e c k e r P r e s e n t = ( i n f o != n u l l ) ;
∗ @since 2 0 1 6 . 3 . 2 2 getFragmentManager ( ) . b e g i n T r a n s a c t i o n ( ) .
∗/ r e p l a c e ( a n d r o i d . R . i d . c o n t e n t , new
public c l a s s A c t i v i t y S e t t i n g s extends F r a g m e n t S e t t i n g s ( ) ) . commit ( ) ;
PreferenceActivity { }
public s t a t i c boolean spellCheckerPresent ; }
@O verr ide
113
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Activity\_SplashScreen.java

package anteraaron . t e s s 2 s p e e c h ; , i n t which ) {


dialog . cancel () ;
i m p o r t a n d r o i d . app . A l e r t D i a l o g ; finish () ;
import android . content . D i a l o g I n t e r f a c e ; }
import android . content . I n t e n t ; }) ;
i m p o r t a n d r o i d . o s . Bundle ;
import android . os . Handler ; f i n a l AlertDialog dialog = builder . create ()
import android . p r e f e r e n c e . PreferenceManager ; ;
i m p o r t a n d r o i d . s p e e c h . t t s . TextToSpeech ; d i a l o g . show ( ) ;
i m p o r t a n d r o i d . s u p p o r t . v7 . app . }
AppCompatActivity ; }
i m p o r t a n d r o i d . v i e w . WindowManager ;
i m p o r t a n d r o i d . w i d g e t . T o a st ; @O verr ide
import java . i o . F i l e ; protected void onActivityResult ( i n t
requestCode , i n t resultCode , I n t e n t data )
/∗ ∗ {
∗ An A c t i v i t y t h a t d i s p l a y s t h e S p l a s h s c r e e n i f ( r e q u e s t C o d e == CHECK TTS REQUEST CODE) {
and copy t h e r e q u i r e d f i l e s . i f ( r e s u l t C o d e == TextToSpeech . E n g i n e .
∗ @author Anter Aaron M. C u s t o d i o CHECK VOICE DATA PASS) {
∗ @since 2 0 1 6 . 3 . 2 2 // A l l c h e c k s OK. C r e a t e an I n t e n t t h a t
∗/ w i l l s t a r t t h e Main A c t i v i t y a f t e r
public c l a s s Activity SplashScreen extends displaying splash screen .
AppCompatActivity { f i n a l I n t e n t i n t e n t = new I n t e n t (
private static final int Activity SplashScreen . this , Activity Main
SPLASH DISPLAY LENGTH = 6 0 0 ; // s p l a s h . class ) ;
screen display duration . startActivity ( intent ) ;
private static final int finish () ;
CHECK TTS REQUEST CODE = 1 ; // S p l a s h S c r e e n t r a n s i t i o n a n i m a t i o n .
o v e r r i d e P e n d i n g T r a n s i t i o n ( a n d r o i d . R . anim .
@O verr ide f a d e i n , a n d r o i d . R . anim . f a d e o u t ) ;
p r o t e c t e d v o i d o n C r e a t e ( f i n a l Bundle }
savedInstanceState ) { } else {
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; f i n a l I n t e n t i n s t a l l I n t e n t = new I n t e n t ( ) ;
getWindow ( ) . s e t F l a g s ( WindowManager . i n s t a l l I n t e n t . s e t A c t i o n ( TextToSpeech . E n g i n e
LayoutParams . FLAG FULLSCREEN, . ACTION INSTALL TTS DATA) ;
WindowManager . LayoutParams . startActivity ( installIntent ) ;
FLAG FULLSCREEN) ; T o as t . makeText ( t h i s , ”TTS i n s t a l l i n g ” , T o as t
s e t C o n t e n t V i e w (R . l a y o u t . s p l a s h s c r e e n ) ; . LENGTH LONG) . show ( ) ;
}
// S e t d e f a u l t p r e f e r e n c e s }
PreferenceManager . s e t D e f a u l t V a l u e s ( t h i s , R.
xml . p r e f e r e n c e s , f a l s e ) ; /∗ ∗
∗ C r e a t e r e q u i r e d f o l d e r s and c h e c k s
// I f SD c a r d i s p r e s e n t . whether the r e q u i r e d a s s e t f i l e s a r e
i f ( Directories . checkExternalStorage () ) { a l r e a d y i n t h e SD c a r d .
// c h e c k i f d i r e c t o r i e s / f i l e s n e e d e d a r e ∗ @return t r u e i f the f i l e s a r e p r e s e n t .
present . ∗/
i f ( requiredFilesPresent () ) { @SuppressWarnings ( { ” R e s u l t O f M e t h o d C a l l I g n o r e d
// D i s p l a y s p l a s h s c r e e n w i t h o u t c o p y i n g ” , ” ConstantConditions ” })
required f i l e s . private boolean r e q u i r e d F i l e s P r e s e n t () {
new H a n d l e r ( ) . p o s t D e l a y e d ( new Runnable ( ) { // c r e a t e r e q u i r e d f o l d e r s f o r t h i s app
@O verr ide
p u b l i c v o i d run ( ) { // Music D i r e c t o r y
// Check i f t h e r e i s a TTS i n s t a l l e d . F i l e d i r = new F i l e ( D i r e c t o r i e s . AUDIO DIR ) ;
f i n a l I n t e n t i n t e n t = new I n t e n t ( ) ; i f (! dir . exists () ){
i n t e n t . s e t A c t i o n ( TextToSpeech . E n g i n e . d i r . mkdir ( ) ;
ACTION CHECK TTS DATA) ; }
startActivityForResult ( intent , // Document D i r e c t o r y
CHECK TTS REQUEST CODE) ; d i r = new F i l e ( D i r e c t o r i e s . PDF DIR ) ;
} i f (! dir . exists () ){
} , SPLASH DISPLAY LENGTH) ; d i r . mkdir ( ) ;
} else { }
// I f d i r e c t o r i e s do n o t e x i s t s , s t a r t // Document D i r e c t o r y
c o p y i n g r e q u i r e d f i l e s and d i s p l a y s p l a s h d i r = new F i l e ( D i r e c t o r i e s . TEXT DIR) ;
screen . i f (! dir . exists () ){
new T a s k C o p y A s s e t s ( t h i s , new d i r . mkdir ( ) ;
T a s k C o p y A s s e t s . AsyncResponse ( ) { }
@O verr ide //Epub D i r e c t o r y
public void processFinished () { d i r = new F i l e ( D i r e c t o r i e s . EPUB CACHE DIR) ;
// Check i f t h e r e i s a TTS i n s t a l l e d . i f (! dir . exists () ){
f i n a l I n t e n t i n t e n t = new I n t e n t ( ) ; d i r . mkdir ( ) ;
i n t e n t . s e t A c t i o n ( TextToSpeech . E n g i n e . }
ACTION CHECK TTS DATA) ; // P i c t u r e s D i r e c t o r y
startActivityForResult ( intent , d i r = new F i l e ( D i r e c t o r i e s . IMAGES DIR ) ;
CHECK TTS REQUEST CODE) ; i f (! dir . exists () ){
} d i r . mkdir ( ) ;
}) . execute ( ) ; }
} // T e s s d a t a f o l d e r t h a t w i l l c o n t a i n .
} else { traineddatas
// D i s p l a y a l e r t D i a l o g t h a t SD c a r d i s n o t d i r = new F i l e ( g e t E x t e r n a l F i l e s D i r ( ” t e s s d a t a
mounted ” ) . getPath ( ) ) ;
f i n a l A l e r t D i a l o g . B u i l d e r b u i l d e r = new i f (! dir . exists () ){
AlertDialog . Builder ( this ) ; d i r . mkdir ( ) ;
b u i l d e r . s e t T i t l e ( ”SD Card n o t mounted ” ) ; }
b u i l d e r . s e t M e s s a g e ( ”An SD Card i s n e e d e d t o // Count t h e c o n t e n t o f t h e t e s s d a t a f o l d e r
run t h i s a p p l i c a t i o n . P l e a s e i n s e r t o r to determine whether the r e q u i r e d f i l e s
mount an SD c a r d ” ) ; are present
builder . setCancelable ( f a l s e ) ; f i n a l File [ ] contents = dir . l i s t F i l e s () ;
b u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new return contents . length > 0;
DialogInterface . OnClickListener () { }
@Ov err ide }
public void onClick ( D i a l o g I n t e r f a c e dialog

114
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
BitmapLoader.java

package anteraaron . t e s s 2 s p e e c h ; getAbsolutePath ( ) , options ) ;


// C a l c u l a t e i n S a m p l e S i z e
i m p o r t a n d r o i d . g r a p h i c s . Bitmap ; options . inSampleSize = calculateInSampleSize
i m p o r t a n d r o i d . g r a p h i c s . BitmapFacto ry ; ( o p t i o n s , reqWidth , r e q H e i g h t ) ;
import java . i o . F i l e ; // Decode bitmap w i t h i n S a m p l e S i z e s e t
o p t i o n s . inJustDecodeBounds = f a l s e ;
/∗ ∗
∗ A c l a s s t h a t c o n t a i n s method f o r R e s a m p l i n g r e t u r n BitmapFacto ry . d e c o d e F i l e ( f i l e .
l a r g e b i t m a p s t o a v o i d Out o f Memory getAbsolutePath ( ) , options ) ;
E r r o r s and A c c e l e r a t e image c o n v e r s i o n . }
∗ @author Android Development t u t o r i a l &
Anter Aaron M. C u s t o d i o /∗ ∗
∗ @since 2 0 1 6 . 3 . 2 2 ∗ C a l c u l a t e s the appropriate InSampleSize
∗/ o f t h e Bitmap .
p u b l i c c l a s s BitmapLoader { ∗ @param o p t i o n s o p t i o n s c o n t a i n i n g t h e
d e c o d e d bounds o f t h e bitmap .
/∗ ∗ ∗ @param reqWidth r e q u i r e d w i d t h o f t h e
∗ Method t h a t c a l l s d i f f e r e n t image pre− bitmap .
processing . ∗ @param r e q H e i g h t r e q u i r e d h e i g h t o f t h e
∗/ bitmap .
p u b l i c s t a t i c Bitmap i m a g e P r e P r o c e s s ( Bitmap ∗ @return r e t u r n s the a p p r o p r i a t e sample
bitmap ) { s i z e f o r r e s i z i n g t h e bitmap .
bitmap = I m a g e P r e P r o c e s s . t o G r a y S c a l e ( bitmap ) ∗/
; private static int calculateInSampleSize (
bitmap = I m a g e P r e P r o c e s s . f i n a l BitmapFac tory . O p t i o n s o p t i o n s ,
c h a n g e B i t m a p C o n t r a s t B r i g h t n e s s ( bitmap ) ; f i n a l i n t reqWidth , f i n a l i n t r e q H e i g h t )
{
r e t u r n bitmap ; // Raw h e i g h t and w i d t h o f image
} f i n a l i n t height = options . outHeight ;
f i n a l i n t w i d t h = o p t i o n s . outWidth ;
/∗ ∗ int inSampleSize = 1;
∗ Reduces t h e s i z e o f bitmap b a s e d on t h e
c a l c u l a t e d InSampleSize . // R e s i z e o n l y i f t h e bitmap i s l a r g e r than
∗ @param f i l e t h e bitmap f i l e t o be the r e q u i r e d dimension .
resampled . i f ( h e i g h t > r e q H e i g h t | | w i d t h > reqWidth )
∗ @param reqWidth r e q u i r e d w i d t h o f t h e {
bitmap . f i n a l int halfHeight = height / 2;
∗ @param r e q H e i g h t r e q u i r e d h e i g h t o f t h e f i n a l i n t halfWidth = width / 2 ;
bitmap . // C a l c u l a t e t h e l a r g e s t i n S a m p l e S i z e v a l u e
∗ @ r e t u r n r e t u r n s t h e r e s a m p l e d bitmap t h a t i s a power o f 2 and k e e p s both
w i t h reqWidth x r e q H e i g h t d i m e n s i o n . h e i g h t and w i d t h l a r g e r than t h e
∗/ r e q u e s t e d h e i g h t and w i d t h .
p u b l i c s t a t i c Bitmap decodeSampledBitmap ( while (( halfHeight / inSampleSize ) >
f i n a l F i l e f i l e , f i n a l i n t reqWidth , r e q H e i g h t && ( h a l f W i d t h / i n S a m p l e S i z e ) >
f i n a l int reqHeight ) { reqWidth ) {
i n S a m p l e S i z e ∗= 2 ;
// F i r s t d e c o d e w i t h i n J u s t D e c o d e B o u n d s=t r u e }
to check dimensions }
f i n a l BitmapFac tory . O p t i o n s o p t i o n s = new return inSampleSize ;
Bitmap Factory . O p t i o n s ( ) ; }
o p t i o n s . inJustDecodeBounds = t r u e ; }
BitmapF actory . d e c o d e F i l e ( f i l e .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Directories.java

package anteraaron . t e s s 2 s p e e c h ; Environment .


getExternalStoragePublicDirectory (”
import android . net . Uri ; Documents ” ) . g e t A b s o l u t e P a t h ( ) ;
i m p o r t a n d r o i d . o s . Environment ; // Saved t e x t d i r e c t o r y
p u b l i c s t a t i c f i n a l S t r i n g TEXT DIR =
import java . i o . F i l e ; Environment .
getExternalStoragePublicDirectory (”
/∗ ∗ Documents ” ) . g e t A b s o l u t e P a t h ( ) ;
∗ Class that contains constant values f o r the // Saved i n p u t i m a g e s
a p p l i c a t i o n ’ s D i r e c t o r i e s and F i l e p u b l i c s t a t i c f i n a l S t r i n g IMAGES DIR =
paths . Environment .
∗ @author Anter Aaron M. C u s t o d i o getExternalStoragePublicDirectory (
∗ @since 2 0 1 6 . 3 . 2 2 Environment . DIRECTORY PICTURES) .
∗/ getAbsolutePath ( ) + F i l e . separator + ”
public f i n a l class Directories { Tesseract ” ;
// Saved p h o t o d i r e c t o r y // Saved t e x t d i r e c t o r y
p u b l i c s t a t i c U r i imageFromCameraUri ; p u b l i c s t a t i c f i n a l S t r i n g EPUB CACHE DIR =
// Saved a u d i o d i r e c t o r y Environment .
p u b l i c s t a t i c f i n a l S t r i n g AUDIO DIR = getExternalStoragePublicDirectory (”
Environment . Documents ” ) . g e t A b s o l u t e P a t h ( ) + F i l e .
getExternalStoragePublicDirectory ( s e p a r a t o r + ” epubCache ” ;
Environment . DIRECTORY MUSIC) .
getAbsolutePath ( ) ; /∗ ∗
// Saved p d f d i r e c t o r y ∗ Checks i f an SD c a r d is mounted .
p u b l i c s t a t i c f i n a l S t r i n g PDF DIR = ∗ @return r e t u r n s t r u e if t h e r e i s an SD

115
c a r d mounted . public s t a t i c void d e l e t e ( f i n a l F i l e
∗/ fileOrDirectory ) {
public s t a t i c boolean checkExternalStorage () { i f ( fileOrDirectory . isDirectory () ) {
r e t u r n Environment . g e t E x t e r n a l S t o r a g e S t a t e ( ) for ( final File child : fileOrDirectory .
. e q u a l s ( Environment .MEDIA MOUNTED) ; l i s t F i l e s () ) {
} delete ( child ) ;
}
/∗ ∗ }
∗ A r e c u r s i v e way f o r d e l e t i n g a f i l e or fileOrDirectory . delete () ;
d i r e c t o r y and i t s c o n t e n t s . }
∗ @param f i l e O r D i r e c t o r y t h e f i l e o r }
d i r e c t o r y t o be d e l e t e d .
∗/

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
DrawingView.java

package anteraaron . t e s s 2 s p e e c h ; oldHeight ) ;

import android . c o n t e n t . Context ; // draw o n t o t h e d e f i n e d Bitmap


import android . u t i l . AttributeSet ; f i n a l Bitmap bitmap = Bitmap . c r e a t e B i t m a p (
import a n d r o i d . u t i l . Log ; width , h e i g h t , Bitmap . C o n f i g . ARGB 8888 ) ;
import a n d r o i d . v i e w . View ; new Canvas ( bitmap ) ;
import a n d r o i d . g r a p h i c s . Bitmap ; }
import a n d r o i d . g r a p h i c s . Canvas ;
import android . graphics . Color ; // O v e r r i d e onDraw
import android . g r a p h i c s . Paint ; @O verr ide
import a n d r o i d . g r a p h i c s . Path ; p r o t e c t e d v o i d onDraw ( Canvas c a n v a s ) {
import a n d r o i d . v i e w . MotionEvent ; s u p e r . onDraw ( c a n v a s ) ;
import java . u t i l . ArrayList ; //Draw t h e p a t h s when onDraw i s c a l l e d w i t h
import j a v a . u t i l . HashMap ; the s e t paint a t t r i b u t e
import j a v a . u t i l . Map ; f o r ( f i n a l Path p : p a t h s ) {
t h i s . paint . s e t C o l o r ( t h i s . colorsMap . get ( p ) ) ;
/∗ ∗ t h i s . p a i n t . s e t S t r o k e W i d t h ( t h i s . widthMap . g e t
∗ The Drawable Canvas View o f t h e a p p l i c a t i o n (p) ) ;
( Using g e s t u r e s ) . c a n v a s . drawPath ( p , t h i s . p a i n t ) ;
∗ @author Anter Aaron M. C u s t o d i o }
∗ @since 2 0 1 6 . 3 . 2 2 // S e t a t t r i b u t e s o f t h e s t r o k e
∗/ this . paint . setColor ( this . selectedColor ) ;
p u b l i c c l a s s DrawingView e x t e n d s View { t h i s . paint . setStrokeWidth ( t h i s . strokeWidth ) ;
c a n v a s . drawPath ( t h i s . path , t h i s . p a i n t ) ;
p r i v a t e Path path ; //Drawn path }
p r i v a t e P a i n t p a i n t ; // C o l o r o f t h e path
private float x , y ; /∗ ∗
p r i v a t e s t a t i c f i n a l f l o a t TOLERANCE = 2 ; // ∗ When ACTION DOWN ( g e s t u r e h a s s t a r t e d ) .
Tolerance l e v e l to a void a l i a s i n g ∗ @param x x c o o r d i n a t e o f t o u c h e d p a r t
p r i v a t e s t a t i c f i n a l f l o a t STROKE WIDTH = 10 f o f the canvas
; // S i z e o f s t r o k e ∗ @param y y c o o r d i n a t e o f t o u c h e d p a r t
p r i v a t e s t a t i c f i n a l f l o a t ERASE WIDTH = 25 f ; o f the canvas
// S i z e o f d e l e t i n g s t r o k e ∗/
p r i v a t e f l o a t strokeWidth ; p r i v a t e void startTouch ( f i n a l f l o a t x , f i n a l
p r i v a t e i n t s e l e c t e d C o l o r = C o l o r .BLACK; float y) {
p r i v a t e boolean drawPoint ; t h i s . drawPoint = t r u e ;
t h i s . path . moveTo ( x , y ) ;
// Hash Maps f o r m a i n t a i n i n g t h e drawn c a n v a s . this .x = x;
p r i v a t e Map<Path , I n t e g e r > c o l o r s M a p ; this .y = y;
p r i v a t e Map<Path , F l o a t > widthMap ; }
p r i v a t e A r r a y L i s t <Path> p a t h s ;
/∗ ∗
p u b l i c DrawingView ( f i n a l C o n t e x t c , final ∗ When ACTION MOVE ( c h a n g e h a s happened
AttributeSet attrs ) { during pressed gesture )
super ( c , a t t r s ) ; ∗ @param x x c o o r d i n a t e o f t o u c h e d p a r t
o f the canvas
// I n i t i a l i z e ∗ @param y y c o o r d i n a t e o f t o u c h e d p a r t
t h i s . s t r o k e W i d t h = STROKE WIDTH ; o f the canvas
t h i s . drawPoint = f a l s e ; ∗/
p r i v a t e v o i d moveTouch ( f i n a l f l o a t x , f i n a l
// I n i t i a l i z e HashMaps float y) {
t h i s . c o l o r s M a p = new HashMap<>() ; t h i s . drawPoint = f a l s e ;
t h i s . widthMap = new HashMap<>() ; f i n a l f l o a t dx = Math . a b s ( x − t h i s . x ) ;
t h i s . p a t h s = new A r r a y L i s t <>() ; f i n a l f l o a t dy = Math . a b s ( y − t h i s . y ) ;

// S e t new Path i f ( dx >= TOLERANCE | | dy >= TOLERANCE) {


t h i s . path = new Path ( ) ; t h i s . path . quadTo ( t h i s . x , t h i s . y , ( x + t h i s .
x ) / 2 , ( y + t h i s . y ) / 2) ;
// S e t new P a i n t w i t h t h e d e s i r e d a t t r i b u t e s . this .x = x;
t h i s . p a i n t = new P a i n t ( ) ; this .y = y;
this . paint . setAntiAlias ( true ) ; }
t h i s . p a i n t . s e t C o l o r ( C o l o r .BLACK) ; }
t h i s . p a i n t . s e t S t y l e ( P a i n t . S t y l e .STROKE) ;
t h i s . p a i n t . s e t S t r o k e J o i n ( P a i n t . J o i n .ROUND) ; /∗ ∗
t h i s . paint . setStrokeWidth (5 f ) ; ∗ When ACTION UP ( g e s t u r e s t o p )
} ∗/
p r i v a t e v o i d upTouch ( ) {
// O v e r r i d e o n S i z e C h a n g e d t h i s . path . l i n e T o ( t h i s . x , t h i s . y ) ;
@O verr ide t h i s . p a t h s . add ( t h i s . path ) ;
p r o t e c t e d v o i d o n S i z e C h a n g e d ( f i n a l i n t width , t h i s . c o l o r s M a p . put ( t h i s . path , t h i s .
f i n a l i n t h e i g h t , f i n a l i n t oldWidth , selectedColor ) ;
f i n a l int oldHeight ) { t h i s . widthMap . put ( t h i s . path , t h i s .
s u p e r . o n S i z e C h a n g e d ( width , h e i g h t , oldWidth , strokeWidth ) ;

116
t h i s . path = new Path ( ) ; t h i s . path . r e s e t ( ) ;
invalidate () ;
// C r e a t e a d o t }
t h i s . path . s e t L a s t P o i n t ( t h i s . x , t h i s . y ) ;
t h i s . x+=5; /∗ ∗
t h i s . path . l i n e T o ( t h i s . x , t h i s . y ) ; ∗ Method t h a t c h a n g e s t h e c o l o r o f t h e
t h i s . p a t h s . add ( t h i s . path ) ; p a t h s from w h i t e t o b l a c k and v i c e −
t h i s . c o l o r s M a p . put ( t h i s . path , t h i s . versa .
selectedColor ) ; ∗/
t h i s . widthMap . put ( t h i s . path , t h i s . p u b l i c void changeInk ( ) {
strokeWidth ) ; i f ( t h i s . s e l e c t e d C o l o r == C o l o r .BLACK) {
t h i s . path = new Path ( ) ; // S e t path c o l o r t o w h i t e and i n c r e a s e t h e
t h i s . x−=5; s i z e of s t r o k e to e r a s e s t r o k e s e a s i l y .
t h i s . s e l e c t e d C o l o r = C o l o r .WHITE;
// C r e a t e a d o t t h i s . s t r o k e W i d t h = ERASE WIDTH ;
t h i s . path . s e t L a s t P o i n t ( t h i s . x , t h i s . y ) ; }else{
t h i s . y−−; // S e t path c o l o r t o b l a c k .
t h i s . path . l i n e T o ( t h i s . x , t h i s . y ) ; t h i s . s e l e c t e d C o l o r = C o l o r .BLACK;
t h i s . p a t h s . add ( t h i s . path ) ; t h i s . s t r o k e W i d t h = STROKE WIDTH ;
t h i s . c o l o r s M a p . put ( t h i s . path , t h i s . }
selectedColor ) ; }
t h i s . widthMap . put ( t h i s . path , t h i s .
strokeWidth ) ; // o v e r r i d e t h e onTouchEvent
t h i s . path = new Path ( ) ; @O verr ide
t h i s . y++; p u b l i c b o o l e a n onTouchEvent ( f i n a l MotionEvent
event ) {
// C r e a t e a d o t f i n a l f l o a t x = e v e n t . getX ( ) ;
t h i s . x−=5 ; f i n a l f l o a t y = e v e n t . getY ( ) ;
t h i s . path . s e t L a s t P o i n t ( t h i s . x , t h i s . y ) ; // C a l l s c o r r e s p o n d i n g methods a c c o r d i n g t o
t h i s . x+=5; user gestures .
t h i s . path . l i n e T o ( t h i s . x , t h i s . y ) ; switch ( event . getAction ( ) ) {
t h i s . p a t h s . add ( t h i s . path ) ; c a s e MotionEvent .ACTION DOWN:
t h i s . c o l o r s M a p . put ( t h i s . path , t h i s . startTouch (x , y ) ;
selectedColor ) ; invalidate () ;
t h i s . widthMap . put ( t h i s . path , t h i s . break ;
strokeWidth ) ; c a s e MotionEvent . ACTION MOVE :
t h i s . path = new Path ( ) ; moveTouch ( x , y ) ;
invalidate () ;
t h i s . path . r e s e t ( ) ; break ;
} c a s e MotionEvent . ACTION UP :
upTouch ( ) ;
/∗ ∗ invalidate () ;
∗ Method t h a t c l e a r s a l l that is written break ;
in the canvas . }
∗/ return true ;
public void clearCanvas () { }
t h i s . colorsMap . c l e a r ( ) ; }
t h i s . paths . c l e a r ( ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_ConvertedText.java

package anteraaron . t e s s 2 s p e e c h ; ∗ @ r e t u r n r e t u r n s t h e i n f l a t e d View .


∗/
import android . o s . Bundle ; p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) {
import android . s u p p o r t . v4 . app . Fragment ; // C r e a t e t h e l i n e d t e x t v i e w i n which t h e
import android . view . L a y o u t I n f l a t e r ; c o n v e r t e d t e x t s w i l l be d i s p l a y e d .
import android . v i e w . View ; e d i t T e x t = ( E d i t T e x t ) v i e w . f i n d V i e w B y I d (R . i d .
import android . v i e w . ViewGroup ; editText ) ;
import android . widget . EditText ; editText . setText ( ”” ) ;
import android . widget . Switch ; // C r e a t e s s w i t c h f o r a p p e n d i n g t e x t .
s w i t c h a p p e n d = ( S w i t c h ) v i e w . f i n d V i e w B y I d (R .
/∗ ∗ id . switch append ) ;
∗ A Fragment f o r t h e C o n v e r t e d t e x t s which is
embedded i n t h e M a i n A c t i v i t y r e t u r n view ;
∗ @author Anter Aaron M. C u s t o d i o }
∗ @since 2 0 1 6 . 3 . 2 2
∗/ /∗ ∗
p u b l i c c l a s s Fragment ConvertedText extends ∗ Checks w h e t h e r append s w i t c h i s on . I f
Fragment { i t i s n o t on , c l e a r t h e
p u b l i c s t a t i c EditText editText ; l i n e d E d i t T e x t view .
p u b l i c s t a t i c Switch switch append ; ∗/
p u b l i c s t a t i c v o i d checkAppend ( ) {
@O verr ide // Check i f t h e u s e r wants t o r e t a i n t h e
p u b l i c View o n C re a t e V i ew ( f i n a l L a y o u t I n f l a t e r previous converted text
i n f l a t e r , f i n a l ViewGroup c o n t a i n e r , i f ( ! switch append . isChecked ( ) | | editText .
f i n a l Bundle s a v e d I n s t a n c e S t a t e ) { g e t T e x t ( ) . l e n g t h ( ) == 0 ) {
// I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t Fragment ConvertedText . e d i t T e x t . setText ( ”” )
r e t u r n c r e a t e U I ( i n f l a t e r . i n f l a t e (R . l a y o u t . ;
fragment converted text , container , f a l s e } else {
)); F r a g m e n t C o n v e r t e d T e x t . e d i t T e x t . append ( ” \n”
} );
}
/∗ ∗ }
∗ C r e a t e UI f o r C o n v e r t e d Text Fragment }
∗ @param v i e w View t o be i n f l a t e d .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/

117
Fragment\_DrawingCanvas.java

package anteraaron . t e s s 2 s p e e c h ; OnClickListener () {


@O verr ide
import android . o s . Bundle ; p u b l i c v o i d o n C l i c k ( View v ) {
import android . s u p p o r t . v4 . app . Fragment ; drawingView . c l e a r C a n v a s ( ) ;
import android . view . L a y o u t I n f l a t e r ; T oa s t . makeText ( g e t A c t i v i t y ( ) , ” Canvas
import android . v i e w . View ; C l e a r e d ! ” , T o as t . LENGTH SHORT) . show ( ) ;
import android . v i e w . ViewGroup ; }
import android . w i d g e t . Button ; }) ;
import android . w i d g e t . T o a st ;
// C r e a t e s t r o k e b u t t o n .
/∗ ∗ f i n a l Button b u t t o n s t r o k e = ( Button ) v i e w .
∗ A Fragment f o r t h e Drawing Canvas which i s f i n d V i e w B y I d (R . i d . b u t t o n s t r o k e ) ;
embedded i n t h e M a i n A c t i v i t y b u t t o n s t r o k e . s e t O n C l i c k L i s t e n e r ( new View .
∗ @author Anter Aaron M. C u s t o d i o OnClickListener () {
∗ @since 2 0 1 6 . 3 . 2 2 @O verr ide
∗/ p u b l i c v o i d o n C l i c k ( View v ) {
p u b l i c c l a s s Fragment DrawingCanvas e x t e n d s i f ( b u t t o n s t r o k e . getText ( ) . e q ua l s (
Fragment { g e t R e s o u r c e s ( ) . g e t S t r i n g (R . s t r i n g .
p u b l i c s t a t i c DrawingView drawingView ; button stroke stroke ) ) ){
// S e t d i s p l a y e d b u t t o n a s e r a s e
@O verr ide drawingView . c h a n g e I n k ( ) ;
p u b l i c View o n C re a t e V i ew ( f i n a l L a y o u t I n f l a t e r button stroke .
i n f l a t e r , f i n a l ViewGroup c o n t a i n e r , setCompoundDrawablesWithIntrinsicBounds
f i n a l Bundle s a v e d I n s t a n c e S t a t e ) { ( 0 , R . mipmap . i c e r a s e r , 0 , 0 ) ;
// I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t button stroke . setText ( getResources () .
r e t u r n c r e a t e U I ( i n f l a t e r . i n f l a t e (R . l a y o u t . g e t S t r i n g (R . s t r i n g . b u t t o n s t r o k e ) ) ;
fragment canvas , container , f a l s e ) ) ; }else{
} // S e t d i s p l a y e d b u t t o n a s s t r o k e
drawingView . c h a n g e I n k ( ) ;
/∗ ∗ button stroke .
∗ C r e a t e UI f o r Drawing Canvas f r a g m e n t . setCompoundDrawablesWithIntrinsicBounds
∗ @param v i e w View t o be i n f l a t e d . ( 0 , R . mipmap . i c a c t i o n b r u s h , 0 , 0 ) ;
∗ @return r e t u r n s the i n f l a t e d view . button stroke . setText ( getResources () .
∗/ g e t S t r i n g (R . s t r i n g . b u t t o n s t r o k e s t r o k e ) )
p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) { ;
// C r e a t e t h e Drawing View . }
drawingView = ( DrawingView ) v i e w . f i n d V i e w B y I d }
(R . i d . d r a w i n g ) ; }) ;

// C r e a t e c l e a r c a n v a s b u t t o n . r e t u r n view ;
f i n a l Button b u t t o n c l e a r = ( Button ) v i e w . }
f i n d V i e w B y I d (R . i d . b u t t o n c l e a r ) ; }
b u t t o n c l e a r . s e t O n C l i c k L i s t e n e r ( new View .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_EPubViewer.java

package anteraaron . t e s s 2 s p e e c h ; ∗ C r e a t e UI f o r Epub Fragment


∗ @param v i e w View t o be i n f l a t e d .
import android . annotation . SuppressLint ; ∗ @ r e t u r n r e t u r n s t h e i n f l a t e d View .
i m p o r t a n d r o i d . o s . Bundle ; ∗/
i m p o r t a n d r o i d . s u p p o r t . v4 . app . Fragment ; @SuppressLint ( ” SetJavaScriptEnabled ” )
i m p o r t a n d r o i d . s u p p o r t . v4 . app . p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) {
FragmentTransaction ; // C r e a t e webview
import android . view . L a y o u t I n f l a t e r ; webView = new WebView ( g e t A c t i v i t y ( ) .
i m p o r t a n d r o i d . v i e w . View ; getApplicationContext () ) ;
i m p o r t a n d r o i d . v i e w . ViewGroup ; webView . s e t W e b V i e w C l i e n t ( new WebViewClient ( )
i m p o r t a n d r o i d . w e b k i t . WebView ; );
i m p o r t a n d r o i d . w e b k i t . WebViewClient ; R e l a t i v e L a y o u t . LayoutParams l p = new
i m p o r t a n d r o i d . w i d g e t . Button ; R e l a t i v e L a y o u t . LayoutParams (
import android . widget . RelativeLayout ; R e l a t i v e L a y o u t . LayoutParams .MATCH PARENT,
R e l a t i v e L a y o u t . LayoutParams .MATCH PARENT
import java . i o . F i l e ; );
l p . addRule ( R e l a t i v e L a y o u t .BELOW, R . i d .
/∗ ∗ button epub back to toc ) ;
∗ A Fragment f o r d i s p l a y i n g t h e d a t a o f t h e webView . s e t L a y o u t P a r a m s ( l p ) ;
c l i c k e d t a b l e o f c o n t e n t s which i s webView . g e t S e t t i n g s ( ) . s e t J a v a S c r i p t E n a b l e d (
embedded i n t h e M a i n A c t i v i t y true ) ;
∗ @author Anter Aaron M. C u s t o d i o
∗ @since 2 0 1 6 . 3 . 2 7 RelativeLayout relativeLayout = (
∗/ R e l a t i v e L a y o u t ) v i e w . f i n d V i e w B y I d (R . i d .
p u b l i c c l a s s Fragment EPubViewer e x t e n d s epub layout ) ;
Fragment { r e l a t i v e L a y o u t . addView ( webView ) ;
p u b l i c s t a t i c WebView webView ;

@O verr ide // c r e a t e Back t o T a b l e o f C o n t e n t s


p u b l i c View o n C re a t e V i ew ( f i n a l L a y o u t I n f l a t e r f i n a l Button b u t t o n e p u b b a c k t o t o c = (
i n f l a t e r , f i n a l ViewGroup c o n t a i n e r , Button ) v i e w . f i n d V i e w B y I d (R . i d .
f i n a l Bundle s a v e d I n s t a n c e S t a t e ) { button epub back to toc ) ;
// I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t button epub back to toc . setOnClickListener (
r e t u r n c r e a t e U I ( i n f l a t e r . i n f l a t e (R . l a y o u t . new View . O n C l i c k L i s t e n e r ( ) {
fragment epub , container , f a l s e ) ) ; @O verr ide
} p u b l i c v o i d o n C l i c k ( View v ) {
//Do n o t c l e a r a l l when o n l y g o i n g back t o
/∗ ∗ toc .

118
webView . s t o p L o a d i n g ( ) ; findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
webView . c l e a r H i s t o r y ( ) ; f t . hide ( getActivity () .
webView . c l e a r C a c h e ( t r u e ) ; getSupportFragmentManager ( ) .
webView . c l e a r F o r m D a t a ( ) ; findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
webView . c l e a r S s l P r e f e r e n c e s ( ) ; f t . commit ( ) ;
webView . l o a d U r l ( ” a b o u t : b l a n k ” ) ;
// R e c r e a t e EPUB t a b l e o f c o n t e n t s
// Hide c u r r e n t f r a g m e n t and d i s p l a y Fragment EPubViewer TOC f r a g m e n t = (
fragment epub toc Fragment EPubViewer TOC ) g e t A c t i v i t y ( ) .
f i n a l FragmentTransaction f t = g e t A c t i v i t y getSupportFragmentManager ( ) .
( ) . getSupportFragmentManager ( ) . findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ;
beginTransaction () ; fragment . clearAdapter ( ) ;
f t . show ( g e t A c t i v i t y ( ) .
getSupportFragmentManager ( ) . // s e t s t a t e
findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ; Activity Main . state = Activity Main . State .
f t . hide ( getActivity () . IS CANVAS ;
getSupportFragmentManager ( ) . }
findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ; }) ;
f t . commit ( ) ;
} r e t u r n view ;
}) ; }

// c r e a t e Back t o Canvas p u b l i c s t a t i c v o i d clearWebView ( ) {


f i n a l Button b u t t o n e p u b b a c k t o c a n v a s = ( // F r e e webview memory
Button ) v i e w . f i n d V i e w B y I d (R . i d . webView . s t o p L o a d i n g ( ) ;
button epub back to canvas ) ; webView . c l e a r H i s t o r y ( ) ;
button epub back to canvas . webView . c l e a r C a c h e ( t r u e ) ;
s e t O n C l i c k L i s t e n e r ( new View . webView . c l e a r F o r m D a t a ( ) ;
OnClickListener () { webView . c l e a r S s l P r e f e r e n c e s ( ) ;
@O verr ide webView . l o a d U r l ( ” a b o u t : b l a n k ” ) ;
p u b l i c v o i d o n C l i c k ( View v ) { // n o i n s p e c t i o n d e p r e c a t i o n
// c l e a r webview c o n t e n t webView . freeMemory ( ) ;
clearWebView ( ) ; // webView . p a u s e T i m e r s ( ) ;
D i r e c t o r i e s . d e l e t e ( new F i l e ( D i r e c t o r i e s . webView . r e m o v e A l l V i e w s ( ) ;
EPUB CACHE DIR) ) ;
// d e l e t e epub c a c h e d i r .
// Hide c u r r e n t f r a g m e n t and d i s p l a y c a n v a s // D i r e c t o r i e s . d e l e t e ( new F i l e ( D i r e c t o r i e s .
f i n a l FragmentTransaction f t = g e t A c t i v i t y EPUB CACHE DIR) ) ;
( ) . getSupportFragmentManager ( ) . }
beginTransaction () ; }
f t . show ( g e t A c t i v i t y ( ) .
getSupportFragmentManager ( ) .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_EPubViewer\_TOC.java

package anteraaron . t e s s 2 s p e e c h ; list ).


∗/
import android . net . Uri ; p r i v a t e c l a s s RowData {
i m p o r t a n d r o i d . s u p p o r t . v4 . app . private String t i t l e ;
FragmentTransaction ; p r i v a t e Resource r e s o u r c e ;
i m p o r t a n d r o i d . s u p p o r t . v4 . app . L i s t F r a g m e n t ;
import android . c o n t e n t . Context ; p u b l i c RowData ( ) {
i m p o r t a n d r o i d . o s . Bundle ; super () ;
i m p o r t a n d r o i d . u t i l . Log ; }
import android . view . L a y o u t I n f l a t e r ;
i m p o r t a n d r o i d . v i e w . View ; // Get t i t l e o f Epub
i m p o r t a n d r o i d . v i e w . ViewGroup ; public String getTitle () {
import andr oid . widget . ArrayAdapter ; return t i t l e ;
i m p o r t a n d r o i d . w i d g e t . Button ; }
i m p o r t a n d r o i d . w i d g e t . TextView ;
import java . i o . F i l e ; // Get d a t a o f Epub
import java . i o . IOException ; p u b l i c Resource getResource ( ) {
import java . i o . InputStream ; return resource ;
import java . u t i l . ArrayList ; }
import java . u t i l . L i s t ;
i m p o r t n l . si e g ma n n . e p u b l i b . domain . Book ; // S e t t h e t i t l e o f t h e Epub
i m p o r t n l . si e g ma n n . e p u b l i b . domain . R e s o u r c e ; public void s e t T i t l e ( f i n a l String title ) {
i m p o r t n l . si e g ma n n . e p u b l i b . domain . TOCReference this . title = title ;
; }
i m p o r t n l . si e g ma n n . e p u b l i b . epub . EpubReader ;
// S e t t h e d a t a o f t h e Epub
/∗ ∗ public void setResource ( f i n a l Resource
∗ A Fragment f o r d i s p l a y i n g Epub t a b l e o f resource ) {
c o n t e n t s which i s embedded i n t h e this . resource = resource ;
Main Activity }
∗ @author Anter Aaron M. C u s t o d i o
∗ @since 2 0 1 6 . 3 . 2 7 }
∗/
p u b l i c c l a s s Fragment EPubViewer TOC e x t e n d s /∗ ∗
ListFragment { ∗ A c l a s s t h a t c r e a t e s a Custom Adapter
f o r d i s p l a y i n g t h e l i s t o f Epubs .
p r i v a t e L i s t <RowData> rowData ; ∗/
p r i v a t e S t r i n g path ; p r i v a t e c l a s s CustomAdapter e x t e n d s
p u b l i c s t a t i c S t r i n g htmlContent , ArrayAdapter<RowData> {
adapterContent ; // C o n s t r u c t o r
p u b l i c CustomAdapter ( f i n a l C o n t e x t c o n t e x t ,
/∗ ∗ f i n a l int resource , f i n a l int
∗ An I n n e r c l a s s t h a t s e r v e s a s t h e Epub t e x t V i e w R e s o u r c e I d , f i n a l L i s t <RowData>
e l e m e n t o f t h e l i s t . ( Rows o f e v e r y objects ) {

119
super ( context , resource , textViewResourceId
, objects ) ; // d e l e t e epub c a c h e d i r .
} D i r e c t o r i e s . d e l e t e ( new F i l e ( D i r e c t o r i e s .
EPUB CACHE DIR) ) ;
/∗ ∗
∗ An i n n e r c l a s s t h a t s e r v e s a s a // Hide c u r r e n t f r a g m e n t and d i s p l a y c a n v a s
h o l d e r f o r t i t l e and row d a t a . f i n a l FragmentTransaction f t = g e t A c t i v i t y
∗/ ( ) . getSupportFragmentManager ( ) .
p r i v a t e c l a s s Vi ew Ho ld er { beginTransaction () ;
p r i v a t e View row ; f t . show ( g e t A c t i v i t y ( ) .
p r i v a t e TextView t i t l e H o l d e r = n u l l ; getSupportFragmentManager ( ) .
// C o n s t r u c t o r findFragmentByTag ( ” f r a g m e n t c a n v a s ” ) ) ;
p u b l i c Vi ew Ho ld e r ( f i n a l View row ) { f t . hide ( getActivity () .
super () ; getSupportFragmentManager ( ) .
t h i s . row = row ; findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
} f t . commit ( ) ;
// G e t t e r f o r t i t l e
p u b l i c TextView g e t T i t l e ( ) { // C l e a r t a b l e o f contents
i f ( n u l l == t h i s . t i t l e H o l d e r ) { clearAdapter () ;
t h i s . t i t l e H o l d e r = ( TextView ) row .
f i n d V i e w B y I d (R . i d . row ) ; // s e t s t a t e
} Activity Main . state = Activity Main . State .
return titleHolder ; IS CANVAS ;
} }
} }) ;
r e t u r n view ;
@Ov err ide }
p u b l i c View g e t V i e w ( f i n a l i n t p o s i t i o n , View
c o n v e r t V i e w , f i n a l ViewGroup p a r e n t ) { @O verr ide
// R e t u r n s row d a t a and t i t l e when an p u b l i c v o i d onViewCreated ( f i n a l View view ,
adapter r e s o u r c e i . d i s used . f i n a l Bundle s a v e d I n s t a n c e S t a t e ) {
Vi ew Ho l de r h o l d e r ; //When t h i s v i e w h a s f o c u s , f i l t e r t e x t s
TextView t i t l e ; that the user types .
f i n a l RowData rowData = g e t I t e m ( p o s i t i o n ) ; getListView () . setTextFilterEnabled ( true ) ;
}
i f ( n u l l == c o n v e r t V i e w ) {
c o n v e r t V i e w = View . i n f l a t e ( g e t A c t i v i t y ( ) , /∗ ∗
R. layout . v i e w e p u b l i s t v i e w r o w , n u l l ) ; ∗ Method t h a t c r e a t e s t h e a d a p t e r ( epub
h o l d e r = new V i ew Ho ld er ( c o n v e r t V i e w ) ; t a b l e of contents ) of the l i s t .
convertView . setTag ( h o l d e r ) ; ∗/
} p u b l i c v o i d c r e a t e A d a p t e r ( f i n a l U r i epubUri ,
f i n a l S t r i n g path ) {
h o l d e r = ( V i ew Ho ld er ) c o n v e r t V i e w . getTag ( ) ; i f ( e p u b U r i != n u l l ) {
t i t l e = holder . getTitle () ; t h i s . path = path ;
t i t l e . s e t T e x t ( rowData . g e t T i t l e ( ) ) ; t h i s . rowData = new A r r a y L i s t <>() ;
return convertView ;
} // Get book c o n t e n t .
try {
} f i n a l InputStream epubInputStream =
getActivity () . getContentResolver () .
@O verr ide openInputStream ( epubUri ) ;
p u b l i c v o i d o n C r e a t e ( f i n a l Bundle f i n a l Book book = ( new EpubReader ( ) ) .
savedInstanceState ) { readEpub ( e p u b I n p u t S t r e a m ) ;
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; i f ( e p u b I n p u t S t r e a m != n u l l ) {
} epubInputStream . c l o s e ( ) ;
}
l o g C o n t e n t s T a b l e ( book . g e t T a b l e O f C o n t e n t s ( )
@O verr ide . getTocReferences ( ) , 0) ;
p u b l i c View o n C re a t e V i ew ( f i n a l L a y o u t I n f l a t e r } catch ( IOException e ) {
i n f l a t e r , f i n a l ViewGroup c o n t a i n e r , Log . e ( ” e p u b l i b ” , e . g e t M e s s a g e ( ) ) ;
f i n a l Bundle s a v e d I n s t a n c e S t a t e ) { }
// I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t
r e t u r n c r e a t e U I ( i n f l a t e r . i n f l a t e (R . l a y o u t . // C r e a t e an a d a p t e r b a s e d on t h e c o n t e n t o f
view epub listview , container , f a l s e ) ) ; t h e book .
} f i n a l CustomAdapter customAdapter = new
CustomAdapter ( g e t A c t i v i t y ( ) , R . l a y o u t .
/∗ ∗ v i e w e p u b l i s t v i e w r o w , R . i d . row , t h i s .
∗ C r e a t e UI f o r Epub T a b l e o f C o n t e n t s rowData ) ;
Fragment s e t L i s t A d a p t e r ( customAdapter ) ;
∗ @param v i e w View t o be i n f l a t e d . customAdapter . n o t i f y D a t a S e t C h a n g e d ( ) ;
∗ @ r e t u r n r e t u r n s t h e i n f l a t e d View . }
∗/ }
p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) {
public void clearAdapter () {
f i n a l Button b u t t o n e p u b t o c b a c k = ( Button ) t h i s . rowData . c l e a r ( ) ;
v i e w . f i n d V i e w B y I d (R . i d . setListAdapter ( null ) ;
button epub toc back ) ; }
b u t t o n e p u b t o c b a c k . s e t O n C l i c k L i s t e n e r ( new
View . O n C l i c k L i s t e n e r ( ) { /∗ ∗
@O verr ide ∗A method t h a t g e t s t h e c h a p t e r s ( d a t a )
p u b l i c v o i d o n C l i c k ( View v ) { b a s e d on t h e t a b l e o f c o n t e n t s a s
// Free−up webview memory reference .
Fragment EPubViewer . webView . s t o p L o a d i n g ( ) ; ∗ @param t o c R e f e r e n c e s t h e t a b l e c o n t e n t s
Fragment EPubViewer . webView . c l e a r H i s t o r y ( ) which i s t h e r e f e r e n c e .
; ∗ @param d e p t h d e t e r m i n e s t h e d e p t h o f
Fragment EPubViewer . webView . c l e a r C a c h e ( t h e data−f e t c h ( 0 i s t h e f i r s t
true ) ; grouping in table of contents , 1 i s
Fragment EPubViewer . webView . c l e a r F o r m D a t a t h e s u b g r o u p o f e a c h 0 and s o on ) .
() ; ∗/
Fragment EPubViewer . webView . private void logContentsTable ( f i n a l List <
clearSslPreferences () ; TOCReference> t o c R e f e r e n c e s , f i n a l i n t
Fragment EPubViewer . webView . l o a d U r l ( ” a b o u t depth ) {
: blank ” ) ; i f ( t o c R e f e r e n c e s == n u l l ) {
// n o i n s p e c t i o n d e p r e c a t i o n return ;
Fragment EPubViewer . webView . freeMemory ( ) ; }
// Fragment EPubViewer . webView . p a u s e T i m e r s f o r ( f i n a l TOCReference t o c R e f e r e n c e :
() ; tocReferences ) {
Fragment EPubViewer . webView . r e m o v e A l l V i e w s f i n a l S t r i n g B u i l d e r t o c S t r i n g = new
() ; StringBuilder () ;

120
// Appends t a b on how deep t h e s e a r c h is try {
// i . e . A. h t m l C o n t e n t = new S t r i n g ( rowData .
// a. getResource ( ) . getData ( ) ) ;
// i. // C o n v e r t EPUB CACHE DIR t o URL s t r i n g
f o r ( i n t i = 0 ; i < d e p t h ; i ++) { S t r i n g u r l = new F i l e ( t h i s . path ) . toURI ( ) .
t o c S t r i n g . append ( ” \ t ” ) ; toURL ( ) . t o S t r i n g ( ) + F i l e . s e p a r a t o r + ”
} OEBPS” + F i l e . s e p a r a t o r ;
Fragment EPubViewer . webView .
// g e t t h e t i t l e o f e a c h c h a p t e r s and d a t a loadDataWithBaseURL ( u r l , htmlContent , ”
o f each c h a p t e r s t e x t / html ” , ” u t f −8” , n u l l ) ;
t o c S t r i n g . append ( t o c R e f e r e n c e . g e t T i t l e ( ) ) ;
// Hide c u r r e n t f r a g m e n t and d i s p l a y
f i n a l RowData row = new RowData ( ) ; fragment epub
row . s e t T i t l e ( t o c S t r i n g . t o S t r i n g ( ) ) ; f i n a l FragmentTransaction f t = g e t A c t i v i t y
row . s e t R e s o u r c e ( t o c R e f e r e n c e . g e t R e s o u r c e ( ) ) ( ) . getSupportFragmentManager ( ) .
; beginTransaction () ;
t h i s . rowData . add ( row ) ; f t . hide ( getActivity () .
a d a p t e r C o n t e n t = row . g e t T i t l e ( ) + ” \n” ; getSupportFragmentManager ( ) .
findFragmentByTag ( ” f r a g m e n t e p u b t o c ” ) ) ;
logContentsTable ( tocReference . getChildren () f t . show ( g e t A c t i v i t y ( ) .
, depth + 1) ; getSupportFragmentManager ( ) .
} findFragmentByTag ( ” f r a g m e n t e p u b ” ) ) ;
} f t . commit ( ) ;

@O verr ide } catch ( IOException e ) {


public void onListItemClick ( f i n a l android . Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;
w i d g e t . L i s t V i e w l , f i n a l View v , f i n a l }
int position , f i n a l long id ) { }
super . onListItemClick ( l , v , position , id ) ; }
f i n a l RowData rowData = t h i s . rowData . g e t (
position ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_InputImage.java

package anteraaron . t e s s 2 s p e e c h ; f i n a l View v i e w = i n f l a t e r . i n f l a t e (R . l a y o u t .


fragment input image , container , f a l s e ) ;
import android . o s . Bundle ; r e t u r n c r e a t e U I ( view ) ;
import android . s u p p o r t . v4 . app . Fragment ; }
import android . view . L a y o u t I n f l a t e r ;
import android . v i e w . View ; /∗ ∗
import android . v i e w . ViewGroup ; ∗ C r e a t e UI f o r I n p u t Image Fragment
import android . w i d g e t . Button ; ∗ @param v i e w View t o be i n f l a t e d .
∗ @ r e t u r n r e t u r n s t h e i n f l a t e d View .
/∗ ∗ ∗/
∗ A Fragment f o r t h e I n p u t Image which i s p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) {
embedded i n t h e M a i n A c t i v i t y // C r e a t e r o t a t e b u t t o n
∗ @author Anter Aaron M. C u s t o d i o b u t t o n r o t a t e = ( Button ) v i e w . f i n d V i e w B y I d (R
∗ @since 2 0 1 6 . 3 . 2 2 . id . button rotate ) ;
∗/ // C r e a t e c r o p b u t t o n
p u b l i c c l a s s Fragment InputImage extends b u t t o n c r o p = ( Button ) v i e w . f i n d V i e w B y I d (R .
Fragment { id . button crop ) ;
p u b l i c s t a t i c Button b u t t o n r o t a t e , // C r e a t e back b u t t o n
button crop , button back ; b u t t o n b a c k = ( Button ) v i e w . f i n d V i e w B y I d (R .
@O verr ide id . button back ) ;
p u b l i c View o n C re a t e V i ew ( f i n a l L a y o u t I n f l a t e r r e t u r n view ;
i n f l a t e r , f i n a l ViewGroup c o n t a i n e r , }
f i n a l Bundle s a v e d I n s t a n c e S t a t e ) { }
// I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_PdfViewer.java

package anteraaron . t e s s 2 s p e e c h ; p u b l i c View o n C r ea t e V i e w ( f i n a l L a y o u t I n f l a t e r


i n f l a t e r , f i n a l ViewGroup c o n t a i n e r ,
import android . o s . Bundle ; f i n a l Bundle s a v e d I n s t a n c e S t a t e ) {
import android . s u p p o r t . v4 . app . Fragment ; // I n f l a t e t h e l a y o u t f o r t h i s f r a g m e n t
import android . view . L a y o u t I n f l a t e r ; r e t u r n c r e a t e U I ( i n f l a t e r . i n f l a t e (R . l a y o u t .
import android . v i e w . View ; fragment pdf viewer , container , f a l s e ) ) ;
import android . v i e w . ViewGroup ; }
import android . w i d g e t . Button ;
import android . w i d g e t . TextView ; /∗ ∗
∗ C r e a t e UI f o r PDF v i e w e r Fragment
/∗ ∗ ∗ @param v i e w View t o be i n f l a t e d .
∗ A Fragment f o r t h e PDF v i e w e r which i s ∗ @ r e t u r n r e t u r n s t h e i n f l a t e d View .
embedded i n t h e M a i n A c t i v i t y ∗/
∗ @author Anter Aaron M. C u s t o d i o p r i v a t e View c r e a t e U I ( f i n a l View v i e w ) {
∗ @since 2 0 1 6 . 3 . 2 2 // C r e a t e t e x t V i e w i n PDF v i e w e r
∗/ t e x t V i e w p d f = ( TextView ) v i e w . f i n d V i e w B y I d (R
p u b l i c c l a s s Fragment PdfViewer extends . id . textView pdf ) ;
Fragment { r e t u r n view ;
p u b l i c s t a t i c TextView t e x t V i e w p d f ; }
p u b l i c s t a t i c Button b u t t o n p d f b a c k ; }
@O verr ide

121
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Fragment\_Settings.java

package anteraaron . t e s s 2 s p e e c h ; Data ” ) ;


// i n f l a t e l a y o u t t o a l e r t D i a l o g .
i m p o r t a n d r o i d . app . A l e r t D i a l o g ; f i n a l View c h e c k e d L i s t V i e w = View . i n f l a t e (
import android . content . D i a l o g I n t e r f a c e ; g e t A c t i v i t y ( ) , R. layout .
import android . content . S h a r e d P r e f e r e n c e s ; alert dialog change language listview ,
i m p o r t a n d r o i d . o s . Bundle ; null ) ;
import android . p r e f e r e n c e . P r e f e r e n c e ; d i a l o g B u i l d e r . setView ( checkedListView ) ;
import android . p r e f e r e n c e . PreferenceFragment ; // c r e a t e l i s t v i e w
import android . p r e f e r e n c e . PreferenceManager ; f i n a l ListView l i s t V i e w = ( ListView )
i m p o r t a n d r o i d . u t i l . Log ; c h e c k e d L i s t V i e w . f i n d V i e w B y I d (R . i d .
import android . u t i l . SparseBooleanArray ; listView change language ) ;
i m p o r t a n d r o i d . v i e w . View ; // Get t r a i n e d d a t a l i s t .
i m p o r t a n d r o i d . w i d g e t . AdapterView ; // n o i n s p e c t i o n C o n s t a n t C o n d i t i o n s
import andr oid . widget . ArrayAdapter ; f i n a l F i l e d i r = new F i l e ( g e t A c t i v i t y ( ) .
import android . widget . ListView ; g e t E x t e r n a l F i l e s D i r ( ” t e s s d a t a ” ) . getPath ( )
i m p o r t a n d r o i d . w i d g e t . TextView ; );
i m p o r t com . g o o g l e c o d e . t e s s e r a c t . a n d r o i d . f i n a l F i l e [ ] l i s t = d i r . l i s t F i l e s ( new
TessBaseAPI ; FileFilter () {
import java . i o . F i l e ; @O verr ide
import java . i o . F i l e F i l t e r ; public boolean accept ( F i l e f i l e ) {
// Only a c c e p t s . t r a i n e d d a t a f i l e s .
/∗ ∗ f i n a l S t r i n g name = f i l e . getName ( ) .
∗ A Fragment f o r t h e P r e f e r e n c e S e t t i n g s toLowerCase ( ) ;
which i s embedded i n t h e M a i n A c t i v i t y r e t u r n name . endsWith ( ” . t r a i n e d d a t a ” ) &&
∗ @author Anter Aaron M. C u s t o d i o f i l e . isFile () ;
∗ @since 2 0 1 6 . 3 . 2 2 }
∗/ }) ;
public c l a s s Fragment Settings extends // Array o f f i l e names .
PreferenceFragment { f i n a l S t r i n g [ ] names = new S t r i n g [ l i s t .
@O verr ide length ] ;
p u b l i c v o i d o n C r e a t e ( f i n a l Bundle f o r ( i n t i =0; i <names . l e n g t h ; i ++) {
savedInstanceState ) { names [ i ] = l i s t [ i ] . getName ( ) ;
super . onCreate ( s a v e d I n s t a n c e S t a t e ) ; }
a d d P r e f e r e n c e s F r o m R e s o u r c e (R . xml . p r e f e r e n c e s // s e t a d a p t e r f o r l i s t v i e w .
); f i n a l ArrayAdapter<S t r i n g > a d a p t e r = new
// I f t h e r e i s no b u i l t i n s p e l l −c h e c k e r , ArrayAdapter <>( g e t A c t i v i t y ( ) , R . l a y o u t .
disable this preference . alert dialog change language listview row
f i n a l Preference spellchecker = , names ) ;
getPreferenceManager () . findPreference ( ” listView . setAdapter ( adapter ) ;
pref key spell check ”) ; l i s t V i e w . setItemsCanFocus ( f a l s e ) ;
s p e l l c h e c k e r . setEnabled ( A c t i v i t y S e t t i n g s . // Allow m u l t i p l e c h o i c e s .
spellCheckerPresent ) ; l i s t V i e w . setChoiceMode ( ListView .
//On c l i c k l i s t e n e r o f l i c e n s e p r e f e r e n c e . CHOICE MODE MULTIPLE) ;
f i n a l Preference l i c e n se s = // Check t h e c u r r e n t l y u s e d l a n g u a g e .
getPreferenceManager () . findPreference ( ” f i n a l String [ ] initLanguage = L i b r a r i e s .
pref key license ”) ; tesseract . getInitLanguagesAsString () .
l i c e n s e s . s e t O n P r e f e r e n c e C l i c k L i s t e n e r ( new s p l i t ( ”\\+” ) ;
Preference . OnPreferenceClickListener () { f i n a l i n t [ ] i n i t L a n g u a g e P o s = new i n t [
@O verr ide initLanguage . length ] ;
public boolean onPreferenceClick ( Preference
preference ) { int ctr = 0;
// c r e a t e a l e r t d i a l o g // Find t h e p o s i t i o n o f t h e c u r r e n t l y
f i n a l AlertDialog . Builder dialogBuilder = i n i t i a l i z e d l a n g u a g e / s from t h e c h e c k b o x
new A l e r t D i a l o g . B u i l d e r ( g e t A c t i v i t y ( ) ) ; list .
dialogBuilder . setTitle (” Licenses ”) ; f o r ( i n t i = 0 ; i < names . l e n g t h ; i ++) {
// i n f l a t e l a y o u t t o a l e r t D i a l o g i f ( names [ i ] . e q u a l s ( i n i t L a n g u a g e [ c t r ] + ”
f i n a l View l i c e n s e s V i e w = View . i n f l a t e ( . traineddata ”) ) {
g e t A c t i v i t y ( ) , R. layout . initLanguagePos [ c t r ] = i ;
alert dialog licenses , null ) ; i = 0;
d i a l o g B u i l d e r . setView ( l i c e n s e s V i e w ) ; c t r ++;
d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new // A l l o f i n i t i a l i z e d l a n g u a g e / s h a s been
DialogInterface . OnClickListener () { compared
@O verr ide i f ( i n i t L a n g u a g e . l e n g t h <= c t r ) {
public void onClick ( D i a l o g I n t e r f a c e break ;
d i a l o g , i n t which ) { }
dialog . dismiss () ; }
} }
}) ; Log . e ( ” t a g ” , i n i t L a n g u a g e . l e n g t h + ” ” ) ;
// D i s p l a y t h e c r e a t e d d i a l o g B u i l d e r // S e t a l l c h e c k b o x e s t o f a l s e
f i n a l AlertDialog alertDialog = f o r ( i n t i = 0 ; i <names . l e n g t h ; i ++) {
dialogBuilder . create () ; l i s t V i e w . setItemChecked ( i , f a l s e ) ;
a l e r t D i a l o g . show ( ) ; }
return f a l s e ;
} // Check t h e c u r r e n t l y i n i t i a l i z e d language
}) ; / s from t h e c h e c k b o x l i s t .
// on c l i c k l i s t e n e r f o r t e s s e r a c t l a n g u a g e f o r ( i n t initLanguagePosValue :
change p r e f e r e n c e . initLanguagePos ) {
f i n a l P r e f e r e n c e c han geLa ngua ge = l i s t V i e w . setItemChecked (
getPreferenceManager () . findPreference ( ” initLanguagePosValue , true ) ;
pref key change language ”) ; }
ch ange Lang uage . s e t O n P r e f e r e n c e C l i c k L i s t e n e r (
new P r e f e r e n c e . O n P r e f e r e n c e C l i c k L i s t e n e r // I f t h e u s e r p r e s s e d ok .
() { d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
@O verr ide DialogInterface . OnClickListener () {
public boolean onPreferenceClick ( Preference @O verr ide
preference ) { public void onClick ( D i a l o g I n t e r f a c e
// c r e a t e a l e r t d i a l o g . d i a l o g , i n t which ) {
f i n a l AlertDialog . Builder dialogBuilder = f i n a l SparseBooleanArray checkedItems =
new A l e r t D i a l o g . B u i l d e r ( g e t A c t i v i t y ( ) ) ; listView . getCheckedItemPositions () ;
d i a l o g B u i l d e r . s e t T i t l e ( ” S e l e c t Trained S t r i n g language = ”” ;

122
f o r ( i n t i =0; i <l i s t V i e w . g e t A d a p t e r ( ) . BUTTON POSITIVE) . s e t E n a b l e d ( t r u e ) ;
g e t C o u n t ( ) ; i ++) { }
i f ( checkedItems . get ( i ) ) { }
// I f i t s o n l y one , do n o t append + }) ;
sign . return f a l s e ;
i f ( language . equals ( ”” ) ) { }
l a n g u a g e += l i s t V i e w . g e t A d a p t e r ( ) . }) ;
getItem ( i ) ;
} else { //On c l i c k l i s t e n e r f o r h e l p p r e f e r e n c e .
l a n g u a g e += ”+” + l i s t V i e w . g e t A d a p t e r f i n a l Preference help = getPreferenceManager
( ) . getItem ( i ) ; () . findPreference (” pref key help ”) ;
} h e l p . s e t O n P r e f e r e n c e C l i c k L i s t e n e r ( new
} Preference . OnPreferenceClickListener () {
} @O verr ide
// Remove . t r a i n e d d a t a e x t e n s i o n . public boolean onPreferenceClick ( Preference
language = language . r e p l a c e ( ” . preference ) {
traineddata ” , ”” ) ; // C r e a t e a l e r t d i a l o g .
// Save l a n g u a g e t o p r e f e r e n c e t o s a v e f i n a l AlertDialog . Builder dialogBuilder =
t h e v a l u e f o r n e x t s t a r t −up . new A l e r t D i a l o g . B u i l d e r ( g e t A c t i v i t y ( ) ) ;
f i n a l SharedPreferences sharedPreference d i a l o g B u i l d e r . s e t T i t l e ( ” Help ” ) ;
= PreferenceManager . // I n f l a t e l a y o u t t o a l e r t D i a l o g .
getDefaultSharedPreferences ( getActivity () f i n a l View l i c e n s e s V i e w = View . i n f l a t e (
); g e t A c t i v i t y ( ) , R. layout . a l e r t d i a l o g h e l p
sharedPreference . edit () . putString (” , null ) ;
language ” , language ) . apply ( ) ; f i n a l TextView t e x t V i e w = ( TextView )
L i b r a r i e s . t e s s e r a c t = new TessBaseAPI ( ) ; l i c e n s e s V i e w . f i n d V i e w B y I d (R . i d .
// n o i n s p e c t i o n C o n s t a n t C o n d i t i o n s textView help directories description ) ;
Libraries . tesseract . init ( getActivity () . f i n a l S t r i n g d i r e c t o r i e s = ” Ima ges
g e t E x t e r n a l F i l e s D i r ( n u l l ) . getPath ( ) , D i r e c t o r y : ” + D i r e c t o r i e s . IMAGES DIR + ”
language ) ; \n\n”
Libraries . tesseract . setVariable (” + ”PDF and Text D i r e c t o r y : ” +
c l a s s i f y e n a b l e l e a r n i n g ” , ”0” ) ; D i r e c t o r i e s . TEXT DIR + ” \n\n”
Libraries . tesseract . setVariable (” + ” Audio D i r e c t o r y : ” + D i r e c t o r i e s .
c l a s s i f y e n a b l e a d a p t i v e m a t c h e r ” , ”0” ) ; AUDIO DIR ;
dialog . dismiss () ; textView . setText ( d i r e c t o r i e s ) ;
}
}) ; d i a l o g B u i l d e r . setView ( l i c e n s e s V i e w ) ;
// Launch t h e c o m p l e t e d d i a l o g . d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
f i n a l AlertDialog alertDialog = DialogInterface . OnClickListener () {
dialogBuilder . create () ; @O verr ide
a l e r t D i a l o g . show ( ) ; public void onClick ( D i a l o g I n t e r f a c e
a l e r t D i a l o g . setCanceledOnTouchOutside ( d i a l o g , i n t which ) {
false ) ; dialog . dismiss () ;
}
l i s t V i e w . s e t O n I t e m C l i c k L i s t e n e r ( new }) ;
AdapterView . O n I t e m C l i c k L i s t e n e r ( ) { // D i s p l a y t h e c r e a t e d d i a l o g B u i l d e r .
@O verr ide f i n a l AlertDialog alertDialog =
p u b l i c v o i d o n I t e m C l i c k ( AdapterView<?> dialogBuilder . create () ;
p a r e n t , View view , i n t p o s i t i o n , l o n g i d ) a l e r t D i a l o g . show ( ) ;
{ return f a l s e ;
i f ( l i s t V i e w . getC heck edIte mCou nt ( ) == 0 ) }
{ }) ;
a l e r t D i a l o g . getButton ( A l e r t D i a l o g . }
BUTTON POSITIVE) . s e t E n a b l e d ( f a l s e ) ; }
} else {
a l e r t D i a l o g . getButton ( A l e r t D i a l o g .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
ImagePreProcess.java

package anteraaron . t e s s 2 s p e e c h ; f i n a l P a i n t p a i n t = new P a i n t ( ) ;


f i n a l C o l o r M a t r i x m a t r i x = new C o l o r M a t r i x ( )
import android . graphics . Bitmap ; ;
import android . graphics . Canvas ; matrix . s e t S a t u r a t i o n ( 0 ) ;
import android . graphics . ColorMatrix ; f i n a l C o l o r M a t r i x C o l o r F i l t e r f i l t e r = new
import android . graphics . ColorMatrixColorFilter C o l o r M a t r i x C o l o r F i l t e r ( matrix ) ;
; paint . s etC ol orF il te r ( f i l t e r ) ;
import android . g r a p h i c s . Paint ; c a n v a s . drawBitmap ( o r i g , 0 , 0 , p a i n t ) ;
return processed ;
/∗ ∗ }
∗ A c l a s s t h a t c o n t a i n s d i f f e r e n t method f o r
image pre−p r o c e s s i n g /∗ ∗
∗ @author Anter Aaron M. C u s t o d i o ∗ @param o r i g i n p u t bitmap
∗ @since 3 . 2 2 . 2 0 1 6 ∗ @ r e t u r n new bitmap
∗/ ∗/
p u b l i c c l a s s ImagePreProcess { // c o n t r a s t 0 . . 1 0 1 i s d e f a u l t
/∗ ∗ // b r i g h t n e s s − 2 5 5 . . 2 5 5 0 i s d e f a u l t
∗ C o n v e r t s a bitmap t o g r a y s c a l e . p u b l i c s t a t i c Bitmap
∗ @param o r i g t h e bitmap t o be p r o c e s s e d . changeBitmapContrastBrightness ( f i n a l
∗ @ r e t u r n r e t u r n s t h e g r a y s c a l e d bitmap . Bitmap o r i g ) {
∗/ f i n a l f l o a t contrast = 1.85 f ;
p u b l i c s t a t i c Bitmap t o G r a y S c a l e ( f i n a l Bitmap f i n a l f l o a t brightness = 35;
orig ) { f i n a l C o l o r M a t r i x cm = new C o l o r M a t r i x ( new
f i n a l int height = orig . getHeight () ; float []{
f i n a l i n t w i d t h = o r i g . getWidth ( ) ; contrast , 0 , 0 , 0 , brightness ,
// C o n v e r t s image t o g r a y s c a l e by s e t t i n g 0 , contrast , 0 , 0 , brightness ,
matrix s a t u r a t i o n to 0 . 0 , 0 , contrast , 0 , brightness ,
f i n a l Bitmap p r o c e s s e d = Bitmap . c r e a t e B i t m a p 0, 0, 0, 1, 0
( width , h e i g h t , Bitmap . C o n f i g . ARGB 8888 ) ; }) ;
f i n a l Canvas c a n v a s = new Canvas ( p r o c e s s e d ) ;

123
f i n a l Bitmap p r o c e s s e d = Bitmap . c r e a t e B i t m a p C o l o r M a t r i x C o l o r F i l t e r (cm) ) ;
( o r i g . getWidth ( ) , o r i g . g e t H e i g h t ( ) , o r i g . c a n v a s . drawBitmap ( o r i g , 0 , 0 , p a i n t ) ;
getConfig () ) ;
return processed ;
final Canvas c a n v a s = new Canvas ( p r o c e s s e d ) ; }
}
f i n a l P a i n t p a i n t = new P a i n t ( ) ;
p a i n t . s e t C o l o r F i l t e r ( new

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Intent\_BrowseFiles.java

package anteraaron . t e s s 2 s p e e c h ; g e t t e r I n t e n t . s e t T y p e ( ” image /∗ ” ) ;

import a n d r o i d . app . A c t i v i t y ; // Only make t h e s e f i l e s v i s i b l e ( f o r b u i l t


import android . content . ContentResolver ; −i n b r o w s e r o n l y a n d r o i d − f i l e −
import android . content . Intent ; picker activity )\
import android . net . Uri ; // Note t h a t b u i l t i n b r o w s e r d o e s n o t
import android . os . Build ; support m u l t i p l e images
import a n d r o i d . w e b k i t . MimeTypeMap ; g e t t e r I n t e n t . putExtra ( F i l e P i c k e r A c t i v i t y .
import java . io . F i l e ; EXTRA ACCEPTED FILE EXTENSIONS ,
import java . u t i l . ArrayList ; IMAGE EXTENSIONS) ;
import java . u t i l . Arrays ;
import java . u t i l . C o l l e c t i o n s ; // Allow m u l t i p l e image s e l e c t i o n .
g e t t e r I n t e n t . putExtra ( I n t e n t .
import kaloer . f i l e p i c k e r . FilePickerActivity ; EXTRA ALLOW MULTIPLE, t r u e ) ;

/∗ ∗ return getterIntent ;
∗ A c l a s s t h a t c o n t a i n s d i f f e r e n t methods f o r }
browsing f i l e s o f d i f f e r e n t type . }
∗ @author Anter Aaron M. C u s t o d i o
∗ @since 2 0 1 6 . 3 . 2 2 /∗ ∗
∗/ ∗ Launch an i n t e n t f o r b r o w s i n g PDF f i l e
public f i n a l class Intent BrowseFiles { ∗ @ r e t u r n U r i o f PDF f i l e
∗/
// L i s t o f a c c e p t a b l e f i l e f o r m a t s . p u b l i c s t a t i c I n t e n t browsePdf ( ) {
p r i v a t e s t a t i c f i n a l A r r a y L i s t <S t r i n g > f i n a l I n t e n t g e t t e r I n t e n t = new I n t e n t (
IMAGE EXTENSIONS = new A r r a y L i s t <>( I n t e n t . ACTION GET CONTENT) ;
C o l l e c t i o n s . u n m o d i f i a b l e L i s t ( Arrays . g e t t e r I n t e n t . addCategory ( I n t e n t .
a s L i s t ( ” . png ” , ” . j p g ” , ” . j p e g ” , ” . bmp” , ” CATEGORY OPENABLE) ;
. webp” , ” . g i f ” ) ) ) ; g e t t e r I n t e n t . setType ( ” a p p l i c a t i o n / pdf ” ) ;
p r i v a t e s t a t i c f i n a l A r r a y L i s t <S t r i n g >
PDF EXTENSION = new A r r a y L i s t <>( // Only make t h e s e f i l e s v i s i b l e ( f o r b u i l t −
Collections . unmodifiableList ( Collections . i n browser only android−f i l e −
s i n g l e t o n L i s t ( ” . pdf ” ) ) ) ; picker activity )
p r i v a t e s t a t i c f i n a l A r r a y L i s t <S t r i n g > g e t t e r I n t e n t . putExtra ( F i l e P i c k e r A c t i v i t y .
EPUB EXTENSION = new A r r a y L i s t <>( EXTRA ACCEPTED FILE EXTENSIONS ,
Collections . unmodifiableList ( Collections . PDF EXTENSION) ;
s i n g l e t o n L i s t ( ” . epub ” ) ) ) ;
return getterIntent ;
/∗ ∗ }
∗ Launch an i n t e n t f o r b r o w s i n g a s i n g l e
image f i l e . /∗ ∗
∗ @ r e t u r n U r i o f image f i l e ∗ Launch an i n t e n t f o r b r o w s i n g Epub f i l e
∗/ ∗ @ r e t u r n U r i o f Epub f i l e
p u b l i c s t a t i c I n t e n t browseImage ( ) { ∗/
f i n a l I n t e n t g e t t e r I n t e n t = new I n t e n t ( p u b l i c s t a t i c I n t e n t browseEpub ( ) {
I n t e n t . ACTION GET CONTENT) ; f i n a l I n t e n t g e t t e r I n t e n t = new I n t e n t (
g e t t e r I n t e n t . addCategory ( I n t e n t . I n t e n t . ACTION GET CONTENT) ;
CATEGORY OPENABLE) ; g e t t e r I n t e n t . addCategory ( I n t e n t .
g e t t e r I n t e n t . s e t T y p e ( ” image /∗ ” ) ; CATEGORY OPENABLE) ;
g e t t e r I n t e n t . s e t T y p e ( ” a p p l i c a t i o n / epub+z i p ” )
// Only make t h e s e f i l e s v i s i b l e ( f o r b u i l t − ;
i n browser only android−f i l e −
picker activity ) // Only make t h e s e f i l e s v i s i b l e ( f o r b u i l t −
g e t t e r I n t e n t . putExtra ( F i l e P i c k e r A c t i v i t y . i n browser only android−f i l e −
EXTRA ACCEPTED FILE EXTENSIONS , picker activity )
IMAGE EXTENSIONS) ; g e t t e r I n t e n t . putExtra ( F i l e P i c k e r A c t i v i t y .
EXTRA ACCEPTED FILE EXTENSIONS ,
return getterIntent ; EPUB EXTENSION) ;
}
return getterIntent ;
/∗ ∗ }
∗ Launch an i n t e n t f o r b r o w s i n g m u l t i p l e
image f i l e /∗ ∗
∗ @ r e t u r n U r i o f image f i l e s ∗ Checks i f an image U r i i s an a c c e p t e d
∗/ format .
public s t a t i c Intent browseMultipleImages () { ∗ @param i m a g e U r i t h e u r i o f t h e image .
∗ @ r e t u r n t r u e i f t h e f o r m a t o f t h e image
// Browse m u l t i p l e image i s n o t s u p p o r t e d in i s acceptable .
API l e v e l b e l o w 18 ∗/
i f ( B u i l d . VERSION . SDK INT < B u i l d . p u b l i c s t a t i c boolean checkImageExtension (
VERSION CODES . JELLY BEAN MR2) { A c t i v i t y a c t i v i t y , Uri imageUri ) {
r e t u r n browseImage ( ) ; // Get f i l e e x t e n s i o n from u r i .
} else { f i n a l S t r i n g e x t e n s i o n = ” . ” + getMimeType (
// I f API l e v e l > 18 a c t i v i t y , imageUri ) ;
f i n a l I n t e n t g e t t e r I n t e n t = new I n t e n t (
I n t e n t . ACTION GET CONTENT) ; r e t u r n IMAGE EXTENSIONS . c o n t a i n s ( e x t e n s i o n ) ;
g e t t e r I n t e n t . addCategory ( I n t e n t . }
CATEGORY OPENABLE) ;

124
/∗ ∗ ∗ @param u r i t h e u r i t o be d e t e r m i n e d .
∗ Checks i f a PDF U r i i s an a c c e p t e d ∗ @ r e t u r n t h e mime t y p e ( e x t e n s i o n ) o f
format . t h e u r i w i t h o u t ” . ” i . e . ( j p g , bmp ,
∗ @param p d f U r i t h e u r i o f t h e PDF . png ) .
∗ @ r e t u r n t r u e i f t h e f o r m a t o f t h e PDF ∗/
i s acceptable . p u b l i c s t a t i c S t r i n g getMimeType ( A c t i v i t y
∗/ a c t i v i t y , Uri u r i ) {
public s t a t i c boolean checkPdfExtension ( String extension ;
A c t i v i t y a c t i v i t y , Uri pdfUri ) {
// Get f i l e e x t e n s i o n from u r i . // Check u r i f o r m a t t o a v o i d n u l l
f i n a l S t r i n g e x t e n s i o n = ” . ” + getMimeType ( i f ( u r i . getScheme ( ) . e q u a l s ( C o n t e n t R e s o l v e r .
a c t i v i t y , pdfUri ) ; SCHEME CONTENT) ) {
// I f scheme i s a c o n t e n t
r e t u r n PDF EXTENSION . c o n t a i n s ( e x t e n s i o n ) ; f i n a l MimeTypeMap mime = MimeTypeMap .
} getSingleton () ;
e x t e n s i o n = mime . getExtensionFromMimeType (
/∗ ∗ a c t i v i t y . g e t C o n t e n t R e s o l v e r ( ) . getType ( u r i
∗ Checks i f an Epub U r i i s an a c c e p t e d ));
format . } else {
∗ @param e p u b U r i t h e u r i o f t h e Epub . // I f scheme i s a F i l e
∗ @ r e t u r n t r u e i f t h e f o r m a t o f t h e Epub // T h i s w i l l r e p l a c e s p a c e s w i t h %20 and
i s acceptable . a l s o o t h e r s p e c i a l c h a r a c t e r s . This w i l l
∗/ a v o i d r e t u r n i n g n u l l v a l u e s on f i l e name
p u b l i c s t a t i c boolean checkEpubExtension ( w i t h s p a c e s and s p e c i a l c h a r a c t e r s .
A c t i v i t y a c t i v i t y , Uri epubUri ) { e x t e n s i o n = MimeTypeMap .
// Get f i l e e x t e n s i o n from u r i . g e t F i l e E x t e n s i o n F r o m U r l ( U r i . f r o m F i l e ( new
f i n a l S t r i n g e x t e n s i o n = ” . ” + getMimeType ( F i l e ( u r i . getPath ( ) ) ) . t o S t r i n g ( ) ) ;
a c t i v i t y , epubUri ) ;
}
r e t u r n EPUB EXTENSION . c o n t a i n s ( e x t e n s i o n ) ;
} return extension ;
}
/∗ ∗ }
∗ Get mime t y p e of the given uri .

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Intent\_Camera.java

package anteraaron . t e s s 2 s p e e c h ; f i n a l A l e r t D i a l o g . B u i l d e r b u i l d e r = new


AlertDialog . Builder ( context ) ;
import android . app . A l e r t D i a l o g ; b u i l d e r . s e t T i t l e ( ”SD Card n o t mounted ” ) ;
import android . c o n t e n t . Context ; b u i l d e r . s e t M e s s a g e ( ”An SD Card i s n e e d e d t o
import android . content . DialogInterface ; run t h i s a p p l i c a t i o n . P l e a s e i n s e r t o r
import android . content . Intent ; mount an SD c a r d ” ) ;
import android . net . Uri ; builder . setCancelable ( f a l s e ) ;
import android . p r o v i d e r . MediaStore ; b u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
import android . w i d g e t . T o a st ; DialogInterface . OnClickListener () {
@Ov err ide
import java . io . File ; public void onClick ( D i a l o g I n t e r f a c e dialog
import java . i o . IOException ; , i n t which ) {
import java . t e x t . SimpleDateFormat ; dialog . cancel () ;
import java . u t i l . Date ; }
import java . u t i l . Locale ; }) ;

/∗ ∗ f i n a l AlertDialog dialog = builder . create ()


∗ A c l a s s t h a t l a u n c h e s t h e Camera I n t e n t . ;
∗ @author Anter Aaron M. C u s t o d i o d i a l o g . show ( ) ;
∗ @since 2 0 1 6 . 3 . 2 2 return null ;
∗/ }
p u b l i c c l a s s Intent Camera { }
p r i v a t e Context c o n t e x t ;
// C o n s t r u c t o r /∗ ∗
p u b l i c Intent Camera ( f i n a l Context c o n t e x t ) { ∗ Continuation of takePicture ( ) to c r e a t e
t h i s . context = context ; camera i n t e n t .
try { ∗ @ r e t u r n r e t u r n s t h e Camera I n t e n t
// C r e a t e f i l e l o c a t i o n ∗/
f i n a l File imageFile = createImageFile () ; private Intent dispatchTakePictureIntent () {
D i r e c t o r i e s . imageFromCameraUri = U r i . f i n a l I n t e n t c a m e r a I n t e n t = new I n t e n t (
fromFile ( imageFile ) ; M e d i a S t o r e . ACTION IMAGE CAPTURE) ;
} c a t c h ( I O E x c e p t i o n ex ) { // Check f o r camera A c t i v i t y t o h a n d l e i n t e n t
// E r r o r i n c r e a t i n g F i l e i f ( cameraIntent . r e s o l v e A c t i v i t y ( t h i s . context
T o as t . makeText ( t h i s . c o n t e x t , ” E r r o r i n . g e tP a ck a ge M an a g er ( ) ) != n u l l ) {
c r e a t i n g f i l e ! ” , To a s t . LENGTH LONG) . show cameraIntent . putExtra ( MediaStore .
() ; EXTRA OUTPUT, D i r e c t o r i e s .
} imageFromCameraUri ) ;
} return cameraIntent ;
} else {
/∗ ∗ return null ;
∗ C r e a t e t h e camera i n t e n t t o t a k e }
picture . }
∗ @ r e t u r n r e t u r n s t h e Camera I n t e n t
∗/ /∗ ∗
public Intent takePicture () { ∗ C r e a t e s t h e f i l e which w i l l be t h e
// Check i f an SD c a r d i s mounted , e l s e c l o s e c o n t a i n e r o f t h e image t a k e n by t h e
t h e app . camera .
i f ( Directories . checkExternalStorage () ) { ∗ @ r e t u r n r e t u r n s Image F i l e w i t h name a s
return dispatchTakePictureIntent () ; timestamp .
}else{ ∗ @throws I O E x c e p t i o n
// D i s p l a y a l e r t D i a l o g t h a t SD c a r d i s n o t ∗/
mounted p r i v a t e F i l e c r e a t e I m a g e F i l e ( ) throws

125
IOException { + ” ”;
// C r e a t e an image f i l e name r e t u r n new F i l e ( D i r e c t o r i e s . IMAGES DIR +
f i n a l S t r i n g timeStamp = new F i l e . s e p a r a t o r + imageName + ” . j p g ” ) ;
SimpleDateFormat ( ”yyyyMMdd HHmmss” , }
L o c a l e . ENGLISH) . f o r m a t ( new Date ( ) ) ; }
f i n a l S t r i n g imageName = ” TS C ” + timeStamp

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Libraries.java

package anteraaron . t e s s 2 s p e e c h ; c l a s s i f y e n a b l e a d a p t i v e m a t c h e r ” , ”0” ) ;


// I n i t i a l i z e Text t o S p e e c h
i m p o r t a n d r o i d . app . A c t i v i t y ; t t s = new TextToSpeech ( a c t i v i t y , t h i s ) ;
i m p o r t a n d r o i d . app . A l e r t D i a l o g ;
import android . content . D i a l o g I n t e r f a c e ; }
import android . content . I n t e n t ;
import android . content . S h a r e d P r e f e r e n c e s ; /∗ ∗
import android . net . Uri ; ∗ U s e s Android PDF−View L i b r a r y t o
import android . os . Build ; d i s p l a y PDF t o imageView .
import android . p r e f e r e n c e . PreferenceManager ; ∗ @param u r i PDF t o be d i s p l a y e d ’ s u r i .
i m p o r t a n d r o i d . s p e e c h . t t s . TextToSpeech ; ∗/
import android . speech . t t s . p u b l i c s t a t i c void displayPdf ( f i n a l Uri u r i ) {
UtteranceProgressListener ; // Workaround t o a c c e s s f i l e v i a u r i
i m p o r t a n d r o i d . v i e w . View ; new T a s k F i l e F r o m U r i ( a c t i v i t y , ” c a c h e . p d f ” ,
import android . widget . EditText ; new T a s k F i l e F r o m U r i . AsyncResponse ( ) {
import android . widget . LinearLayout ; @O verr ide
i m p o r t a n d r o i d . w i d g e t . RadioButton ; public void processFinished ( F i l e f i l e ) {
i m p o r t a n d r o i d . w i d g e t . RadioGroup ; pdfPath = f i l e . getPath ( ) ;
i m p o r t a n d r o i d . w i d g e t . T o a st ; pdfView . f r o m F i l e ( f i l e )
i m p o r t com . g o o g l e c o d e . t e s s e r a c t . a n d r o i d . . defaultPage (1)
TessBaseAPI ; . showMinimap ( f a l s e )
i m p o r t com . j o a n z a p a t a . p d f v i e w . PDFView ; . onPageChange ( new O n P a g e C h a n g e L i s t e n e r ( )
i m p o r t com . j o a n z a p a t a . p d f v i e w . l i s t e n e r . {
OnPageChangeListener ; @O verr ide
i m p o r t com . p o l i t e s . a n d r o i d . Gesture ImageView ; p u b l i c v o i d onPageChanged ( i n t page , i n t
i m p o r t o r g . a p a c h e . commons . i o . F i l e U t i l s ; pageCount ) {
import java . i o . F i l e ; // D i s p l a y c u r r e n t page and page number
import java . i o . IOException ; S t r i n g c u r r e n t P a g e = page + ” / ” +
import java . u t i l . ArrayList ; pageCount ;
import java . u t i l . Locale ; Fragment PdfViewer . t e x t V i e w p d f .
setText ( currentPage ) ;
/∗ ∗ }
∗ C l a s s that c o n t a i n s a l l the l i b r a r i e s used })
in the Tess2Speech a p p l i c a t i o n . enableSwipe ( true )
∗ @author Anter Aaron M. C u s t o d i o . load () ;
∗ @since 3 . 2 2 . 2 0 1 6 pdfView . s e t V e r t i c a l S c r o l l B a r E n a b l e d ( t r u e ) ;
∗/ }
p u b l i c c l a s s L i b r a r i e s i m p l e m e n t s TextToSpeech }) . execute ( u r i ) ;
. OnInitListener { }

p u b l i c s t a t i c TextToSpeech t t s ; // Text t o /∗ ∗
S p e e c h ( Android B u i l t i n ) ∗ U s e s VuDroid L i b r a r y ( t h i s i s i n c l u d e d
p u b l i c s t a t i c TessBaseAPI t e s s e r a c t ; // Image i n PDFView l i b r a r y ) t o c o n v e r t p d f
t o Text L i b r a r y t o image
p u b l i c s t a t i c PDFView pdfView ; // L i b r a r y t o ∗ @param u r i PDF ’ s u r i
v i e w PDF f i l e t o image v i e w ∗/
p u b l i c s t a t i c GestureImageView imageView ; // p u b l i c s t a t i c v o i d pdfToImage ( f i n a l U r i u r i )
L i b r a r y f o r z o o m a b l e imageView {
private static Activity activity ;
p r i v a t e s t a t i c S t r i n g path ; // c o n t a i n e r o f displayPdf ( uri ) ;
f i l e paths
p r i v a t e s t a t i c S t r i n g p d f P a t h ; // F i l e p a t h s toImage = t r u e ;
of the pdfs f i n a l E d i t T e x t e d i t T e x t i n p u t = new E d i t T e x t
p r i v a t e s t a t i c S t r i n g d i r ; // F i l e path f o r ( activity ) ;
c o n v e r t e d p d f t o image d i r e c t o r y
p r i v a t e s t a t i c b o o l e a n p l a y ; // D e t e r m i n e s i f // c r e a t e a l e r t d i a l o g
PdfToText i s c a l l e d w i t h t h e i n t e n t t o f i n a l AlertDialog . Builder dialogBuilder =
play new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) ;
p r i v a t e s t a t i c b o o l e a n t o I m a g e ; // D e t e r m i n e s d i a l o g B u i l d e r . s e t T i t l e ( ” Create Folder ” ) ;
i f PdfToText i s c a l l e d w i t h t h e i n t e n t t o d i a l o g B u i l d e r . s e t M e s s a g e ( ” F o l d e r name where
play c o n v e r t e d i m a g e s w i l l be s a v e d : ” ) ;
p r i v a t e s t a t i c A r r a y L i s t <I n t e g e r > p a g e s ; //Add e d i t t e x t t o a l e r t d i a l o g
f i n a l L i n e a r L a y o u t . LayoutParams l p = new
// C o n s t r u c t o r L i n e a r L a y o u t . LayoutParams ( L i n e a r L a y o u t .
public Libraries ( Activity activity parameter LayoutParams .MATCH PARENT, L i n e a r L a y o u t .
) { LayoutParams .MATCH PARENT) ;
activity = activity parameter ; e d i t T e x t i n p u t . setLayoutParams ( l p ) ;
// I n s t a n t i a t e T e s s e r a c t d i a l o g B u i l d e r . setView ( e d i t T e x t i n p u t ) ;
t e s s e r a c t = new TessBaseAPI ( ) ;
// I n i t i a l i z e T e s s e r a c t ’ s l a n g u a g e // S e t a c t i o n f o r a l e r t d i a l o g
f i n a l SharedPreferences sharedPreference = d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
PreferenceManager . DialogInterface . OnClickListener () {
getDefaultSharedPreferences ( activity ) ; @O verr ide
// n o i n s p e c t i o n C o n s t a n t C o n d i t i o n s public void onClick ( D i a l o g I n t e r f a c e dialog ,
tesseract . init ( activity . getExternalFilesDir ( i n t which ) {
n u l l ) . getPath ( ) , s h a r e d P r e f e r e n c e . c r e a t e F o l d e r ( e d i t T e x t i n p u t . getText ( ) .
g e t S t r i n g ( ” l a n g u a g e ” , ” eng+engh ” ) ) ; toString () ) ;
tesseract . setVariable (” }
c l a s s i f y e n a b l e l e a r n i n g ” , ”0” ) ; }) ;
tesseract . setVariable (” d i a l o g B u i l d e r . setNegativeButton ( ” Cancel ” ,

126
new D i a l o g I n t e r f a c e . O n C l i c k L i s t e n e r ( ) { d i a l o g B u i l d e r . s e t T i t l e ( ” C o n v e r t PDF t o Text ”
@O verr ide );
public void onClick ( D i a l o g I n t e r f a c e dialog , d i a l o g B u i l d e r . s e t M e s s a g e ( ” Pages t o C o n v e r t :
i n t which ) { ”) ;
dialog . dismiss () ; f i n a l View p a g e S e l e c t V i e w = View . i n f l a t e (
T oa s t . makeText ( a c t i v i t y , ” C o n v e r t t o image a c t i v i t y , R. layout .
c a n c e l l e d ” , T o a st . LENGTH LONG) . show ( ) ; alert dialog page select , null ) ;
} d i a l o g B u i l d e r . setView ( pageSelectView ) ;
}) ; // C r e a t e r a d i o g r o u p .
f i n a l RadioGroup r a d i o G r o u p = ( RadioGroup )
// Show t h e c r e a t e d d i a l o g B u i l d e r . p a g e S e l e c t V i e w . f i n d V i e w B y I d (R . i d .
f i n a l AlertDialog alertDialog = radioGroup pdf ) ;
dialogBuilder . create () ; r a d i o G r o u p . s e t O n C h e c k e d C h a n g e L i s t e n e r ( new
a l e r t D i a l o g . show ( ) ; RadioGroup . O n C h e c k e d C h a n g e L i s t e n e r ( ) {
} @O verr ide
p u b l i c v o i d onCheckedChanged ( RadioGroup
/∗ ∗ group , i n t c h e c k e d I d ) {
∗ U s e s VuDroid L i b r a r y ( t h i s i s i n c l u d e d f i n a l EditText e d i t T e x t p d f = ( EditText )
i n PDFView l i b r a r y ) t o c o n v e r t p d f p a g e S e l e c t V i e w . f i n d V i e w B y I d (R . i d .
t o image , t h e n u s e s t e s s e r a c t t o editText pdf ) ;
recognize texts i f ( c h e c k e d I d == R . i d . r a d i o B u t t o n p d f a l l )
∗ @param p l a y p a r a m P l a y t h e c o n v e r t e d {
image i f t h i s p a r a m e t e r i s s e t t o // A l l r a d i o Button
true . editText pdf . setEnabled ( f a l s e ) ;
∗/ editText pdf . setHint ( ”” ) ;
p u b l i c s t a t i c v o i d pdfToText ( f i n a l b o o l e a n e d i t T e x t p d f . setFocusableInTouchMode (
play param ) { false ) ;
toImage = f a l s e ; editText pdf . clearFocus () ;
play = play param ; } e l s e i f ( c h e c k e d I d == R . i d .
path = p d f P a t h ; radioButton pdf select ) {
selectPageDialog () ; // S p e c i f y p a g e s r a d i o b u t t o n .
} editText pdf . setEnabled ( true ) ;
e d i t T e x t p d f . s e t H i n t ( ” Pages e . g . 1 , 2 , 5 , 1 2
/∗ ∗ ”) ;
∗ C r e a t e s a f o l d e r i n which t h e c o n v e r t e d e d i t T e x t p d f . setFocusableInTouchMode ( t r u e
p a g e s o f t h e p d f t o image w i l l be );
stored . editText pdf . requestFocus () ;
∗ @param f o l d e r N a m e Name o f t h e f o l d e r }
t h a t w i l l be c r e a t e d }
∗/ }) ;
private s t a t i c void createFolder ( f i n a l String // S e t a c t i o n f o r a l e r t d i a l o g .
folderName ) { d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
DialogInterface . OnClickListener () {
try { @O verr ide
// S e t f i l e d i r e c t o r y public void onClick ( D i a l o g I n t e r f a c e dialog ,
d i r = D i r e c t o r i e s . IMAGES DIR + F i l e . i n t which ) {
s e p a r a t o r + folderName ; processInput ( pageSelectView ) ;
f i n a l F i l e f i l e = new F i l e ( d i r ) ; pdfToImageProcess ( ) ;
// I f f i l e e x i s t s , prompt o v e r w r i t e d i a l o g }
box }) ;
i f ( f i l e . e x i s t s ( ) && f i l e . i s D i r e c t o r y ( ) ) { // S e t a c t i o n f o r c a n c e l .
new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) d i a l o g B u i l d e r . setNegativeButton ( ” Cancel ” ,
. s e t T i t l e ( ” Folder already e x i s t ” ) new D i a l o g I n t e r f a c e . O n C l i c k L i s t e n e r ( ) {
. setMessage ( ” F i l e s i n s i d e the f o l d e r @O verr ide
w i l l be o v e r w r i t t e n . O v e r w r i t e ? ” ) public void onClick ( D i a l o g I n t e r f a c e dialog ,
//Ok button , O v e r w r i t e e x i s t i n g f i l e i n t which ) {
. s e t P o s i t i v e B u t t o n ( ” Yes ” , new dialog . dismiss () ;
DialogInterface . OnClickListener () { T oa s t . makeText ( a c t i v i t y , ” C o n v e r t
public void onClick ( D i a l o g I n t e r f a c e c a n c e l l e d ” , T o a st . LENGTH LONG) . show ( ) ;
d i a l o g , i n t which ) { }
path = p d f P a t h ; }) ;
selectPageDialog () ;
} // Show t h e c r e a t e d d i a l o g b u i l d e r .
}) f i n a l AlertDialog alertDialog =
// C a n c e l Button , d i s m i s s d i a l o g box dialogBuilder . create () ;
. s e t N e g a t i v e B u t t o n ( ”No” , new a l e r t D i a l o g . setCanceledOnTouchOutside ( f a l s e )
DialogInterface . OnClickListener () { ;
public void onClick ( D i a l o g I n t e r f a c e a l e r t D i a l o g . show ( ) ;
d i a l o g , i n t which ) { }
dialog . dismiss () ;
T o as t . makeText ( a c t i v i t y , ” C o n v e r t t o /∗ ∗
image c a n c e l l e d ” , To a s t . LENGTH LONG) . show ∗ P r o c e s s u s e r i n p u t on p a g e s t o be
() ; converted .
} ∗ @param p a g e S e l e c t V i e w P a g e S e l e c t V i e w
}) that contains the radioButtons .
. show ( ) ∗/
. setCanceledOnTouchOutside ( f a l s e ) ; p r i v a t e s t a t i c v o i d p r o c e s s I n p u t ( f i n a l View
} else { pageSelectView ) {
// n o i n s p e c t i o n R e s u l t O f M e t h o d C a l l I g n o r e d
f i l e . mkdirs ( ) ; if ( ( ( RadioButton ) p a g e S e l e c t V i e w .
selectPageDialog () ; f i n d V i e w B y I d (R . i d . r a d i o B u t t o n p d f a l l ) ) .
} isChecked ( ) ) {
} catch ( Exception e ) { // I f a l l i s c h e c k e d , s a v e a l l t h e p a g e s t o
//An e r r o r h a s o c c u r e d w h i l e s a v i n g arraylist .
T o as t . makeText ( a c t i v i t y , ” E r r o r i n p a g e s = new A r r a y L i s t <>() ;
C o n v e r t i n g PDF t o image ! ” , T oa s t . f o r ( i n t i =0; i <pdfView . getPageCount ( ) ; i
LENGTH SHORT) . show ( ) ; ++) {
} p a g e s . add ( i ) ;
} }
} else {
/∗ ∗ // E l s e , s a v e o n l y t h e s p e c i f i e d p a g e s t o
∗ C r e a t e s a d i a l o g t h a t prompts t h e u s e r arraylist .
t o s e l e c t which p a g e s t h e y would
l i k e to process . // S p l i t t e x t i n p u t t e d by u s e r by comma
∗/ f i n a l E d i t T e x t e d i t T e x t p d f =( E d i t T e x t )
private s t a t i c void selectPageDialog () { p a g e S e l e c t V i e w . f i n d V i e w B y I d (R . i d .
// C r e a t e a l e r t d i a l o g . editText pdf ) ;
f i n a l AlertDialog . Builder dialogBuilder = f i n a l String [ ] pagesString = editText pdf .
new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) ; g e t T e x t ( ) . t o S t r i n g ( ) . s p l i t ( ” \\ s ∗ , \ \ s ∗ ” ) ;

127
// C o n v e r t p a g e s t o i n t );
p a g e s = new A r r a y L i s t <>() ; } catch ( IOException e ) {
f o r ( S t r i n g page : p a g e s S t r i n g ) { e . printStackTrace () ;
i f ( ! page . e q u a l s ( ” ” ) && I n t e g e r . p a r s e I n t ( }
page ) > 0 ) { }
p a g e s . add ( I n t e g e r . p a r s e I n t ( page ) − 1 ) ;
} /∗ ∗
} ∗ Send b r o a d c a s t t o t h e g a l l e r y t o show
// Remove p a g e s which a r e g r e a t e r than t h e the taken p i c t u r e in the g a l l e r y .
max # o f p a g e s ∗ @param u r i u r i o f t h e image t h a t w i l l
f i n a l i n t max = pdfView . getPageCount ( ) ; be added t o g a l l e r y .
f o r ( i n t i =0; i <p a g e s . s i z e ( ) ; i ++) { ∗/
i f ( p a g e s . g e t ( i ) + 1 > max ) { p u b l i c s t a t i c void galleryAddPic ( f i n a l Uri
p a g e s . remove ( i ) ; uri ){
i = 0; i f ( B u i l d . VERSION . SDK INT >= B u i l d .
} VERSION CODES . KITKAT) {
} // For k i t k a t and newer v e r s i o n
} f i n a l I n t e n t i n t e n t = new I n t e n t ( I n t e n t .
ACTION MEDIA SCANNER SCAN FILE , u r i ) ;
} a c t i v i t y . sendBroadcast ( i n t e n t ) ;
} else {
/∗ ∗ // For J e l l y b e a n and b e l o w
∗ C o n t i n u a t i o n o f PdfToImage ( ) . The a c t i v i t y . s e n d B r o a d c a s t ( new I n t e n t ( I n t e n t .
p r o c e s s b e h i n d c o n v e r s i o n o f Pdf t o ACTION MEDIA MOUNTED, u r i ) ) ;
image . }
∗/ }
p r i v a t e s t a t i c void pdfToImageProcess ( ) {
i f ( pages . s i z e ( ) > 0) { /∗ ∗
// While t h e r e a r e p a g e s , s e t s w i t c h append ∗ I n i t i a l i z e text to speech l i b r a r y .
to true . ∗ @param s t a t u s S t a t u s o f t h e TTS . E u t h e r
Fragment ConvertedText . switch append . Success or f a i l .
setChecked ( true ) ; ∗/
// C a l l s AsyncTask t h a t c o n v e r t s PdfToImage @O verr ide
new Task PdfToImage ( a c t i v i t y , new public void onInit ( f i n a l i n t status ) {
Task PdfToImage . AsyncResponse ( ) { i f ( s t a t u s == TextToSpeech . SUCCESS) {
@Ov err ide t t s . s e t O n U t t e r a n c e P r o g r e s s L i s t e n e r ( new
public void processFinished ( F i l e f i l e ) { UtteranceProgressListener () {
i f ( p a g e s . s i z e ( ) == 1 ) { @Ov err ide
i f ( toImage ) { public void onStart ( String utteranceId ) {
// I f t h e u s e r s e l e c t s o n l y t o image , do a c t i v i t y . runOnUiThread ( new Runnable ( ) {
not c o n v e r t to t e x t . @O verr ide
saveConvertedImage ( f i l e , pages . get ( 0 ) + p u b l i c v o i d run ( ) {
1) ; // s e t b u t t o n l a b e l t o s t o p
} else { Activity Main . button play .
// E l s e c o n v e r t i t t o t e x t and append t o setCompoundDrawablesWithIntrinsicBounds
previous pages . ( 0 , R . mipmap . i c a c t i o n p l a y b a c k s t o p , 0 ,
new ToText ( a c t i v i t y ) . e x e c u t e ( U r i . 0) ;
fromFile ( f i l e ) , play ) ; A c t i v i t y M a i n . b u t t o n p l a y . s e t T e x t (R .
} string . button stop ) ;
// D i s p l a y where t h e c o n v e r t e d p d f t o
image i s s a v e d // D i s a b l e b u t t o n s t o a v o i d b u t t o n
i f ( d i r != n u l l && ! d i r . isEmpty ( ) ) { mashing
T o as t . makeText ( a c t i v i t y , ” Ima ges s a v e d Activity Main . button text . setEnabled (
t o : ” + d i r , To a s t . LENGTH LONG) . show ( ) ; false ) ;
} Activity Main . button text .
} else { setClickable ( false ) ;
i f ( toImage ) { }
saveConvertedImage ( f i l e , pages . get ( 0 ) + }) ;
1) ; }
} else {
new ToText ( a c t i v i t y ) . e x e c u t e ( U r i . @Ov err ide
fromFile ( f i l e ) , f a l s e ) ; p u b l i c v o i d onDone ( S t r i n g u t t e r a n c e I d ) {
} a c t i v i t y . runOnUiThread ( new Runnable ( ) {
} @O verr ide
p a g e s . remove ( 0 ) ; p u b l i c v o i d run ( ) {
pdfToImageProcess ( ) ; // Change b u t t o n t o p l a y a f t e r TTS h a s
Fragment ConvertedText . switch append . stopped playing
setChecked ( f a l s e ) ; Activity Main . button play .
setCompoundDrawablesWithIntrinsicBounds
} ( 0 , R . mipmap . i c a c t i o n p l a y b a c k p l a y , 0 ,
} ) . e x e c u t e ( path , pages . get (0) ) ; 0) ;
} A c t i v i t y M a i n . b u t t o n p l a y . s e t T e x t (R .
} string . button play ) ;

/∗ ∗ //Re−e n a b l e b u t t o n s
∗ Save t h e c o n v e r t e d image from c a c h e t o Activity Main . button text . setEnabled (
the created f o l d e r . true ) ;
∗ @param f i l e S o u r c e t h e f i l e path where Activity Main . button text . setClickable (
i t was true ) ;
∗/ }
p r i v a t e s t a t i c void saveConvertedImage ( f i n a l }) ;
F i l e f i l e S o u r c e , i n t page ) { }
int ctr = 0;
F i l e f i l e D e s t i n a t i o n = new F i l e ( d i r + F i l e . @Ov err ide
s e p a r a t o r + ” Page ” + page + ” . png ” ) ; p u b l i c void onError ( S t r i n g utteranceId ) {
// I f f i l e name e x i s t s , i t e r a t e c t r t o make
f i l e name u n i q u e . }
while ( f i l e D e s t i n a t i o n . e x i s t s () ) { }) ;
c t r ++; f i n a l i n t r e s u l t = t t s . setLanguage ( Locale .
f i l e D e s t i n a t i o n = new F i l e ( d i r + F i l e . US) ;
s e p a r a t o r + ” Page ” + page + ” ( ” + c t r + // c h e c k i f l a n g u a g e i s s u p p o r t e d
” ) ” + ” . png ” ) ; i f ( r e s u l t == TextToSpeech .
} LANG MISSING DATA | | r e s u l t ==
try { TextToSpeech . LANG NOT SUPPORTED) {
// Copy f i l e from c a c h e t o s a v e d i r u s i n g T oa s t . makeText ( a c t i v i t y , ” Language n o t
Apache Commons i o s u p p o r t e d ” , T o as t . LENGTH LONG) . show ( ) ;
F i l e U t i l s . copyFile ( fileSource , }
fileDestination ) ; }else{
galleryAddPic ( Uri . fromFile ( f i l e D e s t i n a t i o n ) T o as t . makeText ( a c t i v i t y , ” I n i t i a l i z a t i o n

128
F a i l e d ” , T o as t . LENGTH LONG) . show ( ) ; }
activity . finish () ; }
t t s . shutdown ( ) ;
}

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_CopyAssets.java

package anteraaron . t e s s 2 s p e e c h ; copying of the a s s e t f i l e to


tessdata folder
import android . app . A c t i v i t y ; ∗/
import android . c o n t e n t . r e s . AssetManager ; private s t a t i c void s t a r t () {
import android . o s . AsyncTask ; f i n a l AssetManager a s s e t M a n a g e r = a c t i v i t y .
import android . u t i l . Log ; getAssets () ;
import android . v i e w . View ; String [ ] f i l e s = null ;
import android . v i e w . a n i m a t i o n . AlphaAnimation ; // Load a s s e t s l i s t .
import android . v i e w . a n i m a t i o n . Animation ; try {
import android . w i d g e t . TextView ; f i l e s = assetManager . l i s t ( ”” ) ;
import android . w i d g e t . T o a st ; } catch ( IOException e ) {
import java . io . File ; T o as t . makeText ( a c t i v i t y , ” F a i l e d t o l o a d
import java . io . FileOutputStream ; a s s e t l i s t ” , T oa s t . LENGTH SHORT) . show ( ) ;
import java . io . IOException ; }
import java . io . InputStream ;
import java . io . OutputStream ; i f ( f i l e s != n u l l ) {
// Copy f i l e s i n s i d e t h e a s s e t f o l d e r t o
/∗ ∗ tessdata folder
∗ An AsyncTask t h a t c o p i e s t h e f i l e s from t h e for ( f i n a l String filename : f i l e s ) {
a s s e t f o l d e r t o t h e SD c a r d . InputStream i n = n u l l ;
∗ @author Anter Aaron M. C u s t o d i o OutputStream o u t = n u l l ;
∗ @since 2 0 1 6 . 3 . 2 2
∗/ try {
p u b l i c c l a s s T a s k C o p y A s s e t s e x t e n d s AsyncTask // o n l y copy f i l e s t h a t h a s . t r a i n e d d a t a
<Void , Void , Void> { i n f i l e name
private static Activity activity ; i f ( filename . contains (” . traineddata ”) ) {
p r i v a t e AsyncResponse d e l e g a t e ; i n = a s s e t M a n a g e r . open ( f i l e n a m e ) ;
p r i v a t e TextView t e x t V i e w s p l a s h ; f i n a l F i l e o u t F i l e = new F i l e ( a c t i v i t y .
// C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e getExternalFilesDir (” tessdata ”) , filename
AsyncTask i s f i n i s h e d . );
p u b l i c i n t e r f a c e AsyncResponse { o u t = new F i l e O u t p u t S t r e a m ( o u t F i l e ) ;
void processFinished () ; c o p y F i l e ( in , out ) ;
} }
} catch ( IOException e ) {
p u b l i c Task CopyAssets ( f i n a l A c t i v i t y T o as t . makeText ( a c t i v i t y , ” F a i l e d t o copy
a c t i v i t y , f i n a l AsyncResponse d e l e g a t e ) { a s s e t l i s t : ” + f i l e n a m e , To a s t .
Task CopyAssets . a c t i v i t y = a c t i v i t y ; LENGTH SHORT) . show ( ) ;
this . delegate = delegate ; } finally {
// C r e a t e t h e l o a d i n g t e x t i n s p l a s h s c r e e n .
t h i s . t e x t V i e w s p l a s h = ( TextView ) a c t i v i t y . i f ( i n != n u l l ) {
f i n d V i e w B y I d (R . i d . t e x t V i e w s p l a s h ) ; try {
} in . close () ;
} catch ( IOException e ) {
@O verr ide Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e
p r o t e c t e d void onPreExecute ( ) { );
//Make TextView b l i n k w h i l e c o p y i n g f i l e s . }
t h i s . t e x t V i e w s p l a s h . s e t V i s i b i l i t y ( View . }
VISIBLE ) ; i f ( o u t != n u l l ) {
f i n a l Animation anim = new AlphaAnimation try {
(0.0 f , 1.0 f ) ; out . c l o s e ( ) ;
anim . s e t D u r a t i o n ( 5 0 0 ) ; //You can manage t h e } catch ( IOException e ) {
b l i n k i n g time with t h i s parameter Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e
anim . s e t S t a r t O f f s e t ( 2 0 ) ; );
anim . setRepeatMode ( Animation . REVERSE) ; }
anim . s e t R e p e a t C o u n t ( Animation . INFINITE ) ; }
// S t a r t b l i n k i n g a n i m a t i o n
t h i s . t e x t V i e w s p l a s h . s t a r t A n i m a t i o n ( anim ) ; }
} }
}
@O verr ide }
p r o t e c t e d Void doInBackground ( f i n a l Void . . .
params ) { /∗ ∗
start () ; ∗ The p r o c e s s o f c o p y i n g a s i n g l e f i l e .
return null ; ∗ @param i n I n p u t S t r e a m
} ∗ @param o u t OutputStream
∗ @throws I O E x c e p t i o n
@O verr ide ∗/
p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void param private s t a t i c void copyFile ( f i n a l
) { I n p u t S t r e a m i n , f i n a l OutputStream o u t )
//End a n i m a t i o n when c o p y i n g i s f i n i s h e d . throws IOException {
t h i s . textView splash . clearAnimation () ; f i n a l b y t e [ ] b u f f e r = new b y t e [ 1 0 2 4 ] ;
t h i s . t e x t V i e w s p l a s h . s e t V i s i b i l i t y ( View .
INVISIBLE ) ; i n t read ;
// Use i n t e r f a c e when p r o c e s s i s f i n i s h e d . w h i l e ( ( r e a d = i n . r e a d ( b u f f e r ) ) != −1){
this . delegate . processFinished () ; out . w r i t e ( b u f f e r , 0 , read ) ;
s u p e r . o n P o s t E x e c u t e ( param ) ; }
} }
}
/∗ ∗
∗ Method t h a t s t a r t s and p e r f o r m s t h e

129
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_FileFromUri.java

package anteraaron . t e s s 2 s p e e c h ; f i n a l F i l e f i l e = new F i l e ( t h i s . a c t i v i t y .


getCacheDir ( ) + F i l e . s e p a r a t o r + t h i s .
import android . app . A c t i v i t y ; cacheName ) ;
import android . app . P r o g r e s s D i a l o g ; FileOutputStream out ;
import android . c o n t e n t . pm . A c t i v i t y I n f o ; InputStream i n ;
import android . net . Uri ; try {
import android . o s . AsyncTask ; o u t = new F i l e O u t p u t S t r e a m ( f i l e , f a l s e ) ;
import android . u t i l . Log ; // g e t u r i f i l e v i a i n p u t s t r e a m
import java . io . File ; in = a c t i v i t y . getContentResolver () .
import java . io . FileOutputStream ; o p e n I n p u t S t r e a m ( ( U r i ) params [ 0 ] ) ;
import java . io . IOException ; // copy f i l e
import java . io . InputStream ; f i n a l b y t e [ ] b u f f e r = new b y t e [ 1 0 2 4 ] ;
a s s e r t i n != n u l l ;
/∗ ∗ i n t length = in . read ( b u f f e r ) ;
∗ A AsyncTask which i s a workaround f o r w h i l e ( l e n g t h != −1) {
g e t t i n g a F i l e from U r i . out . w r i t e ( b u f f e r , 0 , l e n g t h ) ;
∗ S a v e s t h e f i l e from u r i t o a c a c h e and length = in . read ( b u f f e r ) ;
r e t u r n s the f i l e o b j e c t via i n t e r f a c e . }
∗ @author Anter Aaron M. C u s t o d i o out . c l o s e ( ) ;
∗ @since 2 0 1 6 . 3 . 2 2 } catch ( IOException e ) {
∗/ Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;
p u b l i c c l a s s Task FileFromUri extends }
AsyncTask<O b j e c t , Void , F i l e > { return f i l e ;
private Activity activity ; }
p r i v a t e AsyncResponse d e l e g a t e ;
p r i v a t e S t r i n g cacheName ; @O verr ide
private ProgressDialog progressDialog ; p r o t e c t e d void onPostExecute ( f i n a l F i l e f i l e )
// C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e {
AsyncTask i s f i n i s h e d . super . onPostExecute ( f i l e ) ;
p u b l i c i n t e r f a c e AsyncResponse { // c a n c e l t h e p r o g r e s s d i a l o g a f t e r c r e a t i n g
void processFinished ( f i n a l F i l e f i l e ) ; cache .
} this . delegate . processFinished ( f i l e ) ;
// C o n s t r u c t o r activity . setRequestedOrientation (
p u b l i c Task FileFromUri ( f i n a l A c t i v i t y ActivityInfo .
a c t i v i t y , f i n a l S t r i n g cacheName , f i n a l SCREEN ORIENTATION UNSPECIFIED) ;
AsyncResponse d e l e g a t e ) { this . progressDialog . cancel () ;
this . activity = activity ; this . progressDialog . dismiss () ;
t h i s . cacheName = cacheName ; }
this . delegate = delegate ; /∗ ∗
} ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
@O verr ide w h i l e t h e r e i s a background t a s k .
p r o t e c t e d void onPreExecute ( ) { ∗/
activity . setRequestedOrientation ( private void createDialog () {
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
; this . activity ) ;
// S t a r t P r o g r e s s D i a l o g this . progressDialog . setCancelable ( f a l s e ) ;
createDialog () ; this . progressDialog .
} setCanceledOnTouchOutside ( f a l s e ) ;
t h i s . p r o g r e s s D i a l o g . s e t M e s s a g e ( ” Opening F i l e
@O verr ide . . . ”) ;
p r o t e c t e d F i l e doInBackground ( f i n a l O b j e c t . . . t h i s . p r o g r e s s D i a l o g . show ( ) ;
params ) { }
// C r e a t e s f i l e i n c a c h e d i r e c t o r y i n which }
t h e f i l e from u r i w i l l be s a v e d

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_PdfToImage.java

package anteraaron . t e s s 2 s p e e c h ; ∗/
p u b l i c c l a s s Task PdfToImage e x t e n d s AsyncTask
import a n d r o i d . app . A c t i v i t y ; <O b j e c t , Void , Void> {
import a n d r o i d . app . P r o g r e s s D i a l o g ; private Activity activity ;
import a n d r o i d . c o n t e n t . pm . A c t i v i t y I n f o ; private File f i l e ;
import a n d r o i d . g r a p h i c s . Bitmap ; p r i v a t e Bitmap bitmap ;
import a n d r o i d . g r a p h i c s . RectF ; p r i v a t e AsyncResponse d e l e g a t e ;
import a n d r o i d . o s . AsyncTask ; private ProgressDialog progressDialog ;
import a n d r o i d . u t i l . Log ; // C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e
import org . vudroid . p d f d r o i d . codec . PdfContext ; AsyncTask i s f i n i s h e d .
import o r g . v u d r o i d . p d f d r o i d . c o d e c . PdfDocument ; p u b l i c i n t e r f a c e AsyncResponse {
import o r g . v u d r o i d . p d f d r o i d . c o d e c . PdfPage ; void processFinished ( f i n a l F i l e f i l e ) ;
import java . io . F i l e ; }
import java . i o . FileOutputStream ; p u b l i c Task PdfToImage ( f i n a l A c t i v i t y
import java . i o . IOException ; a c t i v i t y , f i n a l AsyncResponse d e l e g a t e ) {
this . activity = activity ;
/∗ ∗ this . delegate = delegate ;
∗ An AsyncTask t h a t c o n v e r t s PDF t o Image }
u s i n g VuDroid from a n d r o i d −pdfView ( S e e
. . h t t p s : / / g i t h u b . com/ JoanZapata / a n d r o i d @O verr ide
−p d f v i e w ) . p r o t e c t e d void onPreExecute ( ) {
∗ @author Anter Aaron M. C u s t o d i o activity . setRequestedOrientation (
∗ @since 2 0 1 6 . 3 . 2 2 A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR)

130
; } catch ( IOException e ) {
// S t a r t P r o g r e s s Dialog Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;
createDialog () ; }
} return null ;
}
@O verr ide
p r o t e c t e d Void doInBackground ( f i n a l O b j e c t . . . @O verr ide
param ) { p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void param
// I n i t i a l i z e P d f C o n t e x t ) {
f i n a l P d f C o n t e x t p d f C o n t e x t = new P d f C o n t e x t s u p e r . o n P o s t E x e c u t e ( param ) ;
() ; // R e c y c l e bitmap t o f r e e up s p a c e .
f i n a l PdfDocument p d f = ( PdfDocument ) t h i s . bitmap . r e c y c l e ( ) ;
p d f C o n t e x t . openDocument ( ( S t r i n g ) param // r e t u r n t h e c r e a t e d image F i l e
[0]) ; this . delegate . processFinished ( this . f i l e ) ;
activity . setRequestedOrientation (
// Choose page number t o c o n v e r t t o image . ActivityInfo .
doInBackground a c c e p t s ( f i l e P a t h O f P d f , SCREEN ORIENTATION UNSPECIFIED) ;
page#) // c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g
f i n a l PdfPage page = ( PdfPage ) p d f . g e t P a g e ( ( image .
i n t ) param [ 1 ] ) ; this . progressDialog . cancel () ;
// Render t h e Pdf page t o bitmap
f i n a l RectF r e c t = new RectF ( ) ; }
r e c t . bottom = r e c t . r i g h t = ( f l o a t ) 1 . 0 ;
t h i s . bitmap = page . r e n d e r B i t m a p ( page . /∗ ∗
getWidth ( ) , page . g e t H e i g h t ( ) , r e c t ) ; ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
w h i l e t h e r e i s a background t a s k .
// Save g e n e r a t e d image t o c a c h e ∗/
t h i s . f i l e = new F i l e ( t h i s . a c t i v i t y . private void createDialog () {
g e t C a c h e D i r ( ) + ” / c a c h e . png ” ) ; t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
this . activity ) ;
try { this . progressDialog . setCancelable ( f a l s e ) ;
f i n a l F i l e O u t p u t S t r e a m o u t = new this . progressDialog .
FileOutputStream ( t h i s . f i l e ) ; setCanceledOnTouchOutside ( f a l s e ) ;
t h i s . bitmap . c o m p r e s s ( Bitmap . CompressFormat . t h i s . progressDialog . setMessage ( ” Converting
PNG, 1 0 0 , o u t ) ; PDF . . . ” ) ;
t h i s . p r o g r e s s D i a l o g . show ( ) ;
out . f l u s h ( ) ; }
out . c l o s e ( ) ; }
pdf . r e c y c l e () ;
pdfContext . recycle () ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SaveAudio.java

package anteraaron . t e s s 2 s p e e c h ; splittedTexts = null ;


counter = 1;
i m p o r t a n d r o i d . app . A c t i v i t y ; // C r e a t e c o n t e n t s o f a l e r t d i a l o g
i m p o r t a n d r o i d . app . A l e r t D i a l o g ; f i n a l AlertDialog . Builder dialogBuilder =
i m p o r t a n d r o i d . app . P r o g r e s s D i a l o g ; new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) ;
import android . content . D i a l o g I n t e r f a c e ; d i a l o g B u i l d e r . s e t T i t l e ( ” Save C o n v e r t e d
i m p o r t a n d r o i d . c o n t e n t . pm . A c t i v i t y I n f o ; Speech ” ) ;
i m p o r t a n d r o i d . o s . AsyncTask ; d i a l o g B u i l d e r . s e t M e s s a g e ( ” I n p u t f i l e name : ”
import android . os . Build ; );
i m p o r t a n d r o i d . s p e e c h . t t s . TextToSpeech ;
import android . speech . t t s . //Add e d i t t e x t t o a l e r t d i a l o g .
UtteranceProgressListener ; f i n a l L i n e a r L a y o u t . LayoutParams l p = new
import android . widget . EditText ; L i n e a r L a y o u t . LayoutParams ( L i n e a r L a y o u t .
import android . widget . LinearLayout ; LayoutParams .MATCH PARENT, L i n e a r L a y o u t .
i m p o r t a n d r o i d . w i d g e t . T o a st ; LayoutParams .MATCH PARENT) ;
t h i s . e d i t T e x t i n p u t . setLayoutParams ( l p ) ;
import java . i o . F i l e ; d i a l o g B u i l d e r . setView ( t h i s . e d i t T e x t i n p u t ) ;
import java . u t i l . ArrayList ;
i m p o r t j a v a . u t i l . HashMap ; // S e t a c t i o n f o r a l e r t d i a l o g .
d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new
/∗ ∗ DialogInterface . OnClickListener () {
∗ An AsyncTask t h a t s a v e s Text−to−S p e e c h @O verr ide
output . public void onClick ( D i a l o g I n t e r f a c e dialog ,
∗ @author Anter Aaron M. C u s t o d i o i n t which ) {
∗ @since 2 0 1 6 . 3 . 2 2 save ( ) ;
∗/ }
p u b l i c c l a s s T a s k S a v e A u d i o e x t e n d s AsyncTask< }) ;
Void , Void , Void> { // S e t c a n c e l b u t t o n f o r a l e r t d i a l o g
d i a l o g B u i l d e r . setNegativeButton ( ” Cancel ” ,
p r i v a t e EditText e d i t T e x t i n p u t ; new D i a l o g I n t e r f a c e . O n C l i c k L i s t e n e r ( ) {
private ProgressDialog progressDialog ; @O verr ide
p r i v a t e S t r i n g s t r i n g , path ; public void onClick ( D i a l o g I n t e r f a c e dialog ,
private Activity activity ; i n t which ) {
private s t a t i c boolean f i n i s h e d ; dialog . dismiss () ;
private s t a t i c int counter ; T oa s t . makeText ( a c t i v i t y , ” Save c a n c e l l e d ” ,
p r i v a t e s t a t i c A r r a y L i s t <S t r i n g > T o as t . LENGTH LONG) . show ( ) ;
splittedTexts ; }
p r i v a t e s t a t i c f i n a l i n t MAX CHARS = 3 9 0 0 ; }) ;
// Show t h e c r e a t e d a l e r t D i a l o g
p u b l i c Task SaveAudio ( f i n a l A c t i v i t y a c t i v i t y f i n a l AlertDialog alertDialog =
){ dialogBuilder . create () ;
this . activity = activity ; a l e r t D i a l o g . show ( ) ;
t h i s . e d i t T e x t i n p u t = new E d i t T e x t ( a c t i v i t y ) }
;
t h i s . s t r i n g = Fragment ConvertedText . @O verr ide
editText . getText ( ) . t o S t r i n g ( ) ; p r o t e c t e d Void doInBackground ( f i n a l Void . . .

131
params ) { // f o r non d e p r i c a t e d ( l o w e r than l o l l i p o p )
// s a v e t h e a u d i o i n b a c k g r o u n d i f ( s t r i n g . l e n g t h ( ) >= MAX CHARS) {
s a v e A u d i o ( t h i s . path , t h i s . s t r i n g ) ; splittedTexts = splitText ( string ) ;
return null ; hashRender . put ( TextToSpeech . E n g i n e .
} KEY PARAM UTTERANCE ID, s p l i t t e d T e x t s . g e t
(0) ) ;
@O verr ide Libraries . tts . synthesizeToFile (
p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void param s p l i t t e d T e x t s . g e t ( 0 ) , hashRender , path .
) { s u b s t r i n g ( 0 , path . l a s t I n d e x O f ( ’ . ’ ) ) + ”−
s u p e r . o n P o s t E x e c u t e ( param ) ; p a r t −” + c o u n t e r + ” . wav” ) ;
activity . setRequestedOrientation ( } else {
ActivityInfo . hashRender . put ( TextToSpeech . E n g i n e .
SCREEN ORIENTATION UNSPECIFIED) ; KEY PARAM UTTERANCE ID, s t r i n g ) ;
// c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g Libraries . tts . synthesizeToFile ( string ,
audio . hashRender , path ) ;
this . progressDialog . cancel () ; }
T oa s t . makeText ( t h i s . a c t i v i t y , ” F i l e s a v e d t o }
: ” + t h i s . path , T o a st . LENGTH LONG) . show
() ; Libraries . tts . setOnUtteranceProgressListener
} ( new U t t e r a n c e P r o g r e s s L i s t e n e r ( ) {
@O verr ide
/∗ ∗ public void onStart ( String utteranceId ) {
∗ Method t h a t s a v e s t h e a u d i o o u t p u t by finished = false ;
TTS . }
∗/
p r i v a t e void save ( ) { @O verr ide
// C r e a t e f i l e f o r s a v i n g p u b l i c v o i d onDone ( S t r i n g u t t e r a n c e I d ) {
f i n a l String filename = this . editText input . c o u n t e r ++;
g e t T e x t ( ) + ” . wav” ; i f ( s p l i t t e d T e x t s != n u l l && s p l i t t e d T e x t s
t h i s . path = D i r e c t o r i e s . AUDIO DIR + F i l e . . s i z e ( ) > 1) {
separator + filename ; s p l i t t e d T e x t s . remove ( 0 ) ;
f i n a l F i l e f i l e = new F i l e ( path ) ; i f ( B u i l d . VERSION . SDK INT >= B u i l d .
// I f f i l e e x i s t s , c r e a t e a d i a l o g t h a t VERSION CODES . LOLLIPOP) {
prompts t h e u s e r t o o v e r w r i t e f i l e Libraries . tts . synthesizeToFile (
i f ( f i l e . exists () ) { s p l i t t e d T e x t s . g e t ( 0 ) , n u l l , new F i l e ( path
new A l e r t D i a l o g . B u i l d e r ( t h i s . a c t i v i t y ) . s u b s t r i n g ( 0 , path . l a s t I n d e x O f ( ’ . ’ ) ) + ”−
. setTitle (” File already exist ”) p a r t −” + c o u n t e r + ” . wav” ) , ” t t s ” ) ;
. s e t M e s s a g e ( ”Do you want t o o v e r w r i t e t h e } else {
e x i s t i n g f i l e ?” ) f i n a l HashMap<S t r i n g , S t r i n g > hashRender
= new HashMap<>() ;
//Ok button , O v e r w r i t e e x i s t i n g f i l e hashRender . put ( TextToSpeech . E n g i n e .
. s e t P o s i t i v e B u t t o n ( ” Yes ” , new KEY PARAM UTTERANCE ID, s p l i t t e d T e x t s . g e t
DialogInterface . OnClickListener () { (0) ) ;
public void onClick ( D i a l o g I n t e r f a c e Libraries . tts . synthesizeToFile (
d i a l o g , i n t which ) { s p l i t t e d T e x t s . g e t ( 0 ) , hashRender , path .
activity . setRequestedOrientation ( s u b s t r i n g ( 0 , path . l a s t I n d e x O f ( ’ . ’ ) ) + ”−
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) p a r t −” + c o u n t e r + ” . wav” ) ;
; }
createDialog () ; } else {
execute () ; finished = true ;
} }
}) }

// C a n c e l Button , d i s m i s s d i a l o g box @O verr ide


. s e t N e g a t i v e B u t t o n ( ”No” , new p u b l i c void onError ( S t r i n g u t t e r a n c e I d ) {
DialogInterface . OnClickListener () { T oa s t . makeText ( a c t i v i t y , ”An e r r o r h a s
public void onClick ( D i a l o g I n t e r f a c e o c c u r e d i n s a v i n g a u d i o ” , T o as t .
d i a l o g , i n t which ) { LENGTH LONG) . show ( ) ;
dialog . dismiss () ; }
T o as t . makeText ( a c t i v i t y , ” Save }) ;
c a n c e l l e d ” , To a s t . LENGTH LONG) . show ( ) ;
} // Wait f o r wav f i l e t o be s a v e d
}) // n o i n s p e c t i o n StatementWithEmptyBody
. show ( ) ; while ( ! f i n i s h e d ) {
} else { i f ( s t r i n g . l e n g t h ( ) < MAX CHARS) {
//Do n o t prompt o v e r w r i t e break ;
createDialog () ; }
execute () ; }
} }
}
/∗ ∗
/∗ ∗ ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
∗ S a v e s t h e a u d i o o u t p u t o f TTS . w h i l e t h e r e i s a background t a s k .
∗ @param path f i l e path i n which t h e ∗/
a u d i o f i l e w i l l be s a v e d . private void createDialog () {
∗ @param s t r i n g The t e x t t o be c o n v e r t e d t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
to audio . this . activity ) ;
∗/ this . progressDialog . setCancelable ( f a l s e ) ;
@SuppressWarnings ( ” d e p r e c a t i o n ” ) this . progressDialog .
p r i v a t e v o i d s a v e A u d i o ( f i n a l S t r i n g path , setCanceledOnTouchOutside ( f a l s e ) ;
f i n a l String string ){ t h i s . p r o g r e s s D i a l o g . setMessage ( ” Saving long
i f ( B u i l d . VERSION . SDK INT >= B u i l d . t e x t s take longer . . . ” ) ;
VERSION CODES . LOLLIPOP) { t h i s . p r o g r e s s D i a l o g . show ( ) ;
// f o r d e p r i c a t e d ( l o l l i p o p and h i g h e r ) }
i f ( s t r i n g . l e n g t h ( ) >= MAX CHARS) {
splittedTexts = splitText ( string ) ; /∗ ∗
Libraries . tts . synthesizeToFile ( ∗ Method t h a t s p l i t s s t r i n g i n t o MAX CHAR
s p l i t t e d T e x t s . g e t ( 0 ) , n u l l , new F i l e ( path .
. s u b s t r i n g ( 0 , path . l a s t I n d e x O f ( ’ . ’ ) ) + ”− ∗ @param t e x t t h e s t r i n g t o be s p l i t t e d .
p a r t −” + c o u n t e r + ” . wav” ) , ” t t s ” ) ; ∗ @return the a r r a y l i s t o f s t r i n g that i s
} else { s p l i t t e d i n t o MAX CHARS.
Libraries . tts . synthesizeToFile ( string , ∗/
n u l l , new F i l e ( path ) , ” t t s ” ) ; p r i v a t e A r r a y L i s t <S t r i n g > s p l i t T e x t ( f i n a l
} String text ) {
f i n a l i n t textLength = text . length () ;
f i n a l A r r a y L i s t <S t r i n g > s p l i t t e d T e x t = new
} else { A r r a y L i s t <>() ;
f i n a l HashMap<S t r i n g , S t r i n g > hashRender =
new HashMap<>() ; int index = 0 ;

132
while ( index < textLength ) {
s p l i t t e d T e x t . add ( t e x t . s u b s t r i n g ( i n d e x , Math return splittedText ;
. min ( i n d e x + MAX CHARS, t e x t L e n g t h ) ) ) ; }
i n d e x += MAX CHARS; }
}

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SaveCanvas.java

package anteraaron . t e s s 2 s p e e c h ; B o o l e a n . . . params ) {


// S e t path o f t h e Drawing Canvas c a c h e
import android . app . A c t i v i t y ; f i n a l F i l e f i l e = new F i l e ( t h i s . a c t i v i t y .
import android . g r a p h i c s . Bitmap ; getCacheDir ( ) + F i l e . s e p a r a t o r + ” cache .
import android . net . Uri ; png ” ) ;
import android . o s . AsyncTask ; t h i s . u r i = Uri . fromFile ( f i l e ) ;
import android . u t i l . Log ;
import android . v i e w . View ; try {
import java . io . File ; // n o i n s p e c t i o n R e s u l t O f M e t h o d C a l l I g n o r e d
import java . io . FileOutputStream ; f i l e . createNewFile () ;
import java . io . IOException ; t h i s . o u t = new F i l e O u t p u t S t r e a m ( f i l e ) ;

/∗ ∗ // bitmap s h o u l d n o t be r e u s e d
∗ An AsyncTask t h a t S a v e s t h e u s e r drawn t e x t i f ( ! t h i s . bitmap . i s R e c y c l e d ( ) && !
and c o n v e r t i t t o t e x t . isCancelled () ) {
∗ @author Anter Aaron M. C u s t o d i o t h i s . bitmap . c o m p r e s s ( Bitmap . CompressFormat
∗ @since 2 0 1 6 . 3 . 2 2 .PNG, 1 0 0 , o u t ) ;
∗/ }
p u b l i c c l a s s Task SaveCanvas e x t e n d s AsyncTask } catch ( IOException e ) {
<Boolean , Boolean , Boolean >{ Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;
}
p r i v a t e Bitmap bitmap ;
p r i v a t e View c o n t e n t ; r e t u r n params [ 0 ] ;
private Activity activity ; }
p r i v a t e FileOutputStream out ;
p r i v a t e Uri u r i ; @O verr ide
p r o t e c t e d void onPostExecute ( f i n a l Boolean
p u b l i c Task SaveCanvas ( f i n a l Activity play ) {
activity ){ super . onPostExecute ( play ) ;
this . activity = activity ; try {
} t h i s . out . f l u s h ( ) ;
t h i s . out . c l o s e ( ) ;
@O verr ide i f (! isCancelled () ){
p r o t e c t e d void onPreExecute ( ) { // I f t h r e a d i s n o t c a n c e l l e d C o n v e r t t h e
super . onPreExecute ( ) ; c a n v a s image t o t e x t .
// A c c e s s drawingView ’ s c o n t e n t and r e a d y f o r new ToText ( t h i s . a c t i v i t y ) . e x e c u t e ( t h i s . u r i
saving , play ) ;
t h i s . c o n t e n t = Fragment DrawingCanvas . }
drawingView ;
t h i s . content . setDrawingCacheEnabled ( t r u e ) ; } catch ( IOException e ) {
t h i s . c o n t e n t . s e t D r a w i n g C a c h e Q u a l i t y ( View . Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;
DRAWING CACHE QUALITY HIGH) ; }
t h i s . bitmap = c o n t e n t . getDrawing Cache ( ) ; t h i s . content . setDrawingCacheEnabled ( f a l s e ) ;
} t h i s . content . destroyDrawingCache ( ) ;
t h i s . bitmap . r e c y c l e ( ) ;
}
@O verr ide }
p r o t e c t e d B o o l e a n doInBackground ( f i n a l

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SaveCroppedImage.java

package anteraaron . t e s s 2 s p e e c h ; private Activity activity ;


p r i v a t e AsyncResponse d e l e g a t e ;
import android . app . A c t i v i t y ; private ProgressDialog progressDialog ;
import android . app . P r o g r e s s D i a l o g ; // C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e
import android . c o n t e n t . pm . A c t i v i t y I n f o ; AsyncTask i s f i n i s h e d .
import android . g r a p h i c s . Bitmap ; p u b l i c i n t e r f a c e AsyncResponse {
import android . o s . AsyncTask ; void processFinished ( f i n a l F i l e f i l e ) ;
import android . u t i l . Log ; }
// C o n s t r u c t o r
import java . i o . F i l e ; p u b l i c Task SaveCroppedImage ( f i n a l A c t i v i t y
import java . i o . FileOutputStream ; a c t i v i t y , f i n a l AsyncResponse d e l e g a t e ) {
import java . i o . IOException ; this . activity = activity ;
this . delegate = delegate ;
/∗ ∗ }
∗ An AsyncTask t h a t s a v e s t h e c r o p p e d image .
∗ @author Anter Aaron M. C u s t o d i o @O verr ide
∗ @since 2 0 1 6 . 3 . 2 2 p r o t e c t e d void onPreExecute ( ) {
∗/ activity . setRequestedOrientation (
p u b l i c c l a s s Task SaveCroppedImage e x t e n d s A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR)
AsyncTask<Bitmap , Void , F i l e > { ;

133
// S t a r t P r o g r e s s Dialog }
createDialog () ;
} @O verr ide
p r o t e c t e d void onPostExecute ( f i n a l F i l e f i l e )
@O verr ide {
p r o t e c t e d F i l e doInBackground ( f i n a l Bitmap . . . super . onPostExecute ( f i l e ) ;
params ) { // r e t u r n t h e c r o p p e d image F i l e
f i n a l Bitmap image = params [ 0 ] ; this . delegate . processFinished ( f i l e ) ;
f i n a l S t r i n g fileName = ” crop ” ; activity . setRequestedOrientation (
// I f c r o p [ num ] . png e x i s t s , i t e r a t e num and ActivityInfo .
c r e a t e c r o p [ num ] . png u n t i l c r o p [ num ] . png SCREEN ORIENTATION UNSPECIFIED) ;
i s unique // c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g
i n t num = 0 ; image .
F i l e f i l e = new F i l e ( D i r e c t o r i e s . IMAGES DIR this . progressDialog . cancel () ;
+ F i l e . s e p a r a t o r + f i l e N a m e + ” . png ” ) ;
while ( f i l e . e x i s t s () ) { }
num++; /∗ ∗
f i l e = new F i l e ( D i r e c t o r i e s . IMAGES DIR + ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
F i l e . s e p a r a t o r + f i l e N a m e + ” ( ” + num + ” w h i l e t h e r e i s a background t a s k .
) . png ” ) ; ∗/
} private void createDialog () {
t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
try { this . activity ) ;
// Save f i l e this . progressDialog . setCancelable ( f a l s e ) ;
f i n a l F i l e O u t p u t S t r e a m o u t = new this . progressDialog .
FileOutputStream ( f i l e ) ; setCanceledOnTouchOutside ( f a l s e ) ;
image . c o m p r e s s ( Bitmap . CompressFormat .PNG, t h i s . p r o g r e s s D i a l o g . setMessage ( ” Cropping . . . ”
100 , out ) ; );
out . f l u s h ( ) ; t h i s . p r o g r e s s D i a l o g . show ( ) ;
out . c l o s e ( ) ; }
} catch ( IOException e ) {
Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ; }
}
return f i l e ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SavePdf.java

package anteraaron . t e s s 2 s p e e c h ;
/∗ ∗
i m p o r t a n d r o i d . app . A c t i v i t y ; ∗ C o n s t r u c t o r i f a d a t a / image i s p a s s e d .
i m p o r t a n d r o i d . app . A l e r t D i a l o g ; ∗ @param a c t i v i t y t h e a c t i v i t y from which
i m p o r t a n d r o i d . app . P r o g r e s s D i a l o g ; t h e image comes from .
import android . content . ClipData ; ∗ @param d a t a t h e image b e i n g p a s s e d .
import android . content . D i a l o g I n t e r f a c e ; ∗/
import android . content . I n t e n t ; p u b l i c Task SavePdf ( f i n a l A c t i v i t y a c t i v i t y ,
i m p o r t a n d r o i d . c o n t e n t . pm . A c t i v i t y I n f o ; f i n a l I n t e n t data ) {
i m p o r t a n d r o i d . g r a p h i c s . Bitmap ; this . activity = activity ;
i m p o r t a n d r o i d . g r a p h i c s . Canvas ; t h i s . data = data ;
import android . g r a p h i c s . Color ; t h i s . isData = true ;
import android . net . Uri ; i n i t i a l i z e () ;
i m p o r t a n d r o i d . o s . AsyncTask ; }
import android . os . Build ;
import android . p r o v i d e r . MediaStore ; /∗ ∗
i m p o r t a n d r o i d . t e x t . Layout ; ∗ C o n s t r u c t o r i f no image i s p a s s e d . T h i s
import android . t e x t . StaticLayout ; assumes t h a t the f i l e being
import android . t e x t . TextPaint ; c o n v e r t e d t o PDF i s from t h e
import android . widget . EditText ; e d i t T e x t view
import android . widget . LinearLayout ; ∗ @param a c t i v i t y t h e a c t i v i t y which
i m p o r t a n d r o i d . w i d g e t . T o a st ; calls this class
i m p o r t com . g o o g l e c o d e . l e p t o n i c a . a n d r o i d . Pix ; ∗/
i m p o r t com . g o o g l e c o d e . l e p t o n i c a . a n d r o i d . p u b l i c Task SavePdf ( f i n a l A c t i v i t y a c t i v i t y ) {
ReadFile ; this . activity = activity ;
i m p o r t com . g o o g l e c o d e . l e p t o n i c a . a n d r o i d . t h i s . isData = f a l s e ;
WriteFile ; i n i t i a l i z e () ;
i m p o r t com . g o o g l e c o d e . t e s s e r a c t . a n d r o i d . }
TessPdfRenderer ;
import java . i o . F i l e ; /∗ ∗
import java . i o . IOException ; ∗ Method t h a t i n i t i a l i z e s t h e UI and
T e s s e r a c t ’ s PDF R e n d e r e r
import kaloer . f i l e p i c k e r . FilePickerActivity ; ∗/
private void i n i t i a l i z e () {
/∗ ∗ t h i s . e d i t T e x t i n p u t = new E d i t T e x t ( a c t i v i t y )
∗ An AsyncTask t h a t s a v e s t h e t e x t t o a PDF ;
o r c o n v e r t s an Image t o PDF u s i n g
T e s s e r a c t ’ s PDF R e n d e r e r . // C r e a t e a l e r t d i a l o g
∗ Note t h a t t h i s AsyncTask i s auto−e x e c u t e . . f i n a l AlertDialog . Builder dialogBuilder =
e x e c u t e ( ) d o e s n o t need t o be c a l l e d . new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) ;
∗ @author Anter Aaron M. C u s t o d i o d i a l o g B u i l d e r . s e t T i t l e ( ” Save a s PDF” ) ;
∗ @since 3 . 2 2 . 2 0 1 6 d i a l o g B u i l d e r . s e t M e s s a g e ( ” I n p u t f i l e name : ”
∗/ );
p u b l i c c l a s s T a s k S a v e P d f e x t e n d s AsyncTask<
Void , Void , Void>{ //Add e d i t t e x t t o a l e r t d i a l o g
p r i v a t e EditText e d i t T e x t i n p u t ; f i n a l L i n e a r L a y o u t . LayoutParams l p = new
private Activity activity ; L i n e a r L a y o u t . LayoutParams ( L i n e a r L a y o u t .
p r i v a t e S t r i n g path ; LayoutParams .MATCH PARENT, L i n e a r L a y o u t .
p r i v a t e I n t e n t data ; LayoutParams .MATCH PARENT) ;
p r i v a t e Uri u r i ; t h i s . e d i t T e x t i n p u t . setLayoutParams ( l p ) ;
private ProgressDialog progressDialog ; d i a l o g B u i l d e r . setView ( t h i s . e d i t T e x t i n p u t ) ;
private boolean isData ;

134
// S e t a c t i o n f o r a l e r t d i a l o g execute () ;
d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new }
DialogInterface . OnClickListener () { }
@O verr ide
public void onClick ( D i a l o g I n t e r f a c e dialog , /∗ ∗
i n t which ) { ∗ Method t h a t c o n v e r t s an image t o PDF o r
save ( ) ; s t r i n g t o PDF .
} ∗/
}) ; p r i v a t e v o i d createPDF ( ) {
d i a l o g B u i l d e r . setNegativeButton ( ” Cancel ” , // C r e a t e T e s s e r a c t i n s t a n c e and c r e a t e
new D i a l o g I n t e r f a c e . O n C l i c k L i s t e n e r ( ) { w r i t a b l e pdf
@O verr ide T e s s P d f R e n d e r e r p d f R e n d e r e r = new
public void onClick ( D i a l o g I n t e r f a c e dialog , TessPdfRenderer ( L i b r a r i e s . t e s s e r a c t , t h i s
i n t which ) { . path ) ;
dialog . dismiss () ; L i b r a r i e s . t e s s e r a c t . endDocument ( p d f R e n d e r e r )
T oa s t . makeText ( a c t i v i t y , ” Save c a n c e l l e d ” , ;
T o as t . LENGTH LONG) . show ( ) ;
} // Write t o t h e c r e a t e d p d f
}) ; p d f R e n d e r e r = new T e s s P d f R e n d e r e r ( L i b r a r i e s .
f i n a l AlertDialog alertDialog = t e s s e r a c t , t h i s . path ) ;
dialogBuilder . create () ; L i b r a r i e s . t e s s e r a c t . beginDocument (
a l e r t D i a l o g . show ( ) ; pdfRenderer , ” T i t l e ” ) ;
} i f ( t h i s . isData ) {
// I f image i s p a s s e d and c u r r e n t B u i l d
@O verr ide v e r s i o n i s J e l l y Bean above
p r o t e c t e d Void doInBackground ( f i n a l Void . . . i f ( ( B u i l d . VERSION . SDK INT >= B u i l d .
params ) { VERSION CODES . JELLY BEAN MR2) && ( d a t a .
// c r e a t e PDF i n b a c k g r o u n d . g e t D a t a ( ) == n u l l ) && ( ! t h i s . d a t a .
createPDF ( ) ; hasExtra ( F i l e P i c k e r A c t i v i t y .
return null ; EXTRA FILE PATH) ) ) {
} f i n a l ClipData c l i p d a t a = t h i s . data .
getClipData ( ) ;
@O verr ide f o r ( i n t i = 0 ; i < c l i p d a t a . getItemCount
p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void param ( ) ; i ++) {
) { // Check i f image f o r m a t i s c o r r e c t
s u p e r . o n P o s t E x e c u t e ( param ) ; i f ( Intent BrowseFiles .
// d i s p l a y p d f checkImageExtension ( a c t i v i t y , c l i p d a t a .
Libraries . displayPdf ( this . uri ) ; getItemAt ( i ) . g e t U r i ( ) ) ) {
activity . setRequestedOrientation ( addPage ( p d f R e n d e r e r , c l i p d a t a . g e t I t e m A t (
ActivityInfo . i ) . getUri () ) ;
SCREEN ORIENTATION UNSPECIFIED) ; } else {
// c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g T oa s t . makeText ( a c t i v i t y , ”An e r r o r h a s
audio . o c c u r e d . An image h a s an i n v a l i d f o r m a t ” ,
this . progressDialog . cancel () ; T o as t . LENGTH LONG) . show ( ) ;
T oa s t . makeText ( t h i s . a c t i v i t y , ”PDF s a v e d t o : }
” + t h i s . path + ” . p d f ” , T oa s t .
LENGTH LONG) . show ( ) ; }
} } else {
// E l s e p a s s u r i directly
/∗ ∗ Uri imageUri ;
∗ Method t h a t p r e p a r e s f o r s a v i n g o f p d f .
∗ Asks a u s e r f o r f i l e name and c r e a t e s i f ( t h i s . data . hasExtra ( F i l e P i c k e r A c t i v i t y .
f i l e f o r saving , then determines i f EXTRA FILE PATH) ) {
that f i l e already e x i s t s . // Check i f t h e u s e r u s e d t h e b u i l t i n
∗/ browser
p r i v a t e void save ( ) { i m a g e U r i = U r i . f r o m F i l e ( new F i l e ( t h i s .
// S e t f i l e d i r e c t o r y . data . g e t S t r i n g E x t r a ( F i l e P i c k e r A c t i v i t y .
f i n a l String filename = editText input . EXTRA FILE PATH) ) ) ;
getText ( ) . t o S t r i n g ( ) ; } else {
t h i s . path = D i r e c t o r i e s . PDF DIR + F i l e . // The u s e r d o e s n o t u s e t h e b u i l d i n
separator + filename ; browser .
imageUri = t h i s . data . getData ( ) ;
// C r e a t e F i l e f o r s a v i n g . }
f i n a l F i l e f i l e = new F i l e ( t h i s . path + ” . p d f // Check i f image f o r m a t i s c o r r e c t
”) ; i f ( I n t e n t B r o w s e F i l e s . checkImageExtension
t h i s . u r i = Uri . fromFile ( f i l e ) ; ( a c t i v i t y , imageUri ) ) {
addPage ( p d f R e n d e r e r , i m a g e U r i ) ;
// I f f i l e e x i s t s , prompt o v e r w r i t e d i a l o g } else {
box . T o as t . makeText ( a c t i v i t y , ” S e l e c t an image
i f ( f i l e . exists () ) { w i t h an a p p r o p r i a t e f o r m a t . ” , To a s t .
new A l e r t D i a l o g . B u i l d e r ( t h i s . a c t i v i t y ) LENGTH LONG) . show ( ) ;
. setTitle (” File already exist ”) }
. s e t M e s s a g e ( ”Do you want t o o v e r w r i t e t h e
e x i s t i n g f i l e ?” ) }
//Ok button , O v e r w r i t e e x i s t i n g f i l e . } else {
. s e t P o s i t i v e B u t t o n ( ” Yes ” , new // I f no image i s p a s s e d , p a s s n u l l
DialogInterface . OnClickListener () { addPage ( p d f R e n d e r e r , n u l l ) ;
public void onClick ( D i a l o g I n t e r f a c e }
d i a l o g , i n t which ) { // F i n a l i z e PDF
activity . setRequestedOrientation ( L i b r a r i e s . t e s s e r a c t . endDocument ( p d f R e n d e r e r )
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) ;
; pdfRenderer . r e c y c l e ( ) ;
createDialog () ; }
execute () ;
} /∗ ∗
}) ∗ C o n t i n u a t i o n o f t h e createPDF method .
// C a n c e l Button , d i s m i s s d i a l o g box . T h i s method i s t h e s p e c i f i c method
. s e t N e g a t i v e B u t t o n ( ”No” , new t h a t r e n d e r s an image / t e x t t o PDF .
DialogInterface . OnClickListener () { ∗ @param p d f R e n d e r e r T e s s P d f R e n d e r e r
public void onClick ( D i a l o g I n t e r f a c e Object
d i a l o g , i n t which ) { ∗ @param u r i u r i o f t h e image e l s e n u l l .
dialog . dismiss () ; I f t h i s i s n u l l , assume t e x t w i l l be
T o as t . makeText ( a c t i v i t y , ” Save c o n v e r t e d a s PDF .
c a n c e l l e d ” , T o a st . LENGTH LONG) . show ( ) ; ∗/
} p r i v a t e v o i d addPage ( f i n a l T e s s P d f R e n d e r e r
}) pdfRenderer , f i n a l Uri u r i ) {
. show ( ) ;
} else { try {
createDialog () ; Pix p i x ;

135
i f ( t h i s . isData ) { textPaint . setTextSize (24) ;
// I f t h e r e i s an image p a s s e d , g e t t h e
bitmap from u r i . C r e a t e a p i x o b j e c t from //Draw t h e t e x t t o t h e bitmap u s i n g
t h a t bitmap . StaticLayout .
Bitmap bitmap = M e d i a S t o r e . Im ages . Media . f i n a l S t a t i c L a y o u t t e x t L a y o u t = new
getBitmap ( t h i s . a c t i v i t y . StaticLayout ( text , textPaint , 1000 ,
getContentResolver () , uri ) ; Layout . Al i g n m e n t . ALIGN NORMAL, 1 . 0 f , 1 . 0 f
p i x = R e a d F i l e . readBitmap ( bitmap ) ; , false ) ;
} else { f i n a l Bitmap bitmap = Bitmap . c r e a t e B i t m a p (
// C r e a t e a p i x o b j e c t from t h e s t r i n g i n textLayout . getEllipsizedWidth ( ) ,
EditTextView t e x t L a y o u t . g e t H e i g h t ( ) , Bitmap . C o n f i g .
pix = getTextImage ( Fragment ConvertedText . ARGB 8888 ) ;
editText . getText ( ) . t o S t r i n g ( ) ) ; f i n a l Canvas c a n v a s = new Canvas ( bitmap ) ;
} //Make b a c k g r o u n d o f t e x t s w h i t e .
// C r e a t e a t e m p o r a r y f i l e which w i l l be t h e c a n v a s . d r a w C o l o r ( C o l o r .WHITE) ;
format o f the pix f i l e canvas . save ( ) ;
f i n a l F i l e image = F i l e . c r e a t e T e m p F i l e ( ” canvas . t r a n s l a t e ( 0 , 0 ) ;
page ” , ” . png ” ) ; t e x t L a y o u t . draw ( c a n v a s ) ;
W r i t e F i l e . w r i t e I m p l i e d F o r m a t ( p i x , image ) ; // c a n v a s . r e s t o r e ( ) ;
L i b r a r i e s . t e s s e r a c t . addPageToDocument ( p i x , r e t u r n R e a d F i l e . readBitmap ( bitmap ) ;
image . g e t A b s o l u t e P a t h ( ) , p d f R e n d e r e r ) ; }
pix . r e c y c l e () ;
} catch ( IOException e ) { /∗ ∗
e . printStackTrace () ; ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
} w h i l e t h e r e i s a background t a s k .
} ∗/
private void createDialog () {
/∗ ∗ t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
∗ A method t h a t c r e a t e s an image from this . activity ) ;
input text . this . progressDialog . setCancelable ( f a l s e ) ;
∗ @param t e x t t h e t e x t t o be c o n v e r t e d t o this . progressDialog .
image . setCanceledOnTouchOutside ( f a l s e ) ;
∗ @ r e t u r n r e t u r n s t h e image v e r s i o n o f t h i s . p r o g r e s s D i a l o g . setMessage ( ” Saving as
the text . PDF . . . ” ) ;
∗/ t h i s . p r o g r e s s D i a l o g . show ( ) ;
p r i v a t e Pix g e t T e x t I m a g e ( f i n a l S t r i n g t e x t ) { }
// S e t f o n t s i z e }
f i n a l T e x t P a i n t t e x t P a i n t = new T e x t P a i n t ( ) ;
textPaint . setAntiAlias ( true ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SaveRotatedBitmap.java

package anteraaron . t e s s 2 s p e e c h ;
@O verr ide
import android . app . A c t i v i t y ; p r o t e c t e d void onPreExecute ( ) {
import android . app . P r o g r e s s D i a l o g ; super . onPreExecute ( ) ;
import android . c o n t e n t . pm . A c t i v i t y I n f o ; activity . setRequestedOrientation (
import android . g r a p h i c s . Bitmap ; A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR)
import android . g r a p h i c s . Canvas ; ;
import android . graphics . Color ; // S t a r t p r o g r e s s D i a l o g
import android . g r a p h i c s . Matrix ; t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
import android . net . Uri ; this . activity ) ;
import android . o s . AsyncTask ; this . progressDialog . setCancelable ( f a l s e ) ;
import android . u t i l . Log ; this . progressDialog .
import android . w i d g e t . T o a st ; setCanceledOnTouchOutside ( f a l s e ) ;
import java . io . File ; t h i s . progressDialog . setMessage ( ” Rotating
import java . io . FileOutputStream ; image . . . ” ) ;
import java . io . IOException ; t h i s . p r o g r e s s D i a l o g . show ( ) ;
}
/∗ ∗
∗ An AsyncTask t h a t s a v e s t h e r o t a t e d bitmap . @O verr ide
∗ @author Anter Aaron M. C u s t o d i o p r o t e c t e d Void doInBackground ( f i n a l Object . . .
∗ @since 2 0 1 6 . 3 . 2 2 params ) {
∗/ FileOutputStream out = n u l l ;
p u b l i c c l a s s Task SaveRotatedBitmap e x t e n d s
AsyncTask<O b j e c t , Void , Void> { try {
private ProgressDialog progressDialog ; // r o t a t e t h e bitmap
private Activity activity ; f i n a l Bitmap bitmap = BitmapLoader .
p r i v a t e Uri u r i ; decodeSampledBitmap ( new F i l e ( ( S t r i n g )
p r i v a t e s t a t i c f i n a l i n t MAX WIDTH = 3 0 0 ; // params [ 0 ] ) , MAX WIDTH, MAX HEIGHT) ;
Max w i d t h a f t e r r o t a t i o n f i n a l M a t r i x m a t r i x = new M a t r i x ( ) ;
p r i v a t e s t a t i c f i n a l i n t MAX HEIGHT = 3 0 0 ; // m a t r i x . p o s t R o t a t e ( ( i n t ) params [ 1 ] ) ;
Max h e i g h t a f t e r r o t a t i o n f i n a l Bitmap r o t a t e d B i t m a p = Bitmap .
// p r i v a t e Bitmap bitmap , r o t a t e d B i t m a p , c r e a t e B i t m a p ( bitmap , 0 , 0 , bitmap .
finalBitmap ; getWidth ( ) , bitmap . g e t H e i g h t ( ) , m a t r i x ,
p r i v a t e AsyncResponse d e l e g a t e ; true ) ;
bitmap . r e c y c l e ( ) ;
// C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e
AsyncTask i s f i n i s h e d . // make bitmap b a c k g r o u n d t o w h i t e
p u b l i c i n t e r f a c e AsyncResponse { f i n a l Bitmap f i n a l B i t m a p = Bitmap .
void p r o c e s s F i n i s h e d ( f i n a l Uri u r i ) ; c r e a t e B i t m a p ( r o t a t e d B i t m a p . getWidth ( ) ,
} rotatedBitmap . getHeight ( ) , rotatedBitmap .
getConfig () ) ;
// C o n s t r u c t o r f i n a l Canvas c a n v a s = new Canvas (
p u b l i c Task SaveRotatedBitmap ( f i n a l A c t i v i t y finalBitmap ) ;
a c t i v i t y , f i n a l AsyncResponse d e l e g a t e ) { c a n v a s . d r a w C o l o r ( C o l o r .WHITE) ;
this . activity = activity ; c a n v a s . drawBitmap ( r o t a t e d B i t m a p , 0 , 0 , n u l l
this . delegate = delegate ; );
} rotatedBitmap . r e c y c l e ( ) ;

136
}
// C r e a t e f i l e f o r s a v i n g ( params [ 3 ] i s t h e }
o r i g i n a l f i l e name ) return null ;
f i n a l S t r i n g f i l e N a m e = params [ 2 ] + ” . png ” ; }
f i n a l F i l e f i l e = new F i l e ( D i r e c t o r i e s .
IMAGES DIR + F i l e . s e p a r a t o r + ” r ” + @O verr ide
params [ 1 ] + ” ” + f i l e N a m e ) ; p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void
o u t = new F i l e O u t p u t S t r e a m ( f i l e ) ; results ) {
L i b r a r i e s . galleryAddPic ( t h i s . uri ) ;
// Save bitmap w i t h l o s s l e s s c o m p r e s s i o n // Return r o t a t e d bitmap .
f i n a l B i t m a p . c o m p r e s s ( Bitmap . CompressFormat . this . delegate . processFinished ( this . uri ) ;
PNG, 1 0 0 , o u t ) ; activity . setRequestedOrientation (
finalBitmap . recycle () ; ActivityInfo .
t h i s . u r i = Uri . fromFile ( f i l e ) ; SCREEN ORIENTATION UNSPECIFIED) ;
} catch ( IOException e ) { // c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g
Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ; audio .
} finally { this . progressDialog . cancel () ;
try { T oa s t . makeText ( t h i s . a c t i v i t y , ” Saved t o : ” +
i f ( o u t != n u l l ) { D i r e c t o r i e s . IMAGES DIR , T o a st .
out . f l u s h ( ) ; LENGTH LONG) . show ( ) ;
out . c l o s e ( ) ; }
} }
} catch ( IOException e ) {
Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_SaveText.java

package anteraaron . t e s s 2 s p e e c h ; public void onClick ( D i a l o g I n t e r f a c e dialog ,


i n t which ) {
import a n d r o i d . app . A c t i v i t y ; save ( ) ;
import a n d r o i d . app . A l e r t D i a l o g ; }
import a n d r o i d . app . P r o g r e s s D i a l o g ; }) ;
import android . content . D i a l o g I n t e r f a c e ; //
import a n d r o i d . c o n t e n t . pm . A c t i v i t y I n f o ; d i a l o g B u i l d e r . setNegativeButton ( ” Cancel ” ,
import a n d r o i d . o s . AsyncTask ; new D i a l o g I n t e r f a c e . O n C l i c k L i s t e n e r ( ) {
import android . widget . EditText ; @O verr ide
import android . widget . LinearLayout ; public void onClick ( D i a l o g I n t e r f a c e dialog ,
import a n d r o i d . w i d g e t . T o a st ; i n t which ) {
import o r g . a p a c h e . commons . i o . F i l e U t i l s ; dialog . dismiss () ;
import java . io . F i l e ; T oa s t . makeText ( a c t i v i t y , ” Save c a n c e l l e d ” ,
import java . i o . IOException ; T o as t . LENGTH LONG) . show ( ) ;
}
/∗ ∗ }) ;
∗ An AsyncTask t h a t s a v e s t e x t i n // D i s p l a y t h e c r e a t e d d i a l o g B u i l d e r
LinedEditText to . txt f i l e f i n a l AlertDialog alertDialog =
∗ @author Anter Aaron M. C u s t o d i o dialogBuilder . create () ;
∗ @since 2 0 1 6 . 3 . 2 2 a l e r t D i a l o g . show ( ) ;
∗/ }
p u b l i c c l a s s T a s k S a v e T e x t e x t e n d s AsyncTask<
Void , Void , Void>{ @O verr ide
p r o t e c t e d Void doInBackground ( f i n a l Void . . .
private EditText e d i t T e x t i n p u t ; params ) {
private ProgressDialog progressDialog ; try {
private S t r i n g s t r i n g , path ; writeFile ( this . file , this . string ) ;
private File f i l e ; } catch ( IOException e ) {
private Activity activity ; e . printStackTrace () ;
}
// C o n s t r u c t o r return null ;
p u b l i c Task SaveText ( f i n a l A c t i v i t y a c t i v i t y ) }
{
this . activity = activity ; @O verr ide
// c r e a t e and e d i t T e x t t h a t w i l l be embedded p r o t e c t e d v o i d o n P o s t E x e c u t e ( f i n a l Void param
in the a l e r t D i a l o g . ) {
t h i s . e d i t T e x t i n p u t = new E d i t T e x t ( a c t i v i t y ) s u p e r . o n P o s t E x e c u t e ( param ) ;
; activity . setRequestedOrientation (
// Get t h e i n p u t from e d i t T e x t . T h i s w i l l be ActivityInfo .
the fileName of the . txt f i l e SCREEN ORIENTATION UNSPECIFIED) ;
t h i s . s t r i n g = Fragment ConvertedText . // c a n c e l t h e p r o g r e s s d i a l o g a f t e r s a v i n g .
editText . getText ( ) . t o S t r i n g ( ) ; txt f i l e .
// c r e a t e a l e r t d i a l o g this . progressDialog . cancel () ;
f i n a l AlertDialog . Builder dialogBuilder = T oa s t . makeText ( a c t i v i t y , ” F i l e s a v e d t o : ” +
new A l e r t D i a l o g . B u i l d e r ( a c t i v i t y ) ; t h i s . path , T o as t . LENGTH LONG) . show ( ) ;
d i a l o g B u i l d e r . s e t T i t l e ( ” Save C o n v e r t e d Text }
to . txt ” ) ;
d i a l o g B u i l d e r . s e t M e s s a g e ( ” I n p u t f i l e name : ” /∗ ∗
); ∗ Method t h a t s a v e s t h e t e x t from
//Add e d i t t e x t t o a l e r t d i a l o g LinedEditText to . txt .
f i n a l L i n e a r L a y o u t . LayoutParams l p = new ∗/
L i n e a r L a y o u t . LayoutParams ( L i n e a r L a y o u t . p r i v a t e void save ( ) {
LayoutParams .MATCH PARENT, L i n e a r L a y o u t .
LayoutParams .MATCH PARENT) ; try {
t h i s . e d i t T e x t i n p u t . setLayoutParams ( l p ) ; // S e t f i l e d i r e c t o r y
d i a l o g B u i l d e r . setView ( t h i s . e d i t T e x t i n p u t ) ; f i n a l String filename = this . editText input
. getText ( ) + ” . txt ” ;
// S e t a c t i o n f o r a l e r t d i a l o g t h i s . path = D i r e c t o r i e s . TEXT DIR + F i l e .
d i a l o g B u i l d e r . s e t P o s i t i v e B u t t o n ( ”Ok” , new separator + filename ;
DialogInterface . OnClickListener () { t h i s . f i l e = new F i l e ( t h i s . path ) ;
// I f f i l e e x i s t s , prompt o v e r w r i t e d i a l o g
@O verr ide box

137
i f ( this . f i l e . exists () ) { f i l e ! ” , To a s t . LENGTH SHORT) . show ( ) ;
new A l e r t D i a l o g . B u i l d e r ( t h i s . a c t i v i t y ) }
. setTitle (” File already exist ”) }
. s e t M e s s a g e ( ”Do you want t o o v e r w r i t e
the e x i s t i n g f i l e ?” ) /∗ ∗
//Ok button , O v e r w r i t e e x i s t i n g f i l e ∗ Continuation o f Task SaveText . save ( ) .
. s e t P o s i t i v e B u t t o n ( ” Yes ” , new Write t h e s t r i n g t o a t e x t f i l e .
DialogInterface . OnClickListener () { ∗ @param f i l e f i l e i n which t h e t e x t w i l l
public void onClick ( D i a l o g I n t e r f a c e be w r i t t e n .
d i a l o g , i n t which ) { ∗ @param s t r i n g t e x t t h a t w i l l be w r i t t e n
activity . setRequestedOrientation ( to the f i l e .
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) ∗ @throws I O E x c e p t i o n
; ∗/
createDialog () ; private void w r i t e F i l e ( f i n a l F i l e f i l e ,
execute () ; f i n a l S t r i n g s t r i n g ) throws IOException {
} // n o i n s p e c t i o n R e s u l t O f M e t h o d C a l l I g n o r e d
}) FileUtils . writeStringToFile ( f i l e , string ) ;
// C a n c e l Button , d i s m i s s d i a l o g box }
. s e t N e g a t i v e B u t t o n ( ”No” , new
DialogInterface . OnClickListener () { /∗ ∗
public void onClick ( D i a l o g I n t e r f a c e ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
d i a l o g , i n t which ) { w h i l e t h e r e i s a background t a s k .
dialog . dismiss () ; ∗/
T oa s t . makeText ( a c t i v i t y , ” Save private void createDialog () {
c a n c e l l e d ” , To a s t . LENGTH LONG) . show ( ) ; t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
} this . activity ) ;
}) this . progressDialog . setCancelable ( f a l s e ) ;
. show ( ) ; this . progressDialog .
} else { setCanceledOnTouchOutside ( f a l s e ) ;
createDialog () ; t h i s . p r o g r e s s D i a l o g . setMessage ( ” Saving . . . ” ) ;
execute () ; t h i s . p r o g r e s s D i a l o g . show ( ) ;
} }
} catch ( Exception e ) { }
//An e r r o r h a s o c c u r e d w h i l e s a v i n g
T o as t . makeText ( t h i s . a c t i v i t y , ” E r r o r s a v i n g

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_UnzipEpub.java

package anteraaron . t e s s 2 s p e e c h ; }

import android . app . A c t i v i t y ; @O verr ide


import android . app . P r o g r e s s D i a l o g ; p r o t e c t e d B o o l e a n doInBackground ( f i n a l O b j e c t
import android . c o n t e n t . pm . A c t i v i t y I n f o ; . . . params ) {
import android . net . Uri ; // A c c e p t s t h e u r i o f epub , and t h e
import android . o s . AsyncTask ; e x t r a c t i o n path ( c a c h e P a t h ) .
import android . w i d g e t . T o a st ; t h i s . e p u b U r i = ( U r i ) params [ 0 ] ;
t h i s . c a c h e P a t h = ( S t r i n g ) params [ 1 ] ;
import java . io . BufferedInputStream ; r e t u r n unZip ( t h i s . epubUri , t h i s . c a c h e P a t h ) ;
import java . io . File ; }
import java . i o . FileOutputStream ;
import java . i o . IOException ; @O verr ide
import java . i o . InputStream ; p r o t e c t e d void onPostExecute ( f i n a l Boolean
import java . u t i l . z i p . ZipEntry ; success ) {
import java . u t i l . z i p . ZipInputStream ; super . onPostExecute ( s u c c e s s ) ;
i f (! success ) {
/∗ ∗ //An e r r o r h a s o c c u r e d i n e x t r a c t i n g epub .
∗ An AsyncTask t h a t e x t r a c t s epub c o n t e n t s t o T o as t . makeText ( t h i s . a c t i v i t y , ” E r r o r
f o l d e r EPUB CACHE DIR t o a c c e s s c s s e x t r a c t i n g epub ” , T o a st . LENGTH LONG) . show
f i l e s and i m a g e s () ;
∗ @author Anter Aaron M. C u s t o d i o }
∗ @since 2 0 1 6 . 3 . 2 7 // r e t u r n e x t r a c t e d epub c a c h e path and t h e
∗/ o r i g i n a l epub u r i .
p u b l i c c l a s s Task UnzipEpub e x t e n d s AsyncTask< t h i s . d e l e g a t e . p r o c e s s F i n i s h e d ( t h i s . epubUri ,
O b j e c t , Void , Boolean> { t h i s . cachePath ) ;
private ProgressDialog progressDialog ; activity . setRequestedOrientation (
p r i v a t e AsyncResponse d e l e g a t e ; ActivityInfo .
private Activity activity ; SCREEN ORIENTATION UNSPECIFIED) ;
p r i v a t e S t r i n g cachePath ; // c a n c e l t h e p r o g r e s s d i a l o g a f t e r c r e a t i n g
p r i v a t e Uri epubUri ; cache .
// C r e a t e an i n t e r f a c e t o d e t e r m i n e t h a t t h e this . progressDialog . cancel () ;
AsyncTask i s f i n i s h e d . this . progressDialog . dismiss () ;
p u b l i c i n t e r f a c e AsyncResponse { }
v o i d p r o c e s s F i n i s h e d ( f i n a l U r i epubUri ,
f i n a l S t r i n g path ) ; /∗ ∗
} ∗ Method t h a t u n z i p s t h e epub t o a
// C o n s t r u c t o r s e l e c t e d path .
p u b l i c Task UnzipEpub ( f i n a l A c t i v i t y a c t i v i t y ∗ @param e p u b U r i t h e u r i o f t h e epub t o
, f i n a l AsyncResponse d e l e g a t e ) { be e x t r a c t e d .
this . activity = activity ; ∗ @param c a c h e P a t h t h e path where t h e
this . delegate = delegate ; epub c o n t e n t s w i l l be e x t r a c t e d .
} ∗ @return t r u e i f e x t r a c t i n g i s
successful .
@O verr ide ∗/
p r o t e c t e d void onPreExecute ( ) { p u b l i c b o o l e a n unZip ( f i n a l U r i epubUri ,
activity . setRequestedOrientation ( f i n a l S t r i n g cachePath ) {
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) InputStream i s ;
; ZipInputStream z i s ;
// S t a r t P r o g r e s s D i a l o g
createDialog () ; try {

138
String filename ; FileOutputStream ( cachePath + F i l e .
i s = t h i s . a c t i v i t y . getContentResolver () . separator + filename ) ;
openInputStream ( epubUri ) ; w h i l e ( ( c o u n t = z i s . r e a d ( b u f f e r ) ) != −1)
a s s e r t i s != n u l l ; {
z i s = new Z i p I n p u t S t r e a m ( new f o u t . w r i t e ( b u f f e r , 0 , count ) ;
BufferedInputStream ( i s ) ) ; }
ZipEntry ze ;
fout . close () ;
byte [ ] b u f f e r = new b y t e [ 1 0 2 4 ] ; z i s . closeEntry () ;
}
i n t count ;
w h i l e ( ( z e = z i s . g e t N e x t E n t r y ( ) ) != n u l l ) is . close () ;
{ zis . close () ;
f i l e n a m e = z e . getName ( ) ; } catch ( IOException e ) {
e . printStackTrace () ;
// C r e a t e d i r e c t o r y i f i t d o e s n o t e x i s t . return f a l s e ;
i f ( ze . i s D i r e c t o r y ( ) ) { }
f i n a l F i l e d i r = new F i l e ( cachePath , return true ;
filename ) ; }
// n o i n s p e c t i o n R e s u l t O f M e t h o d C a l l I g n o r e d
d i r . mkdirs ( ) ; /∗ ∗
continue ; ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
} else { w h i l e t h e r e i s a background t a s k .
// C r e a t e p a r e n t d i r e c t o r y i f i t i s a ∗/
file . private void createDialog () {
f i n a l F i l e d i r = new F i l e ( cachePath , t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
filename ) ; this . activity ) ;
f i n a l String parent = d i r . getParentFile this . progressDialog . setCancelable ( f a l s e ) ;
( ) . getPath ( ) ; this . progressDialog .
f i n a l F i l e p a r e n t D i r = new F i l e ( p a r e n t ) ; setCanceledOnTouchOutside ( f a l s e ) ;
// n o i n s p e c t i o n R e s u l t O f M e t h o d C a l l I g n o r e d t h i s . progressDialog . setMessage ( ” Preparing
parentDir . mkdirs ( ) ; Epub . . . ” ) ;
} t h i s . p r o g r e s s D i a l o g . show ( ) ;
}
// Copy t h e c u r r e n t f i l e t o t h e s e l e c t e d }
path
f i n a l F i l e O u t p u t S t r e a m f o u t = new

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
Task\_WebViewToText.java

package anteraaron . t e s s 2 s p e e c h ; i f ( ! params [ 0 ] ) {


publishProgress () ;
import android . app . A c t i v i t y ; while ( ! f i n i s h e d ){
import android . app . P r o g r e s s D i a l o g ; // Wait u n t i l t e x t V i e w f i n i s h e d s e t t i n g
import android . c o n t e n t . pm . A c t i v i t y I n f o ; text to d i s p l a y p r o g r e s s d i a l o g while
import android . o s . AsyncTask ; textView i s s e t t i n g t e x t .
import android . t e x t . Html ; Log . d ( ” Wait ” , ” W a i t i n g f o r t e x t v i e w t o set
import android . t e x t . Spanned ; text . ”) ;
import android . u t i l . Log ; }
}
/∗ ∗ r e t u r n params [ 0 ] ;
∗ An AsyncTask t h a t c o n v e r t s Epub d i s p l a y e d }
on WebView t o Text .
∗ @author Anter Aaron M. C u s t o d i o @O verr ide
∗ @since 2 0 1 6 . 3 . 3 0 p r o t e c t e d v o i d o n P r o g r e s s U p d a t e ( f i n a l Void . . .
∗/ params ) {
p u b l i c c l a s s Task WebViewToText e x t e n d s // Check s t u f f on t h e UI
AsyncTask<Boolean , Void , Boolean >{ s u p e r . o n P r o g r e s s U p d a t e ( params ) ;
private Activity activity ; // Change t e x t V i e w ’ s v a l u e i n C o n v e r t e d T e x t
private ProgressDialog progressDialog ; Fragment
p r i v a t e s t a t i c Spanned c o n v e r t e d T e x t ; F r a g m e n t C o n v e r t e d T e x t . e d i t T e x t . append (
p r i v a t e Boolean f i n i s h e d ; convertedText ) ;
Fragment ConvertedText . e d i t T e x t . s e t S e l e c t i o n
p u b l i c Task WebViewToText ( f i n a l Activity ( Fragment ConvertedText . e d i t T e x t . l e n g t h ( )
activity ) { );
this . activity = activity ; finished = true ;
this . finished = false ; }
}
@O verr ide
@O verr ide p r o t e c t e d void onPostExecute ( f i n a l Boolean
p r o t e c t e d void onPreExecute ( ) { play ) {
super . onPreExecute ( ) ; super . onPostExecute ( play ) ;
// S t a r t p r o g r e s s D i a l o g activity . setRequestedOrientation (
activity . setRequestedOrientation ( ActivityInfo .
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) SCREEN ORIENTATION UNSPECIFIED) ;
; //End p r o g r e s s d i a l o g
createDialog () ; this . progressDialog . cancel () ;
}
// I f p l a y p a r a m e t e r i s t r u e , c o n t i n u e t o
@O verr ide ToSpeech ( ) AsyncTask
p r o t e c t e d B o o l e a n doInBackground ( f i n a l i f ( play ) {
B o o l e a n . . . params ) { new ToSpeech ( ) . e x e c u t e ( c o n v e r t e d T e x t .
// g e t d i s p l a y e d t h e html f o r m a t t e d t e x t toString () ) ;
d i s p l a y e d i n webView . }
c o n v e r t e d T e x t = Html . fromHtml ( }
Fragment EPubViewer TOC . h t m l C o n t e n t ) ;
// o n l y s e t t e x t t o t e x t V i e w i f c o n v e r t e d /∗ ∗
t e x t f r a g m e n t i s v i s i b l e ( params [ 0 ] ( p l a y ) ∗ Method t h a t c r e a t e s P r o g r e s s D i a l o g
== f a l s e ) t o s a v e p r o c e s s i n g t i m e . w h i l e t h e r e i s a background t a s k .

139
∗/ t h i s . progressDialog . setMessage ( ” Converting
private void createDialog () { to text . . . ” ) ;
t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g ( t h i s . p r o g r e s s D i a l o g . show ( ) ;
this . activity ) ; }
this . progressDialog . setCancelable ( f a l s e ) ; }
this . progressDialog .
setCanceledOnTouchOutside ( f a l s e ) ;

Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/
ToSpeech.java

package anteraaron . t e s s 2 s p e e c h ; } else {


// I f not , p l a y d i r e c t l y
import android . a n n o t a t i o n . TargetApi ; L i b r a r i e s . t t s . speak ( text , TextToSpeech .
import android . o s . AsyncTask ; QUEUE FLUSH, map ) ;
import android . os . Build ; }
import android . s p e e c h . t t s . TextToSpeech ; }
/∗ ∗
import java . u t i l . ArrayList ; ∗ Read t e x t u s i n g t e x t t o s p e e c h f o r
i m p o r t j a v a . u t i l . HashMap ; L o l l i p o p and above .
∗ @param t e x t t e x t t o be c o n v e r t e d t o
/∗ ∗ speech .
∗ An AsyncTask t h a t c o n v e r t s t e x t s t o s p e e c h . ∗/
∗ @author Anter Aaron M. C u s t o d i o @TargetApi ( B u i l d . VERSION CODES . LOLLIPOP)
∗ @since 2 0 1 6 . 3 . 2 2 private void ttsGreater21 ( f i n a l String text )
∗/ {
p u b l i c c l a s s ToSpeech e x t e n d s AsyncTask<S t r i n g f i n a l S t r i n g u I d = t h i s . hashCode ( ) + ” ” ;
, Void , Void> {
p r i v a t e s t a t i c f i n a l i n t MAX CHARS = 3 9 0 0 ; // // I f t h e number o f c h a r s e x c e e d s t h e t t s
Max c h a r a c t e r s t h a t t t s can r e a d . limit
private s t a t i c String text ; i f ( t e x t . l e n g t h ( ) >= MAX CHARS) {
f i n a l A r r a y L i s t <S t r i n g > s p l i t t e d T e x t =
@O verr ide splitText ( text ) ;
p r o t e c t e d void onPreExecute ( ) { //Add t h e s p l i t t e d t e x t s t o t t s queue .
super . onPreExecute ( ) ; f o r ( f i n a l S t r i n g queueElement :
// s e t b u t t o n l a b e l t o s t o p splittedText ) {
Activity Main . button play . L i b r a r i e s . t t s . s p e a k ( queueElement ,
setCompoundDrawablesWithIntrinsicBounds TextToSpeech . QUEUE ADD, n u l l , u I d ) ;
( 0 , R . mipmap . i c a c t i o n p l a y b a c k s t o p , 0 , }
0) ; } else {
A c t i v i t y M a i n . b u t t o n p l a y . s e t T e x t (R . s t r i n g . // I f not , p l a y d i r e c t l y .
button stop ) ; L i b r a r i e s . t t s . s p e a k ( t e x t , TextToSpeech .
QUEUE FLUSH, n u l l , u I d ) ;
// D i s a b l e b u t t o n s t o a v o i d b u t t o n mashing }
Activity Main . button text . setEnabled ( f a l s e ) ; }
Activity Main . button text . setClickable ( f a l s e
); /∗ ∗
} ∗ Read t e x t u s i n g t e x t t o s p e e c h .
∗ @param t e x t t e x t t o be c o n v e r t e d t o
@O verr ide speech .
p r o t e c t e d Void doInBackground ( f i n a l String . . . ∗/
params ) { p r i v a t e void speak ( f i n a l S t r i n g t e x t ) {
t e x t = params [ 0 ] ; i f ( B u i l d . VERSION . SDK INT >= B u i l d .
return null ; VERSION CODES . LOLLIPOP) {
} // f o r d e p r i c a t e d OS ( l o l l i p o p and h i g h e r )
ttsGreater21 ( text ) ;
@O verr ide }else{
p r o t e c t e d void onPostExecute ( f i n a l Void // f o r non d e p r i c a t e d OS ( l o w e r than
result ) { lollipop )
super . onPostExecute ( r e s u l t ) ; // n o i n s p e c t i o n d e p r e c a t i o n
speak ( t e x t ) ; ttsUnder20 ( text ) ;
} }
}
/∗ ∗
∗ Read t e x t u s i n g t e x t t o s p e e c h f o r /∗ ∗
below L o l l i p o p . ∗ Method t h a t s p l i t s s t r i n g i n t o MAX CHAR
∗ @param t e x t t e x t t o be c o n v e r t e d t o .
speech . ∗ @param t e x t t h e s t r i n g t o be s p l i t t e d .
∗ @ d e p r e c a t e d f o r API l o w e r than l o l l i p o p ∗ @return the a r r a y l i s t o f s t r i n g that i s
. ttsGreater21 i s alternative s p l i t t e d i n t o MAX CHARS.
∗/ ∗/
@SuppressWarnings ( ” d e p r e c a t i o n ” ) p r i v a t e A r r a y L i s t <S t r i n g > s p l i t T e x t ( f i n a l
p r i v a t e void ttsUnder20 ( f i n a l String text ) { String text ) {
f i n a l HashMap<S t r i n g , S t r i n g > map = new f i n a l i n t textLength = text . length () ;
HashMap<>() ; f i n a l A r r a y L i s t <S t r i n g > s p l i t t e d T e x t = new
map . put ( TextToSpeech . E n g i n e . A r r a y L i s t <>() ;
KEY PARAM UTTERANCE ID, ” Message ” ) ;
i n t index = 0 ;
// I f t h e number o f c h a r s e x c e e d s t h e t t s while ( index < textLength ) {
limit s p l i t t e d T e x t . add ( t e x t . s u b s t r i n g ( i n d e x , Math
i f ( t e x t . l e n g t h ( ) >= MAX CHARS) { . min ( i n d e x + MAX CHARS, t e x t L e n g t h ) ) ) ;
f i n a l A r r a y L i s t <S t r i n g > s p l i t t e d T e x t = i n d e x += MAX CHARS;
splitText ( text ) ; }
//Add t h e s p l i t t e d t e x t s t o t t s queue .
f o r ( f i n a l S t r i n g queueElement : return splittedText ;
splittedText ) { }
L i b r a r i e s . t t s . s p e a k ( queueElement ,
TextToSpeech . QUEUE ADD, map ) ; }
}

140
Path = Tess2Speech/tess2Speech/src/main/java/anteraaron/tess2speech/ToText.java

package anteraaron . t e s s 2 s p e e c h ;
@O verr ide
import android . app . A c t i v i t y ; p r o t e c t e d void onPostExecute ( f i n a l Boolean
import android . app . P r o g r e s s D i a l o g ; play ) {
import android . content . SharedPreferences ; super . onPostExecute ( play ) ;
import android . c o n t e n t . pm . A c t i v i t y I n f o ; // Remove comment o u t t o v i e w t h r e s h o l d e d
import android . g r a p h i c s . Bitmap ; image on phone
import android . net . Uri ; // L i b r a r i e s . imageView . s e t I m a g e B i t m a p (
import android . o s . AsyncTask ; W r i t e F i l e . writeBitmap ( L i b r a r i e s . t e s s e r a c t
import android . p r e f e r e n c e . PreferenceManager ; . getThresholdedImage ( ) ) ) ;
import android . p r o v i d e r . MediaStore ;
import android . u t i l . Log ; Libraries . tesseract . clear () ;
Libraries . tesseract . setVariable (”
i m p o r t com . g o o g l e c o d e . l e p t o n i c a . a n d r o i d . c l a s s i f y e n a b l e l e a r n i n g ” , ”0” ) ;
WriteFile ; Libraries . tesseract . setVariable (”
c l a s s i f y e n a b l e a d a p t i v e m a t c h e r ” , ”0” ) ;
import java . i o . F i l e ;
import java . i o . IOException ; // Change t e x t V i e w ’ s v a l u e i n C o n v e r t e d T e x t
Fragment
/∗ ∗ F r a g m e n t C o n v e r t e d T e x t . e d i t T e x t . append (
∗ An AsyncTask t h a t c o n v e r t s t h e image t o convertedText ) ;
t e x t u s i n g Google ’ s T e s s e r a c t ( See . . . Fragment ConvertedText . e d i t T e x t . s e t S e l e c t i o n
h t t p s : / / g i t h u b . com/ r m t h e i s / t e s s −two ) ( Fragment ConvertedText . e d i t T e x t . l e n g t h ( )
∗ @author Anter Aaron M. C u s t o d i o );
∗ @since 2 0 1 6 . 3 . 2 2
∗/ activity . setRequestedOrientation (
p u b l i c c l a s s ToText e x t e n d s AsyncTask<O b j e c t , ActivityInfo .
Void , Boolean >{ SCREEN ORIENTATION UNSPECIFIED) ;
//Maximum w i d t h o f image a f t e r a c c e l e r a t i n g //End p r o g r e s s d i a l o g
image p r o c e s s this . progressDialog . cancel () ;
p r i v a t e s t a t i c f i n a l i n t MAX WIDTH = 3 0 0 ;
//Maximum h e i g h t o f image a f t e r a c c e l e r a t i n g //Re−e n a b l e b u t t o n s
image p r o c e s s Activity Main . button text . setEnabled ( true ) ;
p r i v a t e s t a t i c f i n a l i n t MAX HEIGHT = 3 0 0 ; Activity Main . button text . setClickable ( true )
;
private Activity activity ; Activity Main . button play . setEnabled ( true ) ;
private ProgressDialog progressDialog ; Activity Main . button play . setClickable ( true )
p r i v a t e s t a t i c String convertedText ; ;
// C o n s t r u c t o r
p u b l i c ToText ( f i n a l A c t i v i t y a c t i v i t y ) { // I f p l a y p a r a m e t e r i s t r u e , c o n t i n u e t o
this . activity = activity ; ToSpeech ( ) AsyncTask
convertedText = ”” ; i f ( play ) {
} new ToSpeech ( ) . e x e c u t e (
Fragment ConvertedText . e d i t T e x t . getText ( )
@O verr ide . toString () ) ;
p r o t e c t e d void onPreExecute ( ) { }
super . onPreExecute ( ) ; }
// D i s a b l e b u t t o n s t o a v o i d b u t t o n mashing
Activity Main . button text . setEnabled ( f a l s e ) ; /∗ ∗
Activity Main . button text . setClickable ( f a l s e ∗ Loads a bitmap from an u r i .
); ∗ @param u r i t h e U r i o f t h e bitmap t o be
Activity Main . button play . setEnabled ( f a l s e ) ; loaded .
Activity Main . button play . setClickable ( f a l s e ∗ @param r e d u c e I m a g e S i z e r e t u r n s a
); r e d u c e d s i z e image i f t h i s p a r a m e t e r
activity . setRequestedOrientation ( i s s e t to true .
A c t i v i t y I n f o . SCREEN ORIENTATION NOSENSOR) ∗ @throws I O E x c e p t i o n
; ∗/
// S t a r t p r o g r e s s D i a l o g p r i v a t e Bitmap loadBitmapFromUri ( f i n a l U r i
createDialog () ; uri , f i n a l boolean reduceImageSize )
} throws IOException {
// A c c e l e r a t e image pre−p r o c e s s by r e d u c i n g
@O verr ide image s i z e
p r o t e c t e d B o o l e a n doInBackground ( f i n a l O b j e c t Bitmap bitmap ;
. . . params ) { i f ( reduceImageSize ) {
try { // I f r e d u c e I m a g e S i z e i s t r u e
// Check i f image p r e p r o c e s s i s e n a b l e d
PreferenceManager . setDefaultValues ( t h i s . // Get f i l e e x t e n s i o n o f t h e f i l e from u r i
a c t i v i t y , R . xml . p r e f e r e n c e s , f a l s e ) ; f i n a l String extension = Intent BrowseFiles
f i n a l SharedPreferences settings = . getMimeType ( a c t i v i t y , u r i ) ;
PreferenceManager . // Resample bitmap t o r e d u c e s i z e &
getDefaultSharedPreferences ( this . activity dimension
);
// C r e a t e a bitmap o f d e s i r e d i n p u t image ( bitmap = BitmapLoader . decodeSampledBitmap (
o r i g i n a l o r r e d u c e d b a s e d on p r e f e r e n c e ) new F i l e ( t h i s . a c t i v i t y . g e t C a c h e D i r ( ) +
Bitmap bitmap = loadBitmapFromUri ( ( U r i ) F i l e . s e p a r a t o r + ” cache . ” + extension ) ,
params [ 0 ] , s e t t i n g s . g e t B o o l e a n ( ” MAX WIDTH, MAX HEIGHT) ;
pre f key acce lerat e ” , true ) ) ; } else {
// p e r f o r m image p r e p r o c e s s i n g // Load t h e o r i g i n a l bitmap w i t h o u t r e d u c i n g
i f ( s e t t i n g s . getBoolean ( ” q u a l i t y . ( Consumes memory )
pref key image preprocess ” , true ) ) { bitmap = M e d i a S t o r e . Im ages . Media . getBitmap (
bitmap = BitmapLoader . i m a g e P r e P r o c e s s ( t h i s . a c t i v i t y . getContentResolver () , uri ) ;
bitmap ) ; }
}
// Check i f bitmap i s empty r e t u r n bitmap ;
i f ( bitmap != n u l l ) { }
// Feed t h e image t o t e s s e r a c t
L i b r a r i e s . t e s s e r a c t . s e t I m a g e ( bitmap ) ; private void createDialog () {
// Output t h i s . p r o g r e s s D i a l o g = new P r o g r e s s D i a l o g (
convertedText = L i b r a r i e s . t e s s e r a c t . this . activity ) ;
getUTF8Text ( ) . r e p l a c e A l l ( ” ( ( ? < ! \ \ . ) \n ) ” , this . progressDialog . setCancelable ( f a l s e ) ;
” ”) ; this . progressDialog .
} setCanceledOnTouchOutside ( f a l s e ) ;
} catch ( IOException e ) { t h i s . progressDialog . setMessage ( ” Converting
Log . e ( ”IO E x c e p t i o n ” , ” S t a c k T r a c e : ” , e ) ; to text . . . ” ) ;
} t h i s . p r o g r e s s D i a l o g . show ( ) ;
}
return ( b o o l e a n ) params [ 1 ] ; }
}
141
Path = Tess2Speech/tess2Speech/src/main/res/layout/activity crop.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : b a c k g r o u n d=” #292929 ” />


<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas .
a n d r o i d . com/ apk / r e s / a n d r o i d ” <Button
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
tools ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : i d=”@+i d / b u t t o n c r o p c o n f i r m ”
a n d r o i d : p a d d i n g B o t t o m=”@dimen/ a n d r o i d : d r a w a b l e B o t t o m=”@mipmap/
activity vertical margin ” ic action tick”
a n d r o i d : p a d d i n g L e f t=”@dimen/ a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
activity horizontal margin ” selectableItemBackground ”
a n d r o i d : p a d d i n g R i g h t=”@dimen/ a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
activity horizontal margin ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : p a d d i n g T o p=”@dimen/ a n d r o i d : l a y o u t m a r g i n L e f t=” 56 dp”
activity vertical margin ” a n d r o i d : l a y o u t b e l o w=”@+i d / CropImageView ”
t o o l s : c o n t e x t=” a n t e r a a r o n . t e s s 2 s p e e c h . />
Activity Crop ”
a n d r o i d : b a c k g r o u n d T i n t M o d e=” m u l t i p l y ” <Button
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<com . t h e a r t o f d e v . edmodo . c r o p p e r . a n d r o i d : i d=”@+i d / b u t t o n c r o p c a n c e l ”
CropImageView a n d r o i d : d r a w a b l e L e f t=”@mipmap/
x m l n s : c u s t o m=” h t t p : // schemas . a n d r o i d . com/ ic action cancel ”
apk / r e s −a u t o ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / CropImageView ” selectableItemBackground ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t m a r g i n R i g h t=” 60 dp”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t m a r g i n E n d=” 60 dp”
c u s t o m : c r o p S c a l e T y p e=” f i t C e n t e r ” a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : l a y o u t a l i g n E n d=”@+i d /
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” CropImageView ” />
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t a b o v e=”@+i d /
button crop cancel ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/activity main.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?>


<a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . <a n d r o i d . s u p p o r t . v7 . w i d g e t . T o o l b a r
C o o r d i n a t o r L a y o u t x m l n s : a n d r o i d=” h t t p : // a n d r o i d : i d=”@+i d / t o o l b a r ”
schemas . a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
x m l n s : a p p=” h t t p : // schemas . a n d r o i d . com/ apk / a n d r o i d : l a y o u t h e i g h t=” ? a t t r /
r e s −a u t o ” actionBarSize ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r P r i m a r y ”
tools ” app:popupTheme=” @ s t y l e /AppTheme .
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” PopupOverlay ” />
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : f i t s S y s t e m W i n d o w s=” t r u e ” </ a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . AppBarLayout
t o o l s : c o n t e x t=” . A c t i v i t y M a i n ”> >

<a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . AppBarLayout <i n c l u d e l a y o u t=” @ l a y o u t / c o n t e n t m a i n ” />


a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” </ a n d r o i d . s u p p o r t . d e s i g n . w i d g e t .
a n d r o i d : t h e m e=” @ s t y l e /AppTheme . C o o r d i n a t o r L a y o u t>
AppBarOverlay ”
a n d r o i d : p a d d i n g L e f t=”−10dp”>

Path = Tess2Speech/tess2Speech/src/main/res/layout/activity rotate.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”


<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : a d j u s t V i e w B o u n d s=” t r u e ”
tools ” a n d r o i d : l a y o u t a b o v e=”@+i d / t e x t V i e w r o t a t e
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : b a c k g r o u n d=” #292929 ”
a n d r o i d : p a d d i n g B o t t o m=”@dimen/ a n d r o i d : c o n t e n t D e s c r i p t i o n=” @ s t r i n g /
activity vertical margin ” i m a g e V i e w r o t a t e c o n t e n t d e s c ” />
a n d r o i d : p a d d i n g L e f t=”@dimen/
activity horizontal margin ”
a n d r o i d : p a d d i n g R i g h t=”@dimen/ <SeekBar
activity horizontal margin ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : p a d d i n g T o p=”@dimen/ a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
activity vertical margin ” a n d r o i d : i d=”@+i d / s e e k B a r r o t a t e ”
t o o l s : c o n t e x t=” . A c t i v i t y R o t a t e ” a n d r o i d : i n d e t e r m i n a t e=” f a l s e ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> a n d r o i d : l a y o u t a b o v e=”@+i d /
b u t t o n r o t a t e s a v e ” />
<ImageView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” <TextView
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : i d=”@+i d / i m a g e V i e w r o t a t e ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”

142
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / ic action tick”
textAppearanceSmall ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / t e x t V i e w r o t a t e ” selectableItemBackground ”
a n d r o i d : l a y o u t a b o v e=”@+i d / s e e k B a r r o t a t e ” a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ” /> a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” f a l s e ”
a n d r o i d : l a y o u t a l i g n T o p=”@+i d /
<Button b u t t o n r o t a t e r e s e t ” />
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” <Button
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : i d=”@+i d / b u t t o n r o t a t e r e s e t ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
ic action undo ” a n d r o i d : i d=”@+i d / b u t t o n r o t a t e e x i t ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : d r a w a b l e L e f t=”@mipmap/
selectableItemBackground ” ic action cancel ”
a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t t o L e f t O f=”@+i d / selectableItemBackground ”
button rotate exit ” a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t t o S t a r t O f=”@+i d / a n d r o i d : l a y o u t a l i g n R i g h t=”@+i d /
b u t t o n r o t a t e e x i t ” /> seekBar rotate ”
a n d r o i d : l a y o u t a l i g n E n d=”@+i d /
seekBar rotate ”
<Button a n d r o i d : l a y o u t a l i g n T o p=”@+i d /
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” b u t t o n r o t a t e r e s e t ” />
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : i d=”@+i d / b u t t o n r o t a t e s a v e ” </ R e l a t i v e L a y o u t>
a n d r o i d : d r a w a b l e B o t t o m=”@mipmap/

Path = Tess2Speech/tess2Speech/src/main/res/layout/alert\_dialog\
_change\_language\_listview.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> <L i s t V i e w


<L i n e a r L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” a n d r o i d : i d=”@+i d / l i s t V i e w c h a n g e l a n g u a g e ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : c h o i c e M o d e=” m u l t i p l e C h o i c e ” />
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”> </ L i n e a r L a y o u t>

Path = Tess2Speech/tess2Speech/src/main/res/layout/alert\_dialog\
_change\_language\_listview\_row.xml

<CheckedTextView x m l n s : a n d r o i d=” h t t p : // schemas a n d r o i d : g r a v i t y=” c e n t e r ”


. a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : d r a w a b l e L e f t=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / c h e ck e d T ex t V i e w ” listChoiceIndicatorMultiple ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : c h e c k e d=” f a l s e ” />
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/alert dialog help.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t i t l e ”


<S c r o l l V i e w x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” < !−−T i p s−−>
a n d r o i d : f i l l V i e w p o r t=” f a l s e ”> <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
<L i n e a r L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” textAppearanceLarge ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p t i p s
a n d r o i d : p a d d i n g S t a r t=” 15 dp” ”
a n d r o i d : p a d d i n g E n d=” 15 dp”> a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t i p s ”
<TextView a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
textAppearanceLarge ” <TextView
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
textView help title ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : t e x t=” @ s t r i n g / t i p s d e s c r i p t i o n ”

143
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t i p s d e s c textAppearanceLarge ”
” a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p s t o p
a n d r o i d : t e x t C o l o r=” #000000 ” ”
a n d r o i d : a u t o L i n k=” none ” a n d r o i d : d r a w a b l e L e f t=”@mipmap/
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” ic action playback stop ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : t e x t S t y l e=” b o l d ”
< !−−Camera−−> a n d r o i d : i d=”@+i d / t e x t V i e w h e l p s t o p ”
<TextView a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
textAppearanceLarge ” <TextView
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
textView help camera ” a n d r o i d : t e x t=” @ s t r i n g / s t o p d e s c r i p t i o n ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : i d=”@+i d /
ic action camera ” textView help stop description ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p c a m e r a ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t S i z e=” 20 s p ” />
< !−−C l e a r−−>
<TextView <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t=” @ s t r i n g / c a m e r a d e s c r i p t i o n a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
” textAppearanceLarge ”
a n d r o i d : i d=”@+i d / a n d r o i d : t e x t=” @ s t r i n g /
textView help camera desc ” textView help clear ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : d r a w a b l e L e f t=”@mipmap/
a n d r o i d : a u t o L i n k=” a l l ” ic action present ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p c l e a r ”
< !−−Browse Image−−> a n d r o i d : t e x t C o l o r=” #000000 ”
<TextView a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / <TextView
textAppearanceLarge ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
textView help browse image ” a n d r o i d : t e x t=” @ s t r i n g / c l e a r d e s c r i p t i o n ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : i d=”@+i d /
ic action picture ” textView help clear description ”
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : i d=”@+i d / a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
textView help browse image ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” < !−−E r a s e−−>
a n d r o i d : t e x t S i z e=” 20 s p ” /> <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
<TextView a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” textAppearanceLarge ”
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : t e x t=” @ s t r i n g /
browse image description ” textView help erase ”
a n d r o i d : i d=”@+i d / a n d r o i d : d r a w a b l e L e f t=”@mipmap/ i c e r a s e r ”
textView help browse image description ” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : i d=”@+i d / t e x t V i e w h e l p e r a s e ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” />
< !−−P l a y−−>
<TextView <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : t e x t=” @ s t r i n g / e r a s e d e s c r i p t i o n ”
textAppearanceLarge ” a n d r o i d : i d=”@+i d /
a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p p l a y textView help erase description ”
” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : a u t o L i n k=” a l l ”
ic action playback play ” a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p p l a y ” < !−−S t r o k e−−>
a n d r o i d : t e x t C o l o r=” #000000 ” <TextView
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” /> a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
<TextView textAppearanceLarge ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t=” @ s t r i n g /
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” textView help stroke ”
a n d r o i d : t e x t=” @ s t r i n g / p l a y d e s c r i p t i o n ” a n d r o i d : d r a w a b l e L e f t=”@mipmap/
a n d r o i d : i d=”@+i d / ic action brush ”
textView help play description ” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : i d=”@+i d / t e x t V i e w h e l p s t r o k e ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” />
< !−−P l a y−−>
<TextView <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : t e x t=” @ s t r i n g / s t r o k e d e s c r i p t i o n

144
” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / textAppearanceLarge ”
textView help stroke description ” a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p c r o p
a n d r o i d : t e x t C o l o r=” #000000 ” ”
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : d r a w a b l e L e f t=”@mipmap/
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” ic action crop ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : t e x t S t y l e=” b o l d ”
< !−−C o n v e r t t o Text−−> a n d r o i d : i d=”@+i d / t e x t V i e w h e l p c r o p ”
<TextView a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
textAppearanceLarge ” <TextView
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
textView help convert text ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : t e x t=” @ s t r i n g / c r o p d e s c r i p t i o n ”
ic action eye open ” a n d r o i d : i d=”@+i d /
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” textView help crop description ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : i d=”@+i d / a n d r o i d : a u t o L i n k=” a l l ”
textView help convert text ” a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” /> < !−−Append t e x t−−>
<TextView
<TextView a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : t e x t=” @ s t r i n g / textAppearanceLarge ”
convert text description ” a n d r o i d : t e x t=” @ s t r i n g /
a n d r o i d : i d=”@+i d / textView help append ”
textView help convert text description ” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : i d=”@+i d / t e x t V i e w h e l p a p p e n d ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” />
< !−−Back t o I n p u t−−>
<TextView <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : t e x t=” @ s t r i n g / a p p e n d d e s c r i p t i o n
textAppearanceLarge ” ”
a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p b a c k a n d r o i d : i d=”@+i d /
” textView help append description ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : t e x t C o l o r=” #000000 ”
ic action eye closed ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p b a c k ”
a n d r o i d : t e x t C o l o r=” #000000 ” < !−−Browse PDF−−>
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” <TextView
a n d r o i d : t e x t S i z e=” 20 s p ” /> a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<TextView a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” textAppearanceLarge ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t=” @ s t r i n g /
a n d r o i d : t e x t=” @ s t r i n g / b a c k d e s c r i p t i o n ” textView help browse pdf ”
a n d r o i d : i d=”@+i d / a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
textView help back description ” a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : i d=”@+i d /
a n d r o i d : a u t o L i n k=” a l l ” textView help browse pdf ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t S i z e=” 20 s p ” />
< !−−R o t a t e−−>
<TextView <TextView
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : t e x t=” @ s t r i n g /
textAppearanceLarge ” browse pdf description ”
a n d r o i d : t e x t=” @ s t r i n g / a n d r o i d : i d=”@+i d /
textView help rotate ” textView help browse pdf description ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ a n d r o i d : t e x t C o l o r=” #000000 ”
ic action turn left” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p r o t a t e ”
a n d r o i d : t e x t C o l o r=” #000000 ” < !−−Browse Epub−−>
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” <TextView
a n d r o i d : t e x t S i z e=” 20 s p ” /> a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<TextView a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” textAppearanceLarge ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t=” @ s t r i n g /
a n d r o i d : t e x t=” @ s t r i n g / r o t a t e d e s c r i p t i o n textView help browse epub ”
” a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : i d=”@+i d / a n d r o i d : t e x t S t y l e=” b o l d ”
textView help rotate description ” a n d r o i d : i d=”@+i d /
a n d r o i d : t e x t C o l o r=” #000000 ” textView help browse epub ”
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : t e x t S i z e=” 20 s p ” />

< !−−Crop−−> <TextView


<TextView a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t=” @ s t r i n g /

145
browse epub description ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : i d=”@+i d / a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
textView help browse epub description ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : a u t o L i n k=” a l l ” <TextView
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t=” @ s t r i n g / t o P d f d e s c r i p t i o n ”
< !−−T a b l e o f c o n t e n t s−−> a n d r o i d : i d=”@+i d /
<TextView textView help toPdf description ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
textAppearanceLarge ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p t o c ”
a n d r o i d : d r a w a b l e L e f t=”@mipmap/ < !−−C o n v e r t PDF t o Image−−>
ic action document ” <TextView
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t o c ” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : t e x t C o l o r=” #000000 ” textAppearanceLarge ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” a n d r o i d : t e x t=” @ s t r i n g /
a n d r o i d : t e x t S i z e=” 20 s p ” /> textView help toImage ”
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
<TextView a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t o I m a g e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : t e x t=” @ s t r i n g / t o c d e s c r i p t i o n ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : i d=”@+i d / a n d r o i d : t e x t S i z e=” 20 s p ” />
textView help toc description ”
a n d r o i d : t e x t C o l o r=” #000000 ” <TextView
a n d r o i d : a u t o L i n k=” a l l ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : t e x t=” @ s t r i n g /
toImage description ”
< !−−Save a s−−> a n d r o i d : i d=”@+i d /
<TextView textView help toImage description ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
textAppearanceLarge ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w h e l p s a v e
” < !−−F i l e d i r e c t o r i e s−−>
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” <TextView
a n d r o i d : t e x t S t y l e=” b o l d ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p s a v e ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r /
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ” textAppearanceLarge ”
a n d r o i d : t e x t S i z e=” 20 s p ” /> a n d r o i d : t e x t=” @ s t r i n g /
textView help directories ”
<TextView a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : i d=”@+i d /
a n d r o i d : t e x t=” @ s t r i n g / s a v e d e s c r i p t i o n ” textView help directories ”
a n d r o i d : i d=”@+i d / a n d r o i d : t e x t C o l o r=” #000000 ”
textView help save description ” a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r A c c e n t ”
a n d r o i d : t e x t C o l o r=” #000000 ” a n d r o i d : t e x t S i z e=” 20 s p ” />
a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : l i n k s C l i c k a b l e=” t r u e ” <TextView
a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” /> a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
< !−−C o n v e r t image t o s e a r c h a b l e PDF−−> a n d r o i d : i d=”@+i d /
<TextView textView help directories description ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t C o l o r=” #000000 ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : a u t o L i n k=” a l l ”
a n d r o i d : t e x t A p p e a r a n c e=” ? a n d r o i d : a t t r / a n d r o i d : l i n k s C l i c k a b l e=” t r u e ”
textAppearanceLarge ” a n d r o i d : l a y o u t m a r g i n B o t t o m=” 15 dp” />
a n d r o i d : t e x t=” @ s t r i n g /
textView help toPdf ” </ L i n e a r L a y o u t>
a n d r o i d : g r a v i t y=” c e n t e r v e r t i c a l ” </ S c r o l l V i e w>
a n d r o i d : t e x t S t y l e=” b o l d ”
a n d r o i d : i d=”@+i d / t e x t V i e w h e l p t o P d f ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/alert dialog page select.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”


<L i n e a r L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : t e x t=” S e l e c t P a g e s : ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : i d=”@+i d / r a d i o B u t t o n p d f s e l e c t ”
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” a n d r o i d : c h e c k e d=” f a l s e ” />
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” </ RadioGroup>
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : w e i g h t S u m=” 1 ”> <E d i t T e x t
a n d r o i d : l a y o u t w i d t h=” 205 dp”
<RadioGroup a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : i n p u t T y p e=” number ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : e m s=” 10 ”
a n d r o i d : i d=”@+i d / r a d i o G r o u p p d f ”> a n d r o i d : i d=”@+i d / e d i t T e x t p d f ”
a n d r o i d : d i g i t s=” 0 1 2 3 4 5 6 7 8 9 , ”
<RadioButton a n d r o i d : c o n t e x t C l i c k a b l e=” f a l s e ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : p a d d i n g S t a r t=” 10 dp”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : p a d d i n g E n d=” 10 dp”
a n d r o i d : t e x t=” A l l ” a n d r o i d : p h o n e N u m b e r=” f a l s e ”
a n d r o i d : i d=”@+i d / r a d i o B u t t o n p d f a l l ” a n d r o i d : e n a b l e d=” f a l s e ”
a n d r o i d : c h e c k e d=” t r u e ” /> a n d r o i d : f o c u s a b l e I n T o u c h M o d e=” f a l s e ” />

<RadioButton </ L i n e a r L a y o u t>


a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” 146
Path = Tess2Speech/tess2Speech/src/main/res/layout/content main.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .


<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . Fragment ConvertedText ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : t a g=” f r a g m e n t t e x t ”
x m l n s : a p p=” h t t p : // schemas . a n d r o i d . com/ apk / a n d r o i d : i d=”@+i d / f r a g m e n t 2 ”
r e s −a u t o ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
tools ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : i d=”@+i d / l a y o u t ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a p p : l a y o u t b e h a v i o r=” @ s t r i n g / <f r a g m e n t
appbar scrolling view behavior ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
t o o l s : c o n t e x t=” . A c t i v i t y M a i n ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
t o o l s : s h o w I n=” @ l a y o u t / a c t i v i t y m a i n ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> Fragment InputImage ”
a n d r o i d : t a g=” f r a g m e n t i m a g e ”
<Button a n d r o i d : i d=”@+i d / f r a g m e n t 3 ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n p l a y ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : i d=”@+i d / b u t t o n p l a y ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
ic action playback play ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / <f r a g m e n t
selectableItemBackground ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ” Fragment PdfViewer ”
a n d r o i d : l a y o u t m a r g i n L e f t=” 5dp” a n d r o i d : t a g=” f r a g m e n t p d f ”
a n d r o i d : t e x t S i z e=” 11 s p ” /> a n d r o i d : i d=”@+i d / f r a g m e n t 4 ”
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
<Button a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n t e x t ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : i d=”@+i d / b u t t o n t e x t ” <f r a g m e n t
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
ic action eye open ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
selectableItemBackground ” Fragment EPubViewer TOC ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : t a g=” f r a g m e n t e p u b t o c ”
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” f a l s e ” a n d r o i d : i d=”@+i d / f r a g m e n t 5 ”
a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t a l i g n B o t t o m=”@+i d / a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
button play ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t m a r g i n R i g h t=” 15 dp” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : t e x t S i z e=” 11 s p ” /> a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” />
<f r a g m e n t
<f r a g m e n t a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h . Fragment EPubViewer ”
Fragment DrawingCanvas ” a n d r o i d : t a g=” f r a g m e n t e p u b ”
a n d r o i d : t a g=” f r a g m e n t c a n v a s ” a n d r o i d : i d=”@+i d / f r a g m e n t 6 ”
a n d r o i d : i d=”@+i d / f r a g m e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
<f r a g m e n t
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/fragment canvas.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”


a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
tools ” a n d r o i d : t e x t=” @ s t r i n g / b u t t o n s t r o k e ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : i d=”@+i d / b u t t o n s t r o k e ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
t o o l s : c o n t e x t=” . Fragment DrawingCanvas ” top ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> a n d r o i d : d r a w a b l e T o p=”@mipmap/ i c e r a s e r ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
<a n t e r a a r o n . t e s s 2 s p e e c h . DrawingView selectableItemBackground ”
a n d r o i d : i d=”@+i d / d r a w i n g ” a n d r o i d : t e x t S i z e=” 11 s p ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t a l i g n T o p=”@+i d / b u t t o n c l e a r
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” ”
a n d r o i d : b a c k g r o u n d=”#FFFFFFFF” a n d r o i d : l a y o u t t o R i g h t O f=”@+i d /
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” button clear ”
a n d r o i d : l a y o u t b e l o w=”@+i d / b u t t o n s t r o k e ” a n d r o i d : l a y o u t t o E n d O f=”@+i d / b u t t o n c l e a r ”
/> a n d r o i d : l a y o u t m a r g i n L e f t=” 15 dp” />

<Button <Button

147
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” selectableItemBackground ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 11 s p ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n c l e a r ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : i d=”@+i d / b u t t o n c l e a r ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l | a n d r o i d : l a y o u t m a r g i n L e f t=” 10 dp” />
top ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ </ R e l a t i v e L a y o u t>
ic action present ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /

Path = Tess2Speech/tess2Speech/src/main/res/layout/fragment converted text.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” />


a n d r o i d . com/ apk / r e s / a n d r o i d ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ <E d i t T e x t
tools ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : i n p u t T y p e=” t e x t M u l t i L i n e ”
t o o l s : c o n t e x t=” . F r a g m e n t C o n v e r t e d T e x t ” a n d r o i d : i d=”@+i d / e d i t T e x t ”
a n d r o i d : b a c k g r o u n d=”# f f f f f f ”> a n d r o i d : g r a v i t y=” t o p ”
a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
< !−− TODO: Update b l a n k f r a g m e n t l a y o u t −−> top ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
<S w i t c h a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a b o v e=”@+i d / s w i t c h a p p e n d ”
a n d r o i d : t e x t=” @ s t r i n g / s w i t c h a p p e n d ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | bottom ” a n d r o i d : p a d d i n g=” 15 dp”
a n d r o i d : c h e c k e d=” f a l s e ” a n d r o i d : h i n t=” @ s t r i n g / p l a c e h o l d e r ” />
a n d r o i d : i d=”@+i d / s w i t c h a p p e n d ”
a n d r o i d : t e x t S i z e=” 21 s p ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/fragment epub.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”


a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : t e x t=” @ s t r i n g / b u t t o n b a c k ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : i d=”@+i d /
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” button epub back to canvas ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : d r a w a b l e T o p=”@mipmap/
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” ic action present ”
a n d r o i d : w e i g h t S u m=” 1 ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / e p u b l a y o u t ”> selectableItemBackground ”
a n d r o i d : t e x t S i z e=” 11 s p ”
a n d r o i d : l a y o u t a b o v e=”@+i d / webView epub ”
<Button a n d r o i d : l a y o u t t o R i g h t O f=”@+i d /
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” button epub back to toc ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t t o E n d O f=”@+i d /
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” button epub back to toc ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n e p u b b a c k ” a n d r o i d : l a y o u t m a r g i n L e f t=” 10 dp” />
a n d r o i d : i d=”@+i d / b u t t o n e p u b b a c k t o t o c ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/
ic action document ” <WebView
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
selectableItemBackground ” a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” a n d r o i d : i d=”@+i d / webView epub ”
a n d r o i d : t e x t S i z e=” 11 s p ” /> a n d r o i d : l a y o u t b e l o w=”@+i d /
b u t t o n e p u b b a c k t o t o c ” />
<Button </ R e l a t i v e L a y o u t>
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/fragment input image.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”


a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : i d=”@+i d / imageView ”
tools ” a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ”
x m l n s : g e s t u r e −image=” h t t p : // schemas . p o l i t e s . g e s t u r e −image:min−s c a l e=” 0 . 1 ”
com/ a n d r o i d ” g e s t u r e −image:max−s c a l e=” 1 0 . 0 ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” g e s t u r e −i m a g e : s t r i c t=” f a l s e ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t b e l o w=”@+i d / b u t t o n b a c k ” />
t o o l s : c o n t e x t=” . F r a g m e n t I n p u t I m a g e ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> <Button
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
< !−− TODO: Update b l a n k f r a g m e n t l a y o u t −−> a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<com . p o l i t e s . a n d r o i d . GestureImageView a n d r o i d : t e x t=” @ s t r i n g / b u t t o n b a c k ”

148
a n d r o i d : i d=”@+i d / b u t t o n b a c k ” ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : t e x t S i z e=” 11 s p ” />
ic action present ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / <Button
selectableItemBackground ” s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t m a r g i n L e f t=” 10 dp” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : t e x t S i z e=” 11 s p ” /> a n d r o i d : t e x t=” @ s t r i n g / b u t t o n c r o p ”
a n d r o i d : i d=”@+i d / b u t t o n c r o p ”
<Button a n d r o i d : d r a w a b l e T o p=”@mipmap/
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” ic action crop ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” selectableItemBackground ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n r o t a t e ” a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
a n d r o i d : i d=”@+i d / b u t t o n r o t a t e ” top ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
ic action turn left” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
selectableItemBackground ” a n d r o i d : l a y o u t m a r g i n L e f t=” 15 dp”
a n d r o i d : l a y o u t g r a v i t y=” r i g h t | t o p ” a n d r o i d : l a y o u t m a r g i n R i g h t=” 10 dp”
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : l a y o u t t o L e f t O f=”@+i d / b u t t o n c r o p ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t t o S t a r t O f=”@+i d / b u t t o n c r o p

Path = Tess2Speech/tess2Speech/src/main/res/layout/fragment pdf viewer.xml

<FrameLayout x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : a l p h a=” 0 . 7 ”


a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : t e x t C o l o r=”# f f f f f f ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : t e x t A l i g n m e n t=” c e n t e r ”
tools ” a n d r o i d : t e x t S i z e=” 16 s p ” />
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” <Button
t o o l s : c o n t e x t=” a n t e r a a r o n . t e s s 2 s p e e c h . s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
F r a g m e n t P d f V i e w e r ”> a n d r o i d : l a y o u t w i d t h=” 79 dp”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<com . j o a n z a p a t a . p d f v i e w . PDFView a n d r o i d : t e x t=” @ s t r i n g / b u t t o n p d f b a c k ”
a n d r o i d : i d=”@+i d / pdfView ” a n d r o i d : i d=”@+i d / b u t t o n p d f b a c k ”
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ” a n d r o i d : d r a w a b l e T o p=”@mipmap/
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ” /> ic action present ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
<TextView selectableItemBackground ”
a n d r o i d : l a y o u t w i d t h=” 82 dp” a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : i d=”@+i d / t e x t V i e w p d f ”
a n d r o i d : l a y o u t g r a v i t y=” r i g h t | bottom ” </ FrameLayout>
a n d r o i d : b a c k g r o u n d=”#0a 0 a 0 a ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/splash screen.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : v i s i b i l i t y =” v i s i b l e ” />


<FrameLayout x m l n s : a n d r o i d=” h t t p : // schemas .
a n d r o i d . com/ apk / r e s / a n d r o i d ” <TextView
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”> a n d r o i d : t e x t=” @ s t r i n g / t e x t V i e w s p l a s h ”
a n d r o i d : i d=”@+i d / t e x t V i e w s p l a s h ”
<ImageView a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” bottom ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : t e x t C o l o r=”# f f f f f f ”
a n d r o i d : i d=”@+i d / i m a g e V i e w s p l a s h ” a n d r o i d : l a y o u t m a r g i n=” 10 dp”
a n d r o i d : s r c=” @drawable / s p l a s h ” a n d r o i d : v i s i b i l i t y =” i n v i s i b l e ” />
a n d r o i d : c o n t e n t D e s c r i p t i o n=” @ s t r i n g /
imageView splash desc ” </ FrameLayout>
a n d r o i d : s c a l e T y p e=” f i t X Y ”

Path = Tess2Speech/tess2Speech/src/main/res/layout/view epub listview.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> ic action present ”


<L i n e a r L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d . com/ apk / r e s / a n d r o i d ” selectableItemBackground ”
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : p a d d i n g L e f t=” 8dp” <L i s t V i e w a n d r o i d : i d=” @id / a n d r o i d : l i s t ”
a n d r o i d : p a d d i n g R i g h t=” 8dp” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> a n d r o i d : l a y o u t h e i g h t=” 0dp”
a n d r o i d : l a y o u t w e i g h t=” 1 ”
<Button a n d r o i d : d r a w S e l e c t o r O n T o p=” f a l s e ” />
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” <TextView a n d r o i d : i d=” @id / a n d r o i d : e m p t y ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n b a c k ” a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” />
a n d r o i d : i d=”@+i d / b u t t o n e p u b t o c b a c k ” </ L i n e a r L a y o u t>
a n d r o i d : d r a w a b l e T o p=”@mipmap/ 149
Path = Tess2Speech/tess2Speech/src/main/res/layout/view epub listvie row.xml

<TextView x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : t e x t C o l o r=” #000000 ”


a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : t e x t S i z e=” 20 s p ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t I s S e l e c t a b l e=” f a l s e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : p a d d i n g=” 15 dp”
a n d r o i d : t e x t=”New Text ” a n d r o i d : b a c k g r o u n d=”# f f f f f f ” />
a n d r o i d : i d=”@+i d / row ”
a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l ”

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/activity crop.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : b a c k g r o u n d=” #292929 ” />


<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas .
a n d r o i d . com/ apk / r e s / a n d r o i d ” <Button
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
tools ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : i d=”@+i d / b u t t o n c r o p c o n f i r m ”
a n d r o i d : p a d d i n g B o t t o m=”@dimen/ a n d r o i d : d r a w a b l e B o t t o m=”@mipmap/
activity vertical margin ” ic action tick”
a n d r o i d : p a d d i n g L e f t=”@dimen/ a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
activity horizontal margin ” selectableItemBackground ”
a n d r o i d : p a d d i n g R i g h t=”@dimen/ a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
activity horizontal margin ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : p a d d i n g T o p=”@dimen/ a n d r o i d : l a y o u t m a r g i n L e f t=” 56 dp”
activity vertical margin ” a n d r o i d : l a y o u t b e l o w=”@+i d / CropImageView ”
t o o l s : c o n t e x t=” a n t e r a a r o n . t e s s 2 s p e e c h . />
Activity Crop ”
a n d r o i d : b a c k g r o u n d T i n t M o d e=” m u l t i p l y ” <Button
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
<com . t h e a r t o f d e v . edmodo . c r o p p e r . a n d r o i d : i d=”@+i d / b u t t o n c r o p c a n c e l ”
CropImageView a n d r o i d : d r a w a b l e L e f t=”@mipmap/
x m l n s : c u s t o m=” h t t p : // schemas . a n d r o i d . com/ ic action cancel ”
apk / r e s −a u t o ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : i d=”@+i d / CropImageView ” selectableItemBackground ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t m a r g i n R i g h t=” 60 dp”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t m a r g i n E n d=” 60 dp”
c u s t o m : c r o p S c a l e T y p e=” f i t C e n t e r ” a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : l a y o u t a l i g n E n d=”@+i d /
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” CropImageView ” />
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t a b o v e=”@+i d /
button crop cancel ”

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/activity main.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?>


<a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . <a n d r o i d . s u p p o r t . v7 . w i d g e t . T o o l b a r
C o o r d i n a t o r L a y o u t x m l n s : a n d r o i d=” h t t p : // a n d r o i d : i d=”@+i d / t o o l b a r ”
schemas . a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
x m l n s : a p p=” h t t p : // schemas . a n d r o i d . com/ apk / a n d r o i d : l a y o u t h e i g h t=” ? a t t r /
r e s −a u t o ” actionBarSize ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r P r i m a r y ”
tools ” app:popupTheme=” @ s t y l e /AppTheme .
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” PopupOverlay ” />
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : f i t s S y s t e m W i n d o w s=” t r u e ” </ a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . AppBarLayout
t o o l s : c o n t e x t=” . A c t i v i t y M a i n ”> >

<a n d r o i d . s u p p o r t . d e s i g n . w i d g e t . AppBarLayout <i n c l u d e l a y o u t=” @ l a y o u t / c o n t e n t m a i n ” />


a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” </ a n d r o i d . s u p p o r t . d e s i g n . w i d g e t .
a n d r o i d : t h e m e=” @ s t y l e /AppTheme . C o o r d i n a t o r L a y o u t>
AppBarOverlay ”
a n d r o i d : p a d d i n g L e f t=”−10dp”>

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/content main.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> tools ”


<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
x m l n s : a p p=” h t t p : // schemas . a n d r o i d . com/ apk / a n d r o i d : i d=”@+i d / l a y o u t ”
r e s −a u t o ” a p p : l a y o u t b e h a v i o r=” @ s t r i n g /
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ appbar scrolling view behavior ”

150
t o o l s : c o n t e x t=” . A c t i v i t y M a i n ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
t o o l s : s h o w I n=” @ l a y o u t / a c t i v i t y m a i n ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
<Button <f r a g m e n t
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n p l a y ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : i d=”@+i d / b u t t o n p l a y ” Fragment InputImage ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : t a g=” f r a g m e n t i m a g e ”
ic action playback play ” a n d r o i d : i d=”@+i d / f r a g m e n t 3 ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
selectableItemBackground ” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t m a r g i n L e f t=” 5dp” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : t e x t S i z e=” 11 s p ” /> <f r a g m e n t
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
<Button a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” Fragment PdfViewer ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : t a g=” f r a g m e n t p d f ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n t e x t ” a n d r o i d : i d=”@+i d / f r a g m e n t 4 ”
a n d r o i d : i d=”@+i d / b u t t o n t e x t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
ic action eye open ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
selectableItemBackground ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” f a l s e ” <f r a g m e n t
a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t a l i g n B o t t o m=”@+i d / a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
button play ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : l a y o u t m a r g i n R i g h t=” 15 dp” Fragment EPubViewer TOC ”
a n d r o i d : t e x t S i z e=” 11 s p ” /> a n d r o i d : t a g=” f r a g m e n t e p u b t o c ”
a n d r o i d : i d=”@+i d / f r a g m e n t 5 ”
<f r a g m e n t a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h . a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
Fragment DrawingCanvas ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” />
a n d r o i d : t a g=” f r a g m e n t c a n v a s ” <f r a g m e n t
a n d r o i d : i d=”@+i d / f r a g m e n t ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ” a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h .
a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” Fragment EPubViewer ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ” a n d r o i d : t a g=” f r a g m e n t e p u b ”
a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ” a n d r o i d : i d=”@+i d / f r a g m e n t 6 ”
a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” /> a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
<f r a g m e n t a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : n a m e=” a n t e r a a r o n . t e s s 2 s p e e c h . a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
Fragment ConvertedText ” a n d r o i d : l a y o u t a b o v e=”@+i d / b u t t o n t e x t ” />
a n d r o i d : t a g=” f r a g m e n t t e x t ”
a n d r o i d : i d=”@+i d / f r a g m e n t 2 ”
a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/fragment canvas.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : t e x t S i z e=” 11 s p ”


a n d r o i d . com/ apk / r e s / a n d r o i d ” a n d r o i d : l a y o u t a l i g n T o p=”@+i d / b u t t o n c l e a r
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ ”
tools ” a n d r o i d : l a y o u t t o R i g h t O f=”@+i d /
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” button clear ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t t o E n d O f=”@+i d / b u t t o n c l e a r ”
t o o l s : c o n t e x t=” . Fragment DrawingCanvas ” a n d r o i d : l a y o u t m a r g i n L e f t=” 15 dp” />
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”>
<Button
<a n t e r a a r o n . t e s s 2 s p e e c h . DrawingView s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : i d=”@+i d / d r a w i n g ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : t e x t=” @ s t r i n g / b u t t o n c l e a r ”
a n d r o i d : b a c k g r o u n d=”#FFFFFFFF” a n d r o i d : i d=”@+i d / b u t t o n c l e a r ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
a n d r o i d : l a y o u t b e l o w=”@+i d / b u t t o n s t r o k e ” top ”
/> a n d r o i d : d r a w a b l e T o p=”@mipmap/
ic action present ”
<Button a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” selectableItemBackground ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : t e x t S i z e=” 11 s p ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n s t r o k e ” a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
a n d r o i d : i d=”@+i d / b u t t o n s t r o k e ” a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l | a n d r o i d : l a y o u t m a r g i n L e f t=” 10 dp” />
top ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ i c e r a s e r ” </ R e l a t i v e L a y o u t>
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
selectableItemBackground ”

151
Path = Tess2Speech/tess2Speech/src/main/res/layout-land/fragment\
_converted\_text.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ” />


a n d r o i d . com/ apk / r e s / a n d r o i d ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ <E d i t T e x t
tools ” a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : i n p u t T y p e=” t e x t M u l t i L i n e ”
t o o l s : c o n t e x t=” . F r a g m e n t C o n v e r t e d T e x t ” a n d r o i d : i d=”@+i d / e d i t T e x t ”
a n d r o i d : b a c k g r o u n d=”# f f f f f f ”> a n d r o i d : g r a v i t y=” t o p ”
a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
< !−− TODO: Update b l a n k f r a g m e n t l a y o u t −−> top ”
a n d r o i d : l a y o u t a l i g n P a r e n t L e f t=” t r u e ”
<S w i t c h a n d r o i d : l a y o u t a l i g n P a r e n t S t a r t=” t r u e ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t a b o v e=”@+i d / s w i t c h a p p e n d ”
a n d r o i d : t e x t=” @ s t r i n g / s w i t c h a p p e n d ” a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | bottom ” a n d r o i d : p a d d i n g=” 15 dp”
a n d r o i d : c h e c k e d=” f a l s e ” a n d r o i d : h i n t=” @ s t r i n g / p l a c e h o l d e r ” />
a n d r o i d : i d=”@+i d / s w i t c h a p p e n d ”
a n d r o i d : t e x t S i z e=” 21 s p ” </ R e l a t i v e L a y o u t>
a n d r o i d : l a y o u t a l i g n P a r e n t B o t t o m=” t r u e ”
a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/fragment input image.xml

<R e l a t i v e L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . <Button


a n d r o i d . com/ apk / r e s / a n d r o i d ” s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
tools ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
x m l n s : g e s t u r e −image=” h t t p : // schemas . p o l i t e s . a n d r o i d : t e x t=” @ s t r i n g / b u t t o n r o t a t e ”
com/ a n d r o i d ” a n d r o i d : i d=”@+i d / b u t t o n r o t a t e ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : d r a w a b l e T o p=”@mipmap/
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” ic action turn left”
t o o l s : c o n t e x t=” . F r a g m e n t I n p u t I m a g e ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> selectableItemBackground ”
a n d r o i d : l a y o u t g r a v i t y=” r i g h t | t o p ”
< !−− TODO: Update b l a n k f r a g m e n t l a y o u t −−> a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
a n d r o i d : l a y o u t t o L e f t O f=”@+i d / b u t t o n c r o p ”
<com . p o l i t e s . a n d r o i d . GestureImageView a n d r o i d : l a y o u t t o S t a r t O f=”@+i d / b u t t o n c r o p
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : i d=”@+i d / imageView ”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” <Button
g e s t u r e −image:min−s c a l e=” 0 . 1 ” s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
g e s t u r e −image:max−s c a l e=” 1 0 . 0 ” a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ”
g e s t u r e −i m a g e : s t r i c t=” f a l s e ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t b e l o w=”@+i d / b u t t o n b a c k ” /> a n d r o i d : t e x t=” @ s t r i n g / b u t t o n c r o p ”
a n d r o i d : i d=”@+i d / b u t t o n c r o p ”
<Button a n d r o i d : d r a w a b l e T o p=”@mipmap/
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” ic action crop ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” selectableItemBackground ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n b a c k ” a n d r o i d : l a y o u t g r a v i t y=” c e n t e r h o r i z o n t a l |
a n d r o i d : i d=”@+i d / b u t t o n b a c k ” top ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ a n d r o i d : l a y o u t a l i g n P a r e n t T o p=” t r u e ”
ic action present ” a n d r o i d : l a y o u t a l i g n P a r e n t R i g h t=” t r u e ”
a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r / a n d r o i d : l a y o u t a l i g n P a r e n t E n d=” t r u e ”
selectableItemBackground ” a n d r o i d : l a y o u t m a r g i n L e f t=” 15 dp”
a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ” a n d r o i d : l a y o u t m a r g i n R i g h t=” 10 dp”
a n d r o i d : l a y o u t m a r g i n L e f t=” 10 dp” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : t e x t S i z e=” 11 s p ” /> </ R e l a t i v e L a y o u t>

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/fragment pdf viewer.xml

<FrameLayout x m l n s : a n d r o i d=” h t t p : // schemas .


a n d r o i d . com/ apk / r e s / a n d r o i d ” <TextView
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : l a y o u t w i d t h=” 82 dp”
tools ” a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : i d=”@+i d / t e x t V i e w p d f ”
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” a n d r o i d : l a y o u t g r a v i t y=” r i g h t | bottom ”
t o o l s : c o n t e x t=” a n t e r a a r o n . t e s s 2 s p e e c h . a n d r o i d : b a c k g r o u n d=”#0a 0 a 0 a ”
F r a g m e n t P d f V i e w e r ”> a n d r o i d : a l p h a=” 0 . 7 ”
a n d r o i d : t e x t C o l o r=”# f f f f f f ”
<com . j o a n z a p a t a . p d f v i e w . PDFView a n d r o i d : t e x t A l i g n m e n t=” c e n t e r ”
a n d r o i d : i d=”@+i d / pdfView ” a n d r o i d : t e x t S i z e=” 16 s p ” />
a n d r o i d : l a y o u t w i d t h=” f i l l p a r e n t ”
a n d r o i d : l a y o u t h e i g h t=” f i l l p a r e n t ” /> <Button

152
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ” a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d : l a y o u t w i d t h=” 79 dp” selectableItemBackground ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n p d f b a c k ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : i d=”@+i d / b u t t o n p d f b a c k ”
a n d r o i d : d r a w a b l e T o p=”@mipmap/ </ FrameLayout>
ic action present ”

Path = Tess2Speech/tess2Speech/src/main/res/layout-land/view epub listview.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> ic action present ”


<L i n e a r L a y o u t x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d : b a c k g r o u n d=” ? a n d r o i d : a t t r /
a n d r o i d . com/ apk / r e s / a n d r o i d ” selectableItemBackground ”
a n d r o i d : o r i e n t a t i o n=” v e r t i c a l ” a n d r o i d : l a y o u t g r a v i t y=” l e f t | t o p ”
a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ” a n d r o i d : t e x t S i z e=” 11 s p ” />
a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ”
a n d r o i d : p a d d i n g L e f t=” 8dp” <L i s t V i e w a n d r o i d : i d=” @id / a n d r o i d : l i s t ”
a n d r o i d : p a d d i n g R i g h t=” 8dp” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : b a c k g r o u n d=” @ c o l o r / c o l o r B a c k g r o u n d ”> a n d r o i d : l a y o u t h e i g h t=” 0dp”
a n d r o i d : l a y o u t w e i g h t=” 1 ”
<Button a n d r o i d : d r a w S e l e c t o r O n T o p=” f a l s e ” />
s t y l e=” ? a n d r o i d : a t t r / b u t t o n S t y l e S m a l l ”
a n d r o i d : l a y o u t w i d t h=” w r a p c o n t e n t ” <TextView a n d r o i d : i d=” @id / a n d r o i d : e m p t y ”
a n d r o i d : l a y o u t h e i g h t=” w r a p c o n t e n t ” a n d r o i d : l a y o u t w i d t h=” m a t c h p a r e n t ”
a n d r o i d : t e x t=” @ s t r i n g / b u t t o n b a c k ” a n d r o i d : l a y o u t h e i g h t=” m a t c h p a r e n t ” />
a n d r o i d : i d=”@+i d / b u t t o n e p u b t o c b a c k ” </ L i n e a r L a y o u t>
a n d r o i d : d r a w a b l e T o p=”@mipmap/

Path = Tess2Speech/tess2Speech/src/main/res/menu/menu main.xml

<menu x m l n s : a n d r o i d=” h t t p : // schemas . a n d r o i d . a p p : s h o w A s A c t i o n=” n e v e r ” />


com/ apk / r e s / a n d r o i d ” <i t e m
x m l n s : a p p=” h t t p : // schemas . a n d r o i d . com/ apk / a n d r o i d : i d=”@+i d / s a v e P d f ”
r e s −a u t o ” a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
x m l n s : t o o l s=” h t t p : // schemas . a n d r o i d . com/ a n d r o i d : t i t l e =” @ s t r i n g / s a v e p d f ”
tools ” a p p : s h o w A s A c t i o n=” n e v e r ” />
t o o l s : c o n t e x t=” . A c t i v i t y M a i n ”> <i t e m
a n d r o i d : i d=”@+i d / s a v e A u d i o ”
<i t e m a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
a n d r o i d : i d=”@+i d / camera ” a n d r o i d : t i t l e =” @ s t r i n g / s a v e a u d i o ”
a n d r o i d : o r d e r I n C a t e g o r y=” 100 ” a p p : s h o w A s A c t i o n=” n e v e r ” />
a n d r o i d : t i t l e =” @ s t r i n g / camera ” <i t e m
a n d r o i d : i c o n=”@mipmap/ i c a c t i o n c a m e r a ” a n d r o i d : i d=”@+i d / imageToPdf ”
a p p : s h o w A s A c t i o n=” a l w a y s ” /> a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
<i t e m a n d r o i d : t i t l e =” @ s t r i n g / i m a g e t o p d f ”
a n d r o i d : i d=”@+i d / b r o w s e ” a p p : s h o w A s A c t i o n=” n e v e r ” />
a n d r o i d : o r d e r I n C a t e g o r y=” 100 ” <i t e m
a n d r o i d : t i t l e =” @ s t r i n g / b r o w s e ” a n d r o i d : i d=”@+i d / pdfToImage ”
a n d r o i d : i c o n=”@mipmap/ i c a c t i o n p i c t u r e ” a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
a p p : s h o w A s A c t i o n=” ifRoom ” /> a n d r o i d : t i t l e =” @ s t r i n g / p d f t o i m a g e ”
<i t e m a p p : s h o w A s A c t i o n=” n e v e r ” />
a n d r o i d : i d=”@+i d / b r o w s e P d f ” <i t e m
a n d r o i d : o r d e r I n C a t e g o r y=” 100 ” a n d r o i d : i d=”@+i d / s e t t i n g s ”
a n d r o i d : t i t l e =” @ s t r i n g / b r o w s e P d f ” a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
a p p : s h o w A s A c t i o n=” n e v e r ” /> a n d r o i d : t i t l e =” @ s t r i n g / s e t t i n g s ”
<i t e m a p p : s h o w A s A c t i o n=” n e v e r ” />
a n d r o i d : i d=”@+i d / browseEpub ” <i t e m
a n d r o i d : o r d e r I n C a t e g o r y=” 100 ” a n d r o i d : i d=”@+i d / e x i t ”
a n d r o i d : t i t l e =” @ s t r i n g / browseEpub ” a n d r o i d : o r d e r I n C a t e g o r y=” 100 ”
a p p : s h o w A s A c t i o n=” n e v e r ” /> a n d r o i d : t i t l e =” @ s t r i n g / e x i t ”
<i t e m a p p : s h o w A s A c t i o n=” n e v e r ” />
a n d r o i d : i d=”@+i d / s a v e T e x t ”
a n d r o i d : o r d e r I n C a t e g o r y=” 100 ” </menu>
a n d r o i d : t i t l e =” @ s t r i n g / s a v e t e x t ”

Path = Tess2Speech/tess2Speech/src/main/res/values/colors.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> < c o l o r name=” c o l o r A c c e n t ”>#117b79</ c o l o r>
<r e s o u r c e s> < c o l o r name=” c o l o r B a c k g r o u n d ”> #e 6 e 0 e 0</
< c o l o r name=” c o l o r P r i m a r y ”>#7B1113</ c o l o r> c o l o r>
< c o l o r name=” c o l o r P r i m a r y D a r k ”>#660101</ </ r e s o u r c e s>
c o l o r>

Path = Tess2Speech/tess2Speech/src/main/res/values/dimens.xml

153
<r e s o u r c e s> <dimen name=” a c t i v i t y v e r t i c a l m a r g i n ”>16 dp<
< !−− D e f a u l t s c r e e n m a r g i n s , p e r t h e Android / dimen>
D e s i g n g u i d e l i n e s . −−> <dimen name=” f a b m a r g i n ”>16 dp</ dimen>
<dimen name=” a c t i v i t y h o r i z o n t a l m a r g i n ”>16 </ r e s o u r c e s>
dp</ dimen>

Path = Tess2Speech/tess2Speech/src/main/res/values/strings.xml

<r e s o u r c e s> Change T e s s e r a c t \ ’ s t r a i n e d d a t a . You can


combine two o r more t r a i n e d d a t a . Make
< !−−App Name−−> s u r e t o a l s o c h a n g e Text−to−S p e e c h
< s t r i n g name=” app name ”>T e s s 2 S p e e c h</ s t r i n g> l a n g u a g e and S p e l l −C h e c k e r i f o t h e r
l a n g u a g e s o t h e r than E n g l i s h i s s e l e c t e d
< !−−A c t i o n Bar Menu −−> . </ s t r i n g >
< s t r i n g name=” camera ”>Use Camera f o r i n p u t</ < s t r i n g name=” t i t l e i n t e n t t t s ”>TTS
s t r i n g> S e t t i n g s </ s t r i n g >
< s t r i n g name=” b r o w s e ”>Browse i n p u t i m a g e < < s t r i n g name=” p r e f s e t t i n g s c a t e g o r y ”>
/ s t r i n g> S e t t i n g s </ s t r i n g >
< s t r i n g name=” b r o w s e P d f ”>Browse i n p u t P D F < s t r i n g name=” s u m m a r y i n t e n t t t s ”>Text−to−
</ s t r i n g> S p e e c h S e t t i n g s </ s t r i n g >
< s t r i n g name=” browseEpub ”>Browse i n p u t < s t r i n g name=” t i t l e i n t e n t s p e l l c h e c k ”>
E p u b </ s t r i n g> S p e l l c h e c k e r </ s t r i n g >
< s t r i n g name=” s a v e t e x t ”>Save a s . t x t</ < s t r i n g name=” s u m m a r y i n t e n t s p e l l c h e c k
s t r i n g> ” > <![CDATA[ Launch Language & I n p u t
< s t r i n g name=” s a v e p d f ”>Save a s . p d f</ s t r i n g s e t t i n g s . Turning S p e l l c h e c k e r on
> can h e l p you r e c o g n i z e q u e s t i o n a b l e
< s t r i n g name=” s a v e a u d i o ”>Save Audio</ s t r i n g words and s u g g e s t c o r r e c t words .]] > </
> string >
< s t r i n g name=” i m a g e t o p d f ”>C o n v e r t image t o < s t r i n g name=” p r e f a b o u t c a t e g o r y ”>About</
s e a r c h a b l e PDF</ s t r i n g> string >
< s t r i n g name=” p d f t o i m a g e ”>C o n v e r t Pdf t o < s t r i n g name=” t i t l e h e l p ”>Help </ s t r i n g >
Image</ s t r i n g> < s t r i n g name=” t i t l e l i c e n s e ”> L i c e n s e </
< s t r i n g name=” s e t t i n g s ”>S e t t i n g s</ s t r i n g> string >
< s t r i n g name=” e x i t ”>E x i t</ s t r i n g> < s t r i n g name=” t i t l e v e r s i o n ”>V e r s i o n </
string >
< !−−App UI s t r i n g s−−> < s t r i n g name=”s u m m a r y v e r s i o n”>v1 . 0 0 ( Beta )
< !−−c o n t e n t m a i n . xml−−> </ s t r i n g >
< s t r i n g name=” b u t t o n p l a y ”>P l a y</ s t r i n g>
< s t r i n g name=” b u t t o n s t o p ”>Stop</ s t r i n g> <!−− L i c e n s e s −−>
< s t r i n g name=” b u t t o n t e x t ”>C o n v e r t Text \ < s t r i n g name=” t e s s t w o l i c e n s e ”>
u0020</ s t r i n g> by R o b e r t T h e i s \n<a h r e f =” h t t p s : //
< s t r i n g name=” b u t t o n t e x t b a c k ”>Back t o g i t h u b . com/ r m t h e i s / t e s s −two”>
I n p u t</ s t r i n g> h t t p s : // g i t h u b . com/ r m t h e i s / t e s s −
< !−− a c t i v i t y r o t a t e . xml−−> two</a>\n\ n C o p y r i g h t 2011 R o b e r t
< s t r i n g name=” i m a g e V i e w r o t a t e c o n t e n t d e s c ” T h e i s \ n L i c e n s e d u n d e r t h e Apache
>I n p u t image</ s t r i n g> License , Version 2.0
< !−−f r a g m e n t c a n v a s . xml−−> </ s t r i n g >
< s t r i n g name=” b u t t o n s t r o k e ”>E r a s e</ s t r i n g> < s t r i n g name=” g e s t u r e i m a g e v i e w l i c e n s e ”>
< s t r i n g name=” b u t t o n s t r o k e s t r o k e ”>S t r o k e</ by j a s o n p o l i t e s \n<a h r e f =” h t t p s : //
s t r i n g> g i t h u b . com/ j a s o n p o l i t e s / g e s t u r e −
< s t r i n g name=” b u t t o n c l e a r ”>C l e a r</ s t r i n g> i m a g e v i e w”> h t t p s : // g i t h u b . com/
< !−−f r a g m e n t c o n v e r t e d t e x t . xml−−> j a s o n p o l i t e s / g e s t u r e −imageview </a
< s t r i n g name=” s w i t c h a p p e n d ”>Append T e x t :</ >\n\ n L i c e n s e d u n d e r t h e Apache
s t r i n g> License , Version 2.0
< s t r i n g name=” p l a c e h o l d e r ”>I n p u t t e x t h e r e</ </ s t r i n g >
s t r i n g> < s t r i n g name=” a n d r o i d p d f v i e w l i c e n s e ”>
< !−−f r a g m e n t i n p u t i m a g e . xml e t c .−−> by Joan Zapata \n<a h r e f =” h t t p s : //
< s t r i n g name=” b u t t o n b a c k ”>Canvas</ s t r i n g> g i t h u b . com/ JoanZapata / a n d r o i d −
< s t r i n g name=” b u t t o n r o t a t e ”>R o t a t e</ s t r i n g> p d f v i e w”> h t t p s : // g i t h u b . com/
< s t r i n g name=” b u t t o n c r o p ”>Crop</ s t r i n g> JoanZapata / a n d r o i d −p d f v i e w </a>\n\
< !−−f r a g m e n t p d f v i e w e r . xml−−> n C o p y r i g h t 2013 −2015 Joan Zapata \
< s t r i n g name=” b u t t o n p d f b a c k ”>Canvas</ n L i c e n s e d u n d e r GNU G e n e r a l
s t r i n g> P u b l i c L i c e n s e v3 ( c o m p a t i b l e
< !−− s p l a s h s c r e e n . xml−−> w i t h Apache L i c e n s e , V e r s i o n 2 . 0 )
< s t r i n g name=” i m a g e V i e w s p l a s h d e s c ”>S p l a s h< \ n L i c e n s e a v a i l a b l e a t : <a h r e f =” h t t p :
/ s t r i n g> //www. gnu . o r g / l i c e n s e s ”> h t t p : //
< s t r i n g name=” t e x t V i e w s p l a s h ”>Copying f i l e s www. gnu . o r g / l i c e n s e s </a>
p l e a s e wait </ s t r i n g> </ s t r i n g >
< !−−f r a g m e n t e p u b . xml−−> < s t r i n g name=” c r o p p e r l i c e n s e ”>
< s t r i n g name=” b u t t o n e p u b b a c k ”>T a b l e o f by ArthurHub f o r k e d from <a h r e f =”
C o n t e n t s</ s t r i n g> h t t p s : // g i t h u b . com/ edmodo / c r o p p e r
”> h t t p s : // g i t h u b . com/ edmodo /
c r o p p e r </a> \n\n<a h r e f =” h t t p s : //
g i t h u b . com/ ArthurHub / Android−
< !−−P r e f e r e n c e s Menu−−> Image−Cropper”> h t t p s : // g i t h u b . com
< s t r i n g name=” t i t l e i m a g e p r e p r o c e s s ”>Image / ArthurHub / Android−Image−Cropper
Pre−p r o c e s s i n g</ s t r i n g> </a>\n\ n C o p y r i g h t 2013 Edmodo ,
< s t r i n g name=” s u m m a r y i m a g e p r e p r o c e s s ”>< ! [ I n c . \ n L i c e n s e d u n d e r t h e Apache
CDATA[ P e r f o r m G r a y s c a l e and f i x e s p o o r License , Version 2.0
i l l u m i n a t e d images b e f o r e c o n v e r t i n g to </ s t r i n g >
t e x t . May i m p r o v e a c c u r a c y but s l o w s < s t r i n g name=” e p u b l i c e n s e ”>
c o n v e r s i o n t i m e . ] ] ></ s t r i n g> by Paul Siegman from <a h r e f =” h t t p s : //
< s t r i n g name=” t i t l e a c c e l e r a t e ”>Re−s c a l e g i t h u b . com/ p s i eg m a n / e p u b l i b ”>
Image</ s t r i n g> h t t p s : // g i t h u b . com/ p si e g ma n /
< s t r i n g name=” s u m m a r y a c c e l e r a t e ”>S p e e d s up e p u b l i b </a>
c o n v e r s i o n s p e e d by r e d u c i n g image s i z e . </ s t r i n g >
Turn t h i s on i f t h e image h a s l a r g e t e x t s < s t r i n g name=” s l 4 j l i c e n s e ”>
. Turn t h i s o f f f o r i m a g e s w i t h s m a l l Copyright 2004 −2013 QOS . ch \n
t e x t s s u c h a s documents e t c .</ s t r i n g> All rights reserved .
< s t r i n g name=” t i t l e c h a n g e l a n g u a g e ”> \n\ n P e r m i s s i o n i s h e r e b y g r a n t e d , f r e e
T e s s e r a c t T r a i n e d Data</ s t r i n g> o f c h a r g e , t o any p e r s o n
< s t r i n g name=” s u m m a r y c h a n g e l a n g u a g e ”> obtaining

154
a copy of this software and
associated documentation f i l e s <!−−Help−−>
( the < s t r i n g name=” t e x t V i e w h e l p t i t l e ”>U s e r
” Software ”) , to deal in the Software Manual</ s t r i n g >
without restriction , including < s t r i n g name=” t e x t V i e w h e l p t i p s ”>Tips </
without l i m i t a t i o n the r i g h t s to use string >
, copy , modify , merge , p u b l i s h , < s t r i n g name=” t i p s d e s c r i p t i o n ” >1. I f t h e
distribute , s u b l i c e n s e , and / o r s e l l image d i m e n s i o n i s l a r g e and o n l y
copies of the Software , and t o contains l a r g e texts , i t i s b e t t e r to
p e r m i t p e r s o n s t o whom t h e S o f t w a r e t u r n on \”Re−s c a l e Image \” t o a v o i d
i s f u r n i s h e d t o do so , s u b j e c t t o reading garbage t e x t s .
the f o l l o w i n g c o n d i t i o n s : \n\ n2 . I f t h e image c o n t a i n s s m a l l
t e x t s ( s u c h a s PDFs , d o c s , e t c . ) ,
\n\nThe above copyright notice t u r n o f f \”Re−s c a l e image \” t o
and this permission notice i n c r e a s e accuracy .
shall be \n\ n3 . I f t h e image c o n t a i n s non−b l a c k
included in a l l c o p i e s or s u b s t a n t i a l c h a r a c t e r s and non−w h i t e
p o r t i o n s of the Software . background , i t i s b e t t e r t o t u r n
on \” Image Pre−p r o c e s s i n g \ ” .
\n\nTHE SOFTWARE I S PROVIDED ”AS \n\ n4 . I n s e t t i n g s > T e s s e r a c t
I S ” , WITHOUT WARRANTY OF ANY Language:
KIND , \n\ t eng . t r a i n e d d a t a − c h e c k t h i s f o r
EXPRESS OR IMPLIED , INCLUDING BUT printed texts .
NOT LIMITED TO THE WARRANTIES \n\ t engh . t r a i n e d d a t a − c h e c k t h i s f o r
OF handwritten t e x t s .
MERCHANTABILITY, FITNESS FOR \n∗You can c h e c k both t o r e a d both
A PARTICULAR PURPOSE h a n d w r i t t e n and p r i n t e d t e x t s ,
AND but t h i s may a f f e c t e a c h o t h e r s
NONINFRINGEMENT. IN NO EVENT SHALL accuracy .
THE AUTHORS OR COPYRIGHT HOLDERS \n\ n5 . I f you want t o add a n o t h e r .
BE t r a i n e d d a t a , Copy t h e d e s i r e d .
LIABLE FOR ANY CLAIM, DAMAGES OR traineddata f i l e to Storage /
OTHER LIABILITY , WHETHER IN AN Android / d a t a / a n t e r a a r o n .
ACTION tess2speech / f i l e s / tessdata
OF CONTRACT, TORT OR OTHERWISE, </ s t r i n g >
ARISING FROM, OUT OF OR IN < s t r i n g name=” t e x t V i e w h e l p c a m e r a ”>Camera
CONNECTION </ s t r i n g >
WITH THE SOFTWARE OR THE USE OR OTHER < s t r i n g name=” c a m e r a d e s c r i p t i o n ”>Use t h e
DEALINGS IN THE SOFTWARE. <a phone \ ’ s camera t o g e t an i n p u t image
h r e f =” h t t p : //www. s l f 4 j . o r g / which w i l l be c o n v e r t e d t o t e x t .</
l i c e n s e . html”> h t t p : //www. s l f 4 j . s t r i n g>
o r g / l i c e n s e . html </a> < s t r i n g name=” t e x t V i e w h e l p b r o w s e i m a g e ”>
</ s t r i n g > Browse Image</ s t r i n g>
< s t r i n g name=” f i l e p i c k e r l i c e n s e ”> < s t r i n g name=” b r o w s e i m a g e d e s c r i p t i o n ”>Get
by Anders K a l r \n<a h r e f =” h t t p s : // an i n p u t image from t h e phone \ ’ s s t o r a g e
g i t h u b . com/ A n d e r s K a l o e r / Android− which w i l l be c o n v e r t e d t o t e x t . </ s t r i n g >
F i l e −P i c k e r −A c t i v i t y ”> h t t p s : // < s t r i n g name=” t e x t V i e w h e l p p l a y ”>Play </
g i t h u b . com/ A n d e r s K a l o e r / Android− string >
F i l e −P i c k e r −A c t i v i t y </a>\n\ < s t r i n g name=” p l a y d e s c r i p t i o n ”>C o n v e r t s
n C o p y r i g h t 2011 Anders K a l r \ t h e image d i s p l a y e d / w r i t t e n words
n L i c e n s e d u n d e r t h e Apache from c a n v a s t o t e x t and t h e n c o n v e r t s
License , Version 2.0 i t t o s p e e c h . </ s t r i n g >
</ s t r i n g > < s t r i n g name=” t e x t V i e w h e l p s t o p ”>Stop </
< s t r i n g name=” i c o n s l i c e n s e ”> string >
A n d r o i d i c o n s i s a p r o d u c t by Opoloo . < s t r i n g name=” s t o p d e s c r i p t i o n ”>S t o p s t h e
You can f o l l o w t h e i r T w i t t e r f e e d Text−to−S p e e c h p l a y b a c k . </ s t r i n g >
a t @opoloo , t h e i r G+ s i t e a t < s t r i n g name=” t e x t V i e w h e l p c l e a r ”>C l e a r </
g o o g l e . com/+Opoloo , o r c o n t a c t string >
them v i a m a i l a t i n f o @ o p o l o o . com < s t r i n g name=” c l e a r d e s c r i p t i o n ”> D e l e t e s
c o n c e r n i n g any q u e s t i o n s o r a l l w r i t i n g s i n t h e w r i t i n g c a n v a s . </
s u g g e s t i o n s . −Guenther Beyer \n<a string >
h r e f =” h t t p : //www. a n d r o i d i c o n s . com < s t r i n g name=” t e x t V i e w h e l p e r a s e ”>E r a s e </
/”> h t t p : //www. a n d r o i d i c o n s . com/</ string >
a> < s t r i n g name=” e r a s e d e s c r i p t i o n ”> E r a s e s a
\n\ n L i c e n s e d u n d e r C r e a t i v e Commons s t r o k e in the w r i t i n g canvas i n s t e a d
A t t r i b u t i o n −S h a r e A l i k e 4 . 0 o f w r i t i n g . </ s t r i n g >
I n t e r n a t i o n a l P u b l i c L i c e n s e <a < s t r i n g name=” t e x t V i e w h e l p s t r o k e ”>S t r o k e
h r e f =” h t t p : // c r e a t i v e c o m m o n s . o r g / </ s t r i n g >
l i c e n s e s /by−s a /4.0/” > h t t p : // < s t r i n g name=” s t r o k e d e s c r i p t i o n ”>W r i t e s a
c r e a t i v e c o m m o n s . o r g / l i c e n s e s /by− s t r o k e t o t h e w r i t i n g c a n v a s . </
s a /4.0/ </ a >. string >
</ s t r i n g > < s t r i n g name=” t e x t V i e w h e l p c o n v e r t t e x t ”>
< s t r i n g name=” t e s s 2 S p e e c h l i c e n s e ”> C o n v e r t Text</ s t r i n g >
by Anter Aaron C u s t o d i o \n\ n C o p y r i g h t < s t r i n g name=” c o n v e r t t e x t d e s c r i p t i o n ”>
2016 Anter Aaron C u s t o d i o \ C o n v e r t s t h e image d i s p l a y e d / w r i t t e n
n L i c e n s e d u n d e r t h e Apache words from c a n v a s t o t e x t and d i s p l a y
License , Version 2.0 ( the ” t h e e d i t a b l e t e x t . </ s t r i n g >
License ”) ; < s t r i n g name=” t e x t V i e w h e l p b a c k ”>Back t o
you may n o t u s e t h i s f i l e e x c e p t i n I n p u t </ s t r i n g >
c o m p l i a n c e w i t h t h e L i c e n s e . You < s t r i n g name=” b a c k d e s c r i p t i o n ”>Go back t o
may o b t a i n a copy o f t h e L i c e n s e t h e i n p u t image / w r i t i n g c a n v a s . </
at string >
\n<a h r e f =” h t t p : //www. a p a c h e . o r g / < s t r i n g name=” t e x t V i e w h e l p r o t a t e ”>Rotate
l i c e n s e s /LICENSE−2.0”> h t t p : //www. </ s t r i n g >
a p a c h e . o r g / l i c e n s e s /LICENSE−2.0</ < s t r i n g name=” r o t a t e d e s c r i p t i o n ”> R o t a t e s
a> t h e image d i s p l a y e d . </ s t r i n g >
\ n U n l e s s r e q u i r e d by a p p l i c a b l e law o r < s t r i n g name=” t e x t V i e w h e l p c r o p ”>Crop</
agreed to in writing , software string >
d i s t r i b u t e d under the L i c e n s e i s < s t r i n g name=” c r o p d e s c r i p t i o n ”>Crops t h e
d i s t r i b u t e d on an ”AS I S ” BASIS , image d i s p l a y e d . </ s t r i n g >
WITHOUT WARRANTIES OR CONDITIONS OF < s t r i n g name=” t e x t V i e w h e l p a p p e n d ”>Append
ANY KIND , e i t h e r e x p r e s s o r Text</ s t r i n g >
implied . < s t r i n g name=” a p p e n d d e s c r i p t i o n ”>Does n o t
See the L i c e n s e f o r the s p e c i f i c c l e a r the p r e v i o u s l y converted text .
language governing permissions The n e x t c o n v e r t e d t e x t w i l l be
and appended t o t h e p r e v i o u s l y c o n v e r t e d
l i m i t a t i o n s under the L i c e n s e . t e x t . ( Does n o t work w i t h Epubs
</ s t r i n g > b e c a u s e Epub t e x t s a r e t o o l o n g ) . </
string >

155
< s t r i n g name=” t e x t V i e w h e l p b r o w s e p d f ”> < s t r i n g name=” t e x t V i e w h e l p t o P d f ”>C o n v e r t
Browse i n p u t PDF</ s t r i n g > image / s t o s e a r c h a b l e PDF. </ s t r i n g >
< s t r i n g name=” b r o w s e p d f d e s c r i p t i o n ”>Gets < s t r i n g name=” t o P d f d e s c r i p t i o n ”>C o n v e r t s
a PDF from t h e phone \ ’ s s t o r a g e a s an image t o PDF which h a s s e a r c h a b l e
i n p u t . Note t h a t c o n v e r t i n g a PDF t o and s e l e c t a b l e t e x t s . The f o n t s i z e
t e x t o r s p e e c h prompts you t o s e l e c t and s t y l e i n t h e PDF w i l l be t h e same
which p a g e s t o c o n v e r t .</ s t r i n g> a s t h e r e c o g n i z e d f o n t i n t h e image .
< s t r i n g name=” t e x t V i e w h e l p b r o w s e e p u b ”> ( Note t h a t m u l t i p l e image s e l e c t i s
Browse i n p u t Epub</ s t r i n g> o n l y a v a i l a b l e f o r API 18 (JELLY BEAN
< s t r i n g name=” b r o w s e e p u b d e s c r i p t i o n ”>Gets MR2) and up . M u l t i p l e image s e l e c t
a Epub from t h e phone \ ’ s s t o r a g e a s i n p u t i s a l s o n o t a v a i l a b l e f o r t h i s app \ ’ s
. </ s t r i n g > b u i l t i n f i l e b r o w s e r . )</ s t r i n g>
< s t r i n g name=” t e x t V i e w h e l p t o c ”>T a b l e o f < s t r i n g name=” t e x t V i e w h e l p t o I m a g e ”>C o n v e r t
C o n t e n t s </ s t r i n g > PDF t o image</ s t r i n g>
< s t r i n g name=” t o c d e s c r i p t i o n ”>Go back t o < s t r i n g name=” t o I m a g e d e s c r i p t i o n ”>C o n v e r t s
t h e o v e r v i e w o f t h e book \ ’ s c h a p t e r s . t h e s e l e c t e d p a g e s o f t h e PDF t o i m a g e s
</ s t r i n g> and s a v e i t t o a s p e c i f i c f o l d e r .</ s t r i n g
< s t r i n g name=” t e x t V i e w h e l p s a v e ”>Save a s . >
t x t / . p d f / a u d i o</ s t r i n g> < s t r i n g name=” t e x t V i e w h e l p d i r e c t o r i e s ”>
< s t r i n g name=” s a v e d e s c r i p t i o n ”>S a v e s t h e F i l e D i r e c t o r i e s</ s t r i n g>
c o n v e r t e d t e x t a s a t e x t f i l e /PDF f i l e . </ r e s o u r c e s>
Save Audio s a v e s t h e c o n v e r t e d t e x t \ ’ s
s p e e c h e q u i v a l e n t a s a WAV f i l e . </ s t r i n g >

Path = Tess2Speech/tess2Speech/src/main/res/values/styles.xml

<r e s o u r c e s>
< s t y l e name=”AppTheme . NoActionBar ”>
< !−− Base a p p l i c a t i o n theme . −−> <i t e m name=” windowActionBar ”> f a l s e</ i t e m>
< s t y l e name=”AppTheme” p a r e n t=”Theme . <i t e m name=” windowNoTitle ”>t r u e</ i t e m>
AppCompat . L i g h t . DarkActionBar ”> </ s t y l e>
< !−− C u s t o m i z e y o u r theme h e r e . −−>
<i t e m name=” c o l o r P r i m a r y ”>@ c o l o r / < s t y l e name=”AppTheme . AppBarOverlay ” p a r e n t=
c o l o r P r i m a r y</ i t e m> ” ThemeOverlay . AppCompat . Dark . A c t i o n B a r ” /
<i t e m name=” c o l o r P r i m a r y D a r k ”>@ c o l o r / >
c o l o r P r i m a r y D a r k</ i t e m>
<i t e m name=” c o l o r A c c e n t ”>@ c o l o r / < s t y l e name=”AppTheme . PopupOverlay ” p a r e n t=”
c o l o r A c c e n t</ i t e m> ThemeOverlay . AppCompat . L i g h t ” />
<i t e m name=” windowActionModeOverlay ”>t r u e<
/ i t e m> </ r e s o u r c e s>
</ s t y l e>

Path = Tess2Speech/tess2Speech/src/main/res/values-v21/styles.xml

<r e s o u r c e s> t r u e</ i t e m>


<i t e m name=” a n d r o i d : s t a t u s B a r C o l o r ”>
< s t y l e name=”AppTheme . NoActionBar ”> @ a n d r o i d : c o l o r / t r a n s p a r e n t</ i t e m>
<i t e m name=” windowActionBar ”> f a l s e</ i t e m> </ s t y l e>
<i t e m name=” windowNoTitle ”>t r u e</ i t e m> </ r e s o u r c e s>
<i t e m name=”
a n d r o i d : w i n d o w D r a w s S y s t e m B a r B a c k g r o u n d s ”>

Path = Tess2Speech/tess2Speech/src/main/res/values-w820dp/dimens.xml

<r e s o u r c e s> l a n d s c a p e ( ˜ 9 6 0 dp and ˜ 1 2 8 0 dp


< !−− Example c u s t o m i z a t i o n o f d i m e n s i o n s r e s p e c t i v e l y ) . −−>
o r i g i n a l l y d e f i n e d i n r e s / v a l u e s / dimens . <dimen name=” a c t i v i t y h o r i z o n t a l m a r g i n ”>64
xml dp</ dimen>
( such as s c r e e n margins ) f o r s c r e e n s with </ r e s o u r c e s>
more than 820 dp o f a v a i l a b l e w i d t h . T h i s
would i n c l u d e 7 ” and 10 ” d e v i c e s i n

Path = Tess2Speech/tess2Speech/src/main/res/xml/preferences.xml

<? xml v e r s i o n=” 1 . 0 ” e n c o d i n g=” u t f −8” ?> a n d r o i d : s u m m a r y=” @ s t r i n g /


<P r e f e r e n c e S c r e e n x m l n s : a n d r o i d=” h t t p : // summary image preprocess ”
schemas . a n d r o i d . com/ apk / r e s / a n d r o i d ”> a n d r o i d : d e f a u l t V a l u e=” t r u e ”>
<P r e f e r e n c e C a t e g o r y a n d r o i d : t i t l e =” @ s t r i n g / </ C h e c k B o x P r e f e r e n c e>
p r e f s e t t i n g s c a t e g o r y ”> <C h e c k B o x P r e f e r e n c e
<C h e c k B o x P r e f e r e n c e a n d r o i d : k e y=” p r e f k e y a c c e l e r a t e ”
a n d r o i d : k e y=” p r e f k e y i m a g e p r e p r o c e s s ” a n d r o i d : t i t l e =” @ s t r i n g / t i t l e a c c e l e r a t e ”
a n d r o i d : t i t l e =” @ s t r i n g / a n d r o i d : s u m m a r y=” @ s t r i n g /
title image preprocess ” summary accelerate ”

156
a n d r o i d : d e f a u l t V a l u e=” f a l s e ”> settings ”
</ C h e c k B o x P r e f e r e n c e> a n d r o i d : t a r g e t C l a s s=”com . a n d r o i d .
<P r e f e r e n c e S c r e e n s e t t i n g s . L a n g u a g e S e t t i n g s ” />
a n d r o i d : k e y=” p r e f k e y c h a n g e l a n g u a g e ” </ P r e f e r e n c e S c r e e n>
a n d r o i d : t i t l e =” @ s t r i n g / </ P r e f e r e n c e C a t e g o r y>
title change language ”
a n d r o i d : s u m m a r y=” @ s t r i n g / <P r e f e r e n c e C a t e g o r y a n d r o i d : t i t l e =” @ s t r i n g /
s u m m a r y c h a n g e l a n g u a g e ”> p r e f a b o u t c a t e g o r y ”>
</ P r e f e r e n c e S c r e e n> <P r e f e r e n c e S c r e e n
<P r e f e r e n c e S c r e e n a n d r o i d : k e y=” p r e f k e y h e l p ”
a n d r o i d : t i t l e =” @ s t r i n g / t i t l e i n t e n t t t s ” a n d r o i d : t i t l e =” @ s t r i n g / t i t l e h e l p ”
a n d r o i d : s u m m a r y=” @ s t r i n g / a n d r o i d : s u m m a r y=” ”>
s u m m a r y i n t e n t t t s ”> </ P r e f e r e n c e S c r e e n>
<i n t e n t a n d r o i d : a c t i o n=”com . a n d r o i d . <P r e f e r e n c e S c r e e n
s e t t i n g s . TTS SETTINGS” /> a n d r o i d : k e y=” p r e f k e y l i c e n s e ”
</ P r e f e r e n c e S c r e e n> a n d r o i d : t i t l e =” @ s t r i n g / t i t l e l i c e n s e ”
<P r e f e r e n c e S c r e e n a n d r o i d : s u m m a r y=” ”>
a n d r o i d : k e y=” p r e f k e y s p e l l c h e c k ” </ P r e f e r e n c e S c r e e n>
a n d r o i d : t i t l e =” @ s t r i n g / <P r e f e r e n c e S c r e e n
title intent spell check” a n d r o i d : t i t l e =” @ s t r i n g / t i t l e v e r s i o n ”
a n d r o i d : s u m m a r y=” @ s t r i n g / a n d r o i d : s u m m a r y=” @ s t r i n g / s u m m a r y v e r s i o n
summary intent spell check ” ”>
a n d r o i d : e n a b l e d=” t r u e ”> </ P r e f e r e n c e S c r e e n>
</ P r e f e r e n c e C a t e g o r y>
<i n t e n t a n d r o i d : a c t i o n=” a n d r o i d . i n t e n t .
a c t i o n . MAIN” </ P r e f e r e n c e S c r e e n>
a n d r o i d : t a r g e t P a c k a g e=”com . a n d r o i d .

157
B..2 Tess2Speech Trainer

Tessdata folder, edited jTessBoxEditor folder, training tools folder should be all
in the same directory.
Base Path = Tess2SpeechTrainer/
Path = Tess2SpeechTrainer/src/anteraaron/tess2speech/Driver.java

package anteraaron . t e s s 2 s p e e c h ; new Frame ( ) ;


} catch ( ClassNotFoundException e ) {
import javax . swing . S w i n g U t i l i t i e s ; // TODO Auto−g e n e r a t e d c a t c h b l o c k
import javax . swing . e . printStackTrace () ;
UnsupportedLookAndFeelException ; } catch ( InstantiationException e ) {
/∗ ∗ // TODO Auto−g e n e r a t e d c a t c h b l o c k
∗ D r i v e r f o r the whole Tess2Speech T r a i n e r e . printStackTrace () ;
∗ @author Anter Aaron M. C u s t o d i o } catch ( Illegal AccessExc eption e ) {
∗ @since 2016/5/2 // TODO Auto−g e n e r a t e d c a t c h b l o c k
∗/ e . printStackTrace () ;
public c l a s s Driver { } catch (
UnsupportedLookAndFeelException e
/∗ ∗ ) {
∗ Main method // TODO Auto−g e n e r a t e d c a t c h b l o c k
∗ @param a r g s S t r i n g a r g u m e n t s f o r main e . printStackTrace () ;
∗/ } // I n s t a n t i a t e t h e f r a m e
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { }
// Launch t h e GUI f r a m e }) ;
S w i n g U t i l i t i e s . i n v o k e L a t e r ( new Runnable ( ) }
{
@O verr ide }
p u b l i c v o i d run ( ) {
try {

Path = Tess2SpeechTrainer/src/anteraaron/tess2speech/Frame.java

package anteraaron . t e s s 2 s p e e c h ; , InstantiationException ,


IllegalAccessException ,
i m p o r t j a v a . awt . Dimension ; UnsupportedLookAndFeelException {
UIManager . s e t L o o k A n d F e e l (
import javax . swing . ImageIcon ; ”com . sun . j a v a . s w i n g . p l a f . windows .
i m p o r t j a v a x . s w i n g . JFrame ; WindowsLookAndFeel ” ) ;
i m p o r t j a v a x . s w i n g . UIManager ; t h i s . f r a m e = new JFrame ( ” T e s s 2 S p e e c h
import javax . swing . Trainer ” ) ;
UnsupportedLookAndFeelException ; t h i s . f r a m e . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame
. EXIT ON CLOSE ) ;
/∗ ∗ t h i s . f r a m e . s e t S i z e ( new Dimension ( 4 0 0 , 4 4 0 ) )
∗ The Frame o f t h e T e s s 2 S p e e c h GUI ;
∗ @author Anter Aaron M. C u s t o d i o t h i s . frame . s e t R e s i z a b l e ( f a l s e ) ;
∗ @since 2016/5/2 t h i s . frame . s e t L o c a t i o n R e l a t i v e T o ( n u l l ) ;
∗/ t h i s . frame . s e t V i s i b l e ( t r u e ) ;
p u b l i c c l a s s Frame { t h i s . f r a m e . s e t I c o n I m a g e ( new I m a g e I c o n (
f i n a l p r i v a t e JFrame f r a m e ; g e t C l a s s ( ) . getResource ( ”/ images / l o g o .
/∗ ∗ png ” ) ) . g e t I m a g e ( ) ) ;
∗ Constructor
∗ @throws U n s u p p o r t e d L o o k A n d F e e l E x c e p t i o n t h i s . f r a m e . s e t C o n t e n t P a n e ( new MainPanel ( ) )
∗ @throws I l l e g a l A c c e s s E x c e p t i o n ;
∗ @throws I n s t a n t i a t i o n E x c e p t i o n }
∗ @throws C l a s s N o t F o u n d E x c e p t i o n }
∗/
p u b l i c Frame ( ) t h r o w s C l a s s N o t F o u n d E x c e p t i o n

Path = Tess2SpeechTrainer/src/anteraaron/tess2speech/Functions.java

package anteraaron . t e s s 2 s p e e c h ;
i m p o r t j a v a x . s w i n g . JOptionPane ;
import java . awt . H e a d l e s s E x c e p t i o n ;
import java . io . BufferedWriter ; /∗ ∗
import java . io . File ; ∗ A Class that contains a l l of the
import java . io . FileWriter ; f u n c t i o n a l i t i e s o f Tess2Speech trainer
import java . io . FilenameFilter ; ∗ @author Anter Aaron M. C u s t o d i o
import java . i o . IOException ; ∗ @since 2016/5/3
import java . nio . f i l e . F i l e s ; ∗/
import java . n i o . f i l e . StandardCopyOption ; public c l a s s Functions {
import java . u t i l . ArrayList ;
import java . u t i l . Arrays ; private static final S t r i n g OUTPUT DIR = ”

158
output ” ; // Check i f image f i l e i s a l r e a d y
p r i v a t e s t a t i c f i n a l S t r i n g TESSDATA DIR = ” e x i s t i n g i n f o l d e r , prompt u s e r
tessdata ” ; to whether to o v e r w r i t e
private static f i n a l String i f ( destinationFile . exists () ) {
TRAINING TOOLS DIR = ” t r a i n i n g t o o l s ” ; f i n a l i n t c h o i c e = JOptionPane .
p r i v a t e s t a t i c f i n a l S t r i n g TESSERACT CMD = s h o w O p t i o n D i a l o g ( n u l l , ”The
” training tools ” + File . separator + ” image ’ ” + f i l e N a m e + ” ’
t e s s e r a c t −−t e s s d a t a −d i r ” + ” . \ \ ” ; already e x i s t s . Overwrite ?” , ”
private static f i n a l String Warning ” , JOptionPane .
UNICHARSET EXTRACTOR CMD = ” OK CANCEL OPTION, JOptionPane .
training tools ” + File . separator + ” WARNING MESSAGE, n u l l , n u l l ,
unicharset extractor ” ; null ) ;
p r i v a t e s t a t i c f i n a l S t r i n g MFTRAINING CMD = i f ( c h o i c e == JOptionPane . OK OPTION)
” training tools ” + File . separator + ” {
mftraining ” ; F i l e s . copy ( s o u r c e F i l e . t o P a t h ( ) ,
private static f i n a l String d e s t i n a t i o n F i l e . toPath ( ) ,
SET UNICHARSET PROPERTIES CMD = ” StandardCopyOption .
training tools ” + File . separator + ” REPLACE EXISTING) ;
set unicharset properties ”; }
p r i v a t e s t a t i c f i n a l S t r i n g CNTRAINING CMD = } else {
” training tools ” + File . separator + ” F i l e s . copy ( s o u r c e F i l e . t o P a t h ( ) ,
cntraining ” ; d e s t i n a t i o n F i l e . toPath ( ) ,
private static f i n a l String StandardCopyOption .
WORDLIST2DAWG CMD = ” t r a i n i n g t o o l s ” + REPLACE EXISTING) ;
F i l e . separator + ” wordlist2dawg ” ; }
private static f i n a l String
COMBINE TESSDATA CMD = ” t r a i n i n g t o o l s ” } catch ( IOException e ) {
+ File . separator + ” combine tessdata ” JOptionPane . s h o w M e s s a g e D i a l o g ( n u l l , ”
; Source F i l e ’ ” + sourcePath + ” ’
private static f i n a l String n o t Found ! ” , ” F a i l u r e ” ,
JTESSBOXEDITOR DIR = ” j T e s s B o x E d i t o r ” ; JOptionPane . ERROR MESSAGE) ;
/∗ ∗ e . printStackTrace () ;
∗ Start Tesseract Training }
∗/ }
public s t a t i c void st ar tT ra i ni n g () {
// Remove empty f i l e p a t h s // Get l i s t o f f i l e w i t h o u t e x t e n s i o n
f i n a l S t r i n g t e s s e r a c t L a n g u a g e = MainPanel f i n a l F i l e [ ] f i l e s = new F i l e (OUTPUT DIR +
. language combobox . g e t S e l e c t e d I t e m ( ) . F i l e . s e p a r a t o r + languageName ) .
toString () ; l i s t F i l e s ( new F i l e n a m e F i l t e r ( ) {
f i n a l S t r i n g languageName = MainPanel .
f o n t t e x t f i e l d . getText ( ) ; @O verr ide
f i n a l S t r i n g [ ] p a t h s = MainPanel . public boolean accept ( F i l e dir , String
t i f f t e x t f i e l d . getText ( ) . s p l i t ( ” ; ” ) ; name ) {
f i n a l A r r a y L i s t <S t r i n g > l i s t = new r e t u r n name . toLowerCase ( ) . endsWith ( ” .
A r r a y L i s t <S t r i n g >( A r r a y s . a s L i s t ( p a t h s t i f ”) ;
)); }
l i s t . removeAll ( Arrays . a s L i s t ( ”” , n u l l ) ) ; }) ;

S t r i n g [ ] f i l e N a m e s = new S t r i n g [ f i l e s .
// C r e a t e l a n g u a g e d i r length ] ;
f i n a l F i l e d i r e c t o r y = new F i l e (OUTPUT DIR
+ F i l e . s e p a r a t o r + languageName ) ; // f o r m a t o u t p u t \ l a n g \ f o n t
f o r ( i n t i = 0 ; i < f i l e s . l e n g t h ; i ++) {
if ( directory . exists () ) { f i l e N a m e s [ i ] = OUTPUT DIR + F i l e .
f i n a l i n t c h o i c e = JOptionPane . s e p a r a t o r + languageName + F i l e .
s h o w O p t i o n D i a l o g ( n u l l , ”The s e p a r a t o r + f i l e s [ i ] . getName ( ) .
Language ’ ” + languageName + ” ’ s u b s t r i n g ( 0 , f i l e s [ i ] . getName ( ) .
already e x i s t s . Previous t r a i n i n g lastIndexOf ( ’ . ’ ) ) ;
i m a g e s w i l l be u s e d a g a i n . C o n t i n u e }
Anyway? ” , ” Warning ” , JOptionPane .
OK CANCEL OPTION, JOptionPane .
WARNING MESSAGE, n u l l , n u l l , n u l l ) ; // S t a r t c r e a t i n g command f o r cmd
i f ( c h o i c e == JOptionPane . CANCEL OPTION) S t r i n g command = ”cmd / c s t a r t / w a i t cmd .
{ e x e / c \” ” ;
return ; f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++)
} {
} else { i f ( ! new F i l e ( f i l e N a m e s [ i ] + ” . box ” ) .
d i r e c t o r y . mkdirs ( ) ; e x i s t s ( ) | | MainPanel . checkBox .
} isSelected () ) {
command += TESSERACT CMD + ”− l ” +
// Rename and Copy f i l e s to output t e s s e r a c t L a n g u a g e + ” −psm 6 ” +
directory fileNames [ i ] + ” . t i f ” +
S t r i n g [ ] temp ; f i l e N a m e s [ i ] + ” b a t c h . nochop
String fileName ; makebox && ” ;
File sourceFile ; }
File destinationFile ; }
command += ” j a v a − j a r ” +
f o r ( f i n a l String sourcePath : l i s t ) { JTESSBOXEDITOR DIR + F i l e . s e p a r a t o r +
temp = new F i l e ( s o u r c e P a t h ) . getName ( ) . ” jTessBoxEditor . j a r ” ;
s p l i t ( ” \\. ” ) ; command += ” ” + ” \” ” + new F i l e (
OUTPUT DIR + F i l e . s e p a r a t o r +
// I f f o r m a t i s l a n g . f o n t . exp0 . t i f languageName ) + ” \” ” ;
i f ( temp . l e n g t h > 2 ) { command += ” && ” + OUTPUT DIR + F i l e .
f i l e N a m e = languageName + ” . ” + temp s e p a r a t o r + languageName + F i l e .
[ 1 ] + ” . exp0 . t i f ” ; s e p a r a t o r + ” t r a i n . bat ” ;
} else {
// E l s e i f f o r m a t i s j u s t image . t i f
f i l e N a m e = languageName + ” . ” + temp
[ 0 ] + ” . exp0 . t i f ” ; command += ” \” ” ;
}
//Run command f o r g e n e r a t i n g box f i l e
// P r e p a r e s o u r c e f i l e and d e s t i n a t i o n try {
f i l e f o r copying c r e a t e B a t c h F i l e ( f i l e N a m e s , languageName ,
s o u r c e F i l e = new F i l e ( s o u r c e P a t h ) ; tesseractLanguage ) ;
d e s t i n a t i o n F i l e = new F i l e (OUTPUT DIR + Runtime . getRuntime ( ) . e x e c ( command ) .
F i l e . s e p a r a t o r + languageName + waitFor ( ) ;
F i l e . separator + fileName ) ; f i n a l i n t c h o i c e = JOptionPane .
showConfirmDialog ( n u l l ,
try { languageName + ” . t r a i n e d d a t a was

159
c r e a t e d s u c c e s s f u l l y ! F i l e saved at languageName + ” . u n i c h a r s e t t e m p ”
T e s s 2 S p e e c h T r a i n e r / t e s s d a t a . Open ;
tessdata f o l d e r ?” , ” Successful ” , f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++)
JOptionPane . YES NO OPTION) ; {
batchCommand += f i l e N a m e s [ i ] + ” . t r ” ;
i f ( c h o i c e == JOptionPane . YES OPTION) { }
Runtime . getRuntime ( ) . e x e c ( ” e x p l o r e r .
exe t e s s d a t a ” ) ; // s e t u n i c h a r s e t p r o p e r t i e s
} batchCommand += ”&& ” +
SET UNICHARSET PROPERTIES CMD + ”−U ”
} catch ( IOException e ) { + l a n g u a g e P a t h + languageName +
// TODO Auto−g e n e r a t e d c a t c h b l o c k ” . u n i c h a r s e t t e m p −O ” + l a n g u a g e P a t h +
e . printStackTrace () ; languageName + ” . u n i c h a r s e t −
} catch ( HeadlessException e ) { s c r i p t d i r =” + TRAINING TOOLS DIR
// TODO Auto−g e n e r a t e d c a t c h b l o c k + ” && ” ;
e . printStackTrace () ;
} catch ( InterruptedException e ) { // c n t r a i n i n g
// TODO Auto−g e n e r a t e d c a t c h b l o c k batchCommand += CNTRAINING CMD ;
e . printStackTrace () ; f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++)
} {
batchCommand += f i l e N a m e s [ i ] + ” . t r ” ;
} }

/∗ ∗ // O p t i o n a l files
∗ A method t h a t c r e a t e s a b a t c h f i l e f o r
Automatic T e s s e r a c t T r a i n i n g // c o n f i g f i l e
∗ @param f i l e N a m e s f i l e N a m e s o f t h e batchCommand += ”&& xcopy / y ” +
t r a i n i n g data TRAINING TOOLS DIR + F i l e . s e p a r a t o r +
∗ @param languageName s p e c i f i e d name o f ” lang . c o n f i g ” + languagePath ;
output t r a i n e d data language batchCommand += ” && d e l ” + l a n g u a g e P a t h
∗ @param t e s s e r a c t L a n g u a g e s p e c i f i e d + languageName + ” . c o n f i g 2>NUL” ;
T e s s e r a c t l a n g u a g e f o r r e c o g n i z i n g box batchCommand += ” && r e n ” + l a n g u a g e P a t h
files + ” l a n g . c o n f i g ” + languageName + ” .
∗ @throws I O E x c e p t i o n E r r o r config ” ;
∗/
private s t a t i c void createBatchFile ( String [ ] // u n i c h a r a m b i g s f i l e
f i l e N a m e s , S t r i n g languageName , S t r i n g batchCommand += ” && xcopy / y ” +
t e s s e r a c t L a n g u a g e ) throws IOException { TRAINING TOOLS DIR + F i l e . s e p a r a t o r +
// C r e a t e command f o r b a t c h f i l e ” lang . unicharambigs ” + languagePath
;
// S e t d i r e c t o r y t o l a n g u a g e b e i n g c r e a t e d batchCommand += ” && d e l ” + l a n g u a g e P a t h
S t r i n g l a n g u a g e P a t h = OUTPUT DIR + F i l e . + languageName + ” . u n i c h a r a m b i g s 2>
s e p a r a t o r + languageName + F i l e . NUL” ;
separator ; batchCommand += ” && r e n ” + l a n g u a g e P a t h
+ ” lang . unicharambigs ” +
// S e t t o t h i s F i l e ’ s c u r r e n t d i r e c t o r y and languageName + ” . u n i c h a r a m b i g s ” ;
up by two f o l d e r s
S t r i n g batchCommand = ” cd /d %˜dp0 \ ncd // f r e q −dawg
. . / . . / \ n” ; batchCommand += ” && ” + WORDLIST2DAWG CMD
+ TRAINING TOOLS DIR + F i l e .
// G e n e r a t e . t r f i l e separator + ” lang . freqwords . txt ” +
f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++) l a n g u a g e P a t h + languageName + ” . f r e q −
{ dawg ” + l a n g u a g e P a t h +
// batchCommand += TESSERACT CMD + ”− l ” languageName + ” . u n i c h a r s e t ” ;
+ t e s s e r a c t L a n g u a g e + ” −psm 6 ” ;
batchCommand += TESSERACT CMD + ”−psm 6 // wird−dawg
”; batchCommand += ” && ” + WORDLIST2DAWG CMD
batchCommand += f i l e N a m e s [ i ] + ” . t i f ” ; + TRAINING TOOLS DIR + F i l e .
batchCommand += f i l e N a m e s [ i ] + ” ” ; separator + ” lang . wordlist ” +
// batchCommand += ” b a t c h . nochop box . l a n g u a g e P a t h + languageName + ” . word−
t r a i n && ” ; dawg ” + l a n g u a g e P a t h +
batchCommand += ” box . t r a i n && ” ; languageName + ” . u n i c h a r s e t ” ;
}
// b i g r a m s
// U n i c h a r s e t e x t r a c t o r ’ batchCommand += ” && ” + WORDLIST2DAWG CMD
batchCommand += UNICHARSET EXTRACTOR CMD ; + TRAINING TOOLS DIR + F i l e .
f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++) s e p a r a t o r + ” lang . bigrams ” +
{ l a n g u a g e P a t h + languageName + ” . bigram
batchCommand += f i l e N a m e s [ i ] + ” . box ” ; −dawg ” + l a n g u a g e P a t h +
} languageName + ” . u n i c h a r s e t ” ;
batchCommand += ”&& move / y u n i c h a r s e t ” +
languagePath ; // punc−dawg
batchCommand += ” && ” + WORDLIST2DAWG CMD
// f o n t p r o p e r t e s f i l e + TRAINING TOOLS DIR + F i l e .
f i n a l F i l e f o n t P r o p e r t i e s F i l e = new F i l e ( s e p a r a t o r + ” l a n g . punc ” +
l a n g u a g e P a t h + ” f o n t p r o p e r t i e s . sh ” ) ; l a n g u a g e P a t h + languageName + ” . punc−
B u f f e r e d W r i t e r w r i t e r = new B u f f e r e d W r i t e r dawg ” + l a n g u a g e P a t h +
( new F i l e W r i t e r ( f o n t P r o p e r t i e s F i l e ) ) ; languageName + ” . u n i c h a r s e t ” ;
S t r i n g fontPropertiesContent = ”” ;
S t r i n g fontName = ” ” ; // number−dawg
f o r ( i n t i = 0 ; i < f i l e N a m e s . l e n g t h ; i ++) batchCommand += ” && ” + WORDLIST2DAWG CMD
{ + TRAINING TOOLS DIR + F i l e .
fontName = f i l e N a m e s [ i ] . s u b s t r i n g ( s e p a r a t o r + ” l a n g . numbers ” +
f i l e N a m e s [ i ] . l a s t I n d e x O f ( ” \\ ” ) + 1 , l a n g u a g e P a t h + languageName + ” . number
fileNames [ i ] . length ( ) − 1) ; −dawg ” + l a n g u a g e P a t h +
fontName = fontName . s p l i t ( ” \ \ . ” ) [ 1 ] ; languageName + ” . u n i c h a r s e t ” ;
f o n t P r o p e r t i e s C o n t e n t += fontName + ” 0
0 0 0 0\ n” ; // Rename and move r e q u i r e d f i l e s
} batchCommand += ” && r e n normproto ” +
writer . write ( fontPropertiesContent ) ; languageName + ” . normproto ” ;
writer . flush () ; batchCommand += ” && move / y ” +
writer . close () ; languageName + ” . normproto ” +
languagePath ;
// m f t r a i n i n g
batchCommand += ” && ” + MFTRAINING CMD + batchCommand += ” && r e n i n t t e m p ” +
”−F ” + l a n g u a g e P a t h + ” languageName + ” . i n t t e m p ” ;
f o n t p r o p e r t i e s . sh −U ” + batchCommand += ” && move / y ” +
languagePath + languageName + ” . i n t t e m p ” +
” u n i c h a r s e t −O ”+ l a n g u a g e P a t h + languagePath ;

160
batchCommand += ” && move / y ” +
batchCommand += ” && r e n p f f m t a b l e ” + l a n g u a g e P a t h + languageName + ” .
languageName + ” . p f f m t a b l e ” ; t r a i n e d d a t a ” + TESSDATA DIR + F i l e .
batchCommand += ” && move / y ” + separator ;
languageName + ” . p f f m t a b l e ” +
languagePath ;
f i n a l F i l e b a t c h F i l e = new F i l e (
batchCommand += ” && r e n s h a p e t a b l e ” + languagePath + ” t r a i n . bat ” ) ;
languageName + ” . s h a p e t a b l e ” ;
batchCommand += ” && move / y ” + w r i t e r = new B u f f e r e d W r i t e r ( new F i l e W r i t e r
languageName + ” . s h a p e t a b l e ” + ( batchFile ) ) ;
languagePath ; w r i t e r . w r i t e ( batchCommand ) ;
writer . flush () ;
batchCommand += ” && ” + writer . close () ;
COMBINE TESSDATA CMD + l a n g u a g e P a t h + }
languageName ; }

Path = Tess2SpeechTrainer/src/anteraaron/tess2speech/MainPanel.java

package anteraaron . t e s s 2 s p e e c h ; B o r d e r F a c t o r y . createCompoundBorder (


MainPanel . t i f f t e x t f i e l d . g e t B o r d e r ( ) ,
i m p o r t j a v a . awt . G r a p h i c s ; BorderFactory . createEmptyBorder ( 5 ,
i m p o r t j a v a . awt . Graphics2D ; 5 , 5 , 5) ) ) ;
i m p o r t j a v a . awt . Image ; t h i s . add ( MainPanel . t i f f t e x t f i e l d ) ;
i m p o r t j a v a . awt . e v e n t . A c t i o n E v e n t ;
i m p o r t j a v a . awt . e v e n t . A c t i o n L i s t e n e r ; // Browse Button
import java . i o . F i l e ; t h i s . b r o w s e b u t t o n = new JButton ( ” Browse
import javax . swing . BorderFactory ; TIFF/ s ” ) ;
import javax . swing . ImageIcon ; t h i s . b r o w s e b u t t o n . s e t T o o l T i p T e x t ( ” Browse
i m p o r t j a v a x . s w i n g . JButton ; TIFF f i l e s . F i l e p a t h s o f m u l t i p l e
i m p o r t j a v a x . s w i n g . JCheckBox ; TIFF i m a g e s a r e s e p a r a t e d by semi−
i m p o r t j a v a x . s w i n g . JComboBox ; colon ”) ;
import javax . swing . JFileChooser ; t h i s . browse button . setBounds (135 , 160 ,
import javax . swing . JLabel ; 120 , 30) ;
i m p o r t j a v a x . s w i n g . JOptionPane ; t h i s . browse button . setFocusable ( f a l s e ) ;
import javax . swing . JPanel ; t h i s . add ( t h i s . b r o w s e b u t t o n ) ;
import javax . swing . JSeparator ; t h i s . browse button . addActionListener ( t h i s )
import javax . swing . JTextField ; ;
import javax . swing . SwingConstants ;
i m p o r t j a v a x . s w i n g . e v e n t . PopupMenuEvent ; // L i n e s e p a r a t o r
i m p o r t j a v a x . s w i n g . e v e n t . PopupMenuListener ; t h i s . s e p a r a t o r = new J S e p a r a t o r (
import javax . swing . f i l e c h o o s e r . S w i n g C o n s t a n t s . HORIZONTAL) ;
FileNameExtensionFilter ; t h i s . s e p a r a t o r . setBounds ( 6 0 , 205 , 320 , 5) ;
t h i s . add ( t h i s . s e p a r a t o r ) ;
/∗ ∗
∗ The P a n e l where t h e c o n t e n t s o f t h e Frame // T r a i n i n g s e t t i n g s l a b e l
i s placed . t h i s . s e t t i n g s l a b e l = new J L a b e l ( ” S e t t i n g s
∗ @author Anter Aaron M. C u s t o d i o ”) ;
∗ @since 2016/5/2 t h i s . s e t t i n g s l a b e l . setBounds ( 1 0 , 190 , 50 ,
∗/ 30) ;
p u b l i c c l a s s MainPanel e x t e n d s J P a n e l t h i s . add ( t h i s . s e t t i n g s l a b e l ) ;
implements A c t i o n L i s t e n e r {
// Font name l a b e l
private s t a t i c f i n a l long serialVersionUID = t h i s . f o n t l a b e l = new J L a b e l ( ” T r a i n e d Data
1L ; Name : ” ) ;
p r i v a t e f i n a l JButton b r o w s e b u t t o n , t h i s . f o n t l a b e l . setBounds ( 3 0 , 225 , 120 ,
start button ; 30) ;
p r i v a t e f i n a l JLabel t i f f l a b e l , t h i s . add ( t h i s . f o n t l a b e l ) ;
settings label , font label ,
language label ; //Name o f f o n t t e x t f i e l d
private f i n a l JSeparator separator ; MainPanel . f o n t t e x t f i e l d = new J T e x t F i e l d
private f i n a l JFileChooser fileChooser ; () ;
p r i v a t e f i n a l ImageIcon imageIcon ; MainPanel . f o n t t e x t f i e l d . s e t B o u n d s ( 1 7 0 ,
p r i v a t e f i n a l Image image ; 225 , 130 , 30) ;
s t a t i c JTextField t i f f t e x t f i e l d , MainPanel . f o n t t e x t f i e l d . s e t B o r d e r (
font textfield ; B o r d e r F a c t o r y . createCompoundBorder (
s t a t i c JComboBox<S t r i n g > l a n g u a g e c o m b o b o x ; MainPanel . f o n t t e x t f i e l d . g e t B o r d e r ( ) ,
s t a t i c JCheckBox checkBox ; BorderFactory . createEmptyBorder ( 5 ,
5 , 5 , 5) ) ) ;
/∗ ∗ t h i s . add ( MainPanel . f o n t t e x t f i e l d ) ;
∗ Constructor
∗/ // Language l a b e l
p u b l i c MainPanel ( ) { t h i s . l a n g u a g e l a b e l = new J L a b e l ( ”Box
// S e t b a c k g r o u n d c o l o r Maker : ” ) ;
super () ; t h i s . l a n g u a g e l a b e l . setBounds ( 3 0 , 275 ,
280 , 30) ;
// A b s o l u t e P o s i t i o n i n g t h i s . add ( t h i s . l a n g u a g e l a b e l ) ;
t h i s . setLayout ( n u l l ) ;
//Combo box f o r l a n g u a g e l i s t s
// I n p u t image l a b e l MainPanel . l a n g u a g e c o m b o b o x = new
t h i s . t i f f l a b e l = new J L a b e l ( ” I n p u t Image / JComboBox<S t r i n g >() ;
s : ”) ; addLanguages ( ) ;
t h i s . t i f f l a b e l . setBounds ( 1 0 , 80 , 130 , 30) MainPanel . l a n g u a g e c o m b o b o x . s e t B o u n d s ( 1 7 0 ,
; 275 , 100 , 30) ;
t h i s . add ( t h i s . t i f f l a b e l ) ; MainPanel . l a n g u a g e c o m b o b o x .
addPopupMenuListener ( new
// Browsed T i f f F i l e path c o n t a i n e r PopupMenuListener ( ) {
tiff textfield = new J T e x t F i e l d ( ) ;
MainPanel . t i f f t e x t f i e l d . setBounds ( 6 0 , @Ov err ide
115 , 280 , 30) ; p u b l i c v o i d p op u p M e n u W i l lB e c o m e V i s ib l e (
MainPanel . t i f f t e x t f i e l d . setBorder ( PopupMenuEvent e ) {

161
// R e f r e s h l a n g u a g e s if there a r e new i f ( index > 0) {
added f i n a l S t r i n g e x t e n s i o n = f i l e . getName
addLanguages ( ) ; ( ) . s u b s t r i n g ( index + 1) ;
} //Add a l l f i l e s w i t h . t r a i n e d d a t a
e x t e n s i o n t o ComboBox
@Ov err ide i f ( e x t e n s i o n . toLowerCase ( ) . e q u a l s ( ”
p u b l i c void popupMenuWillBecomeInvisible traineddata ”) ) {
( PopupMenuEvent e ) { MainPanel . l a n g u a g e c o m b o b o x . addItem (
} f i l e . getName ( ) . s u b s t r i n g ( 0 ,
index ) ) ;
@Ov err ide }
p u b l i c v o i d popupMenuCanceled ( }
PopupMenuEvent e ) { }
} }
}) ;
t h i s . add ( MainPanel . l a n g u a g e c o m b o b o x ) ; /∗ ∗
∗ Draw t h e o b j e c t s t o t h e s c r e e n
// Language l a b e l ∗/
checkBox = new JCheckBox ( ” O v e r w r i t e @Ov err ide
p r e v i o u s Box F i l e s ” ) ; p u b l i c v o i d paintComponent ( G r a p h i c s g ) {
checkBox . s e t B o u n d s ( 3 0 , 3 2 5 , 2 8 0 , 3 0 ) ; s u p e r . paintComponent ( g ) ;
checkBox . s e t F o c u s a b l e ( f a l s e ) ; Graphics2D g2d = ( Graphics2D ) g ;
t h i s . add ( checkBox ) ;
g2d . drawImage ( t h i s . image , 0 , 0 , 400 , 85 ,
// S t a r t t r a i n i n g b u t t o n null ) ;
t h i s . s t a r t b u t t o n = new JButton ( ” S t a r t }
Training ” ) ;
t h i s . s t a r t b u t t o n . setToolTipText ( ” Execute
Tesseract Training ” ) ; @Ov err ide
t h i s . s t a r t b u t t o n . setBounds ( 1 35 , 365 , 120 , p u b l i c void actionPerformed ( ActionEvent e ) {
30) ; // I f b r o w s e b u t t o n i s c l i c k e d .
this . start button . setFocusable ( f a l s e ) ; i f ( e . g e t S o u r c e ( ) == t h i s . b r o w s e b u t t o n ) {
t h i s . add ( t h i s . s t a r t b u t t o n ) ; f i n a l int returnVal = t h i s . fileChooser .
this . start button . addActionListener ( this ) ; showOpenDialog ( MainPanel . t h i s ) ;

// C r e a t e f i l e C h o o s e r if ( r e t u r n V a l == J F i l e C h o o s e r .
t h i s . f i l e C h o o s e r = new J F i l e C h o o s e r ( ) ; APPROVE OPTION) {
t h i s . f i l e C h o o s e r . s e t C u r r e n t D i r e c t o r y ( new // D i s p l a y browsed f i l e p a t h s
File (” ./ ”) ) ; S t r i n g t i f f p a t h s = ”” ;
for ( final File f i l e : this . fileChooser
//Add f i l t e r s t o f i l e c h o o s e r . getSelectedFiles () ){
this . fileChooser . addChoosableFileFilter ( t i f f p a t h s += f i l e . g e t A b s o l u t e P a t h ( )
new F i l e N a m e E x t e n s i o n F i l t e r ( ”Tag + ”;”;
Image F i l e Format ( ∗ . t i f f , ∗ . t i f ) ” , ” }
t i f ” , ” t i f f ”) ) ; t i f f t e x t f i e l d . setText ( t i f f p a t h s ) ;
this . fileChooser . }
setAcceptAllFileFilterUsed ( false ) ;
this . fileChooser . setMultiSelectionEnabled ( }
true ) ;
// I f start training is clicked
t h i s . i m a g e I c o n = new I m a g e I c o n ( g e t C l a s s ( ) . else i f ( e . g e t S o u r c e ( ) == t h i s .
g e t R e s o u r c e ( ” / i m a g e s / b a n n e r . png ” ) ) ; start button ){
t h i s . image = i m a g e I c o n . g e t I m a g e ( ) ; i f ( t i f f t e x t f i e l d . getText ( ) . r e p l a c e A l l (
” ; ” , ” ” ) . isEmpty ( ) | |
} f o n t t e x t f i e l d . g e t T e x t ( ) . isEmpty ( ) )
{
/∗ ∗ JOptionPane . s h o w M e s s a g e D i a l o g ( n u l l , ”
∗ Method t h a t p o p u l a t e s t h e Combo box w i t h Empty F i e l d / s ! ” , ” F a i l u r e ” ,
. traineddata languages JOptionPane . ERROR MESSAGE) ;
∗/ } else {
s t a t i c v o i d addLanguages ( ) { Functions . st a rt Tr ai n in g () ;
MainPanel . l a n g u a g e c o m b o b o x . r e m o v e A l l I t e m s }
() ; }
f i n a l F i l e f o l d e r = new F i l e ( ” . / t e s s d a t a ” )
; }
final File [ ] f i l e s = folder . l i s t F i l e s () ;

for ( final File f i l e : f i l e s ){


f i n a l i n t i n d e x = f i l e . getName ( ) .
lastIndexOf ( ’ . ’ ) ; }

These are the edited files in jTessBoxEditor by VietOCR [32]:


Path = Tess2SpeechTrainer/src/jTessBoxEditor/src/net/sourceforge/
tessboxeditor/Gui.java

/∗ ∗ 2 . 0 ( t h e ” L i c e n s e ” ) ; you may n o t
∗ E d i t e d by Anter Aaron M. C u s t o d i o ∗ use t h i s f i l e except i n compliance with the
∗ Removed T o o l b a r s , T r a i n i n g , T i f f G e n e r a t o r L i c e n s e . You may o b t a i n a copy o f
tabs . ∗ the License at
∗ Changed Open b u t t o n t o Next / F i n i s h b u t t o n ∗
∗ @since 2016/5/3 ∗ h t t p : / /www. a p a c h e . o r g / l i c e n s e s /LICENSE−2.0
∗ ∗
∗ ∗ U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d
∗ C o p y r i g h t @ 2011 Quan Nguyen to in writing , software
∗ ∗ d i s t r i b u t e d under the L i c e n s e i s
∗ L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n d i s t r i b u t e d on an ”AS I S ” BASIS , WITHOUT

162
∗ WARRANTIES OR CONDITIONS OF ANY KIND , protected static int scaleFactor = 4;
e i t h e r e x p r e s s or i m p l i e d . See the protected static i n t iconPosX = 0 ;
∗ License f o r the s p e c i f i c language governing protected static i n t iconPosY = 0 ;
p e r m i s s i o n s and l i m i t a t i o n s u n d e r protected static i n t i c o n W i dt h = 0 ;
∗ the License . protected static int iconHeight = 0;
∗/ protected static i n t imageWidth = 0 ;
package net . s o u r c e f o r g e . t e s s b o x e d i t o r ; protected static i n t imageHeight = 0 ;
protected static i n t movementMultiplier = 1 ;
i m p o r t j a v a . awt . B o r d e r L a y o u t ;
i m p o r t j a v a . awt . C o l o r ; p r i v a t e f i n a l s t a t i c Logger l o g g e r = Logger .
i m p o r t j a v a . awt . Component ; g e t L o g g e r ( Gui . c l a s s . getName ( ) ) ;
i m p o r t j a v a . awt . C u r s o r ; /∗
i m p o r t j a v a . awt . D e f a u l t K e y b o a r d F o c u s M a n a g e r ; ∗ Added by Anter Aaron M. C u s t o d i o
i m p o r t j a v a . awt . Font ; ∗ S a v e s a r g u m e n t s p r o v i d e d by t h e u s e r
i m p o r t j a v a . awt . Frame ; ∗/
i m p o r t j a v a . awt . G r a p h i c s E n v i r o n m e n t ; public static File [ ] inputTiffs ;
i m p o r t j a v a . awt . H e a d l e s s E x c e p t i o n ; public s t a t i c int currentIndex = 0;
i m p o r t j a v a . awt . Image ; public s t a t i c boolean f i n i s h e d = f a l s e ;
i m p o r t j a v a . awt . K e y E v e n t D i s p a t c h e r ;
i m p o r t j a v a . awt . KeyboardFocusManager ; /∗ ∗
i m p o r t j a v a . awt . P o i n t ; ∗ C r e a t e s new form J T e s s B o x E d i t o r .
i m p o r t j a v a . awt . R e c t a n g l e ; ∗/
i m p o r t j a v a . awt . dnd . DropTarget ; p u b l i c Gui ( ) {
i m p o r t j a v a . awt . e v e n t . ∗ ;
i m p o r t j a v a . awt . image . B u f f e r e d I m a g e ; t h i s . b a s e D i r = U t i l s . g e t B a s e D i r ( Gui . t h i s ) ;
import java . i o . ∗ ; try {
import java . nio . channels . ∗ ; UIManager . s e t L o o k A n d F e e l ( p r e f s . g e t ( ”
import java . t e x t . ∗ ; l o o k A n d F e e l ” , UIManager .
import java . u t i l . ∗ ; getSystemLookAndFeelClassName ( ) ) ) ;
import java . u t i l . l o g g i n g . Level ; } catch ( Exception e ) {
import java . u t i l . l o g g i n g . Logger ; // k e e p d e f a u l t LAF
import java . u t i l . p r e f s . P r e f e r e n c e s ; l o g g e r . l o g ( L e v e l .WARNING, e . g e t M e s s a g e ( ) , e
import javax . swing . ∗ ; );
import javax . swing . JSpinner . D e f a u l t E d i t o r ; }
import javax . swing . event . ∗ ; bundle = ResourceBundle . getBundle ( ” net .
import javax . swing . f i l e c h o o s e r . F i l e F i l t e r ; s o u r c e f o r g e . t e s s b o x e d i t o r . Gui ” ) ; //
import javax . swing . t a b l e . ∗ ; NOI18N
import net . s o u r c e f o r g e . t e s s b o x e d i t o r . initComponents ( ) ;
components . ∗ ;
import net . s o u r c e f o r g e . t e s s b o x e d i t o r . datamodel i f (MAC OS X) {
.∗; new MacOSXApplication ( Gui . t h i s ) ;
import net . s o u r c e f o r g e . v i e t o c r . u t i l . U t i l s ;
import net . s o u r c e f o r g e . t e s s 4 j . u t i l . // remove E x i t menuitem
ImageIOHelper ; t h i s . j M e n u F i l e . remove ( t h i s . j S e p a r a t o r E x i t ) ;
i m p o r t n e t . s o u r c e f o r g e . v i e t p a d . components . ∗ ; t h i s . j M e n u F i l e . remove ( t h i s . jMenuItemExit ) ;
import net . s o u r c e f o r g e . vietpad . u t i l i t i e s .
LimitedLengthDocument ; // remove About menuitem
import net . s o u r c e f o r g e . vietpad . u t i l i t i e s . t h i s . jMenuHelp . remove ( t h i s . j S e p a r a t o r A b o u t )
TextUtilities ; ;
t h i s . jMenuHelp . remove ( t h i s . jMenuItemAbout ) ;
public c l a s s Gui e x t e n d s j a v a x . s w i n g . JFrame { }

private s t a t i c f i n a l long serialVersionUID = boxPages = new A r r a y L i s t <T e s s B o x C o l l e c t i o n


1L ; >() ;
p u b l i c s t a t i c f i n a l S t r i n g APP NAME = ”
jTessBoxEditor ” ; // DnD s u p p o r t
p u b l i c s t a t i c f i n a l S t r i n g TO BE IMPLEMENTED new DropTarget ( t h i s . j S p l i t P a n e E d i t o r , new
= ”To be i m p l e m e n t e d i n s u b c l a s s ” ; F i l e D r o p T a r g e t L i s t e n e r ( Gui . t h i s , t h i s .
f i n a l S t r i n g [ ] h e a d e r s = { ” Char ” , ”X” , ”Y” , ” jSplitPaneEditor ) ) ;
Width ” , ” H e i g h t ” , ”Ok” } ; // E d i t e d by
Aaron t h i s . addWindowListener (
s t a t i c f i n a l b o o l e a n MAC OS X = System . new WindowAdapter ( ) {
g e t P r o p e r t y ( ” o s . name” ) . s t a r t s W i t h ( ”Mac” ) ;
s t a t i c f i n a l b o o l e a n WINDOWS = System . @O verr ide
g e t P r o p e r t y ( ” o s . name” ) . toLowerCase ( ) . p u b l i c v o i d w i n d o w C l o s i n g ( WindowEvent e )
s t a r t s W i t h ( ” windows ” ) ; {
s t a t i c f i n a l S t r i n g EOL = System . g e t P r o p e r t y ( quit () ;
” line . separator ”) ; }
s t a t i c f i n a l S t r i n g UTF8 = ”UTF−8” ;
p r o t e c t e d ResourceBundle bundle ; @O verr ide
static final Preferences prefs = Preferences . p u b l i c v o i d windowOpened ( WindowEvent e ) {
u s e r R o o t ( ) . node ( ” / n e t / s o u r c e f o r g e / updateSave ( f a l s e ) ;
tessboxeditor ”) ; setExtendedState ( p r e f s . getInt ( ”
private f i n a l Rectangle screen = w i n d o w S t a t e ” , Frame .NORMAL) ) ;
GraphicsEnvironment . populateMRUList ( ) ;
getLocalGraphicsEnvironment ( ) . }
getMaximumWindowBounds ( ) ; }) ;
private int filterIndex ;
private FileFilter [ ] f i l e F i l t e r s ; setSize (
private File boxFile ; snap ( p r e f s . g e t I n t ( ” frameWidth ” , 5 0 0 ) , 3 0 0 ,
private String currentDirectory , s c r e e n . width ) ,
outputDirectory ; snap ( p r e f s . g e t I n t ( ” f r a m e H e i g h t ” , 3 6 0 ) ,
p r i v a t e b o o l e a n boxChanged = f a l s e ; // E d i t e d 150 , screen . height ) ) ;
by Aaron setLocation (
protected boolean t a b l e S e l e c t A c t i o n ; snap (
p r i v a t e L i s t <T e s s B o x C o l l e c t i o n > boxPages ; p r e f s . g e t I n t ( ” frameX ” , ( s c r e e n . w i d t h −
p r o t e c t e d T e s s B o x C o l l e c t i o n b o x e s ; // b o x e s getWidth ( ) ) / 2 ) ,
o f c u r r e n t page s c r e e n . x , s c r e e n . x + s c r e e n . width −
p r o t e c t e d s h o r t imageIndex ; getWidth ( ) ) ,
p r i v a t e L i s t <B u f f e r e d I m a g e > i m a g e L i s t ; snap (
protected f i n a l F i l e baseDir ; p r e f s . g e t I n t ( ” frameY ” , s c r e e n . y + (
DefaultTableModel tableModel ; screen . height − getHeight ( ) ) / 3) ,
private boolean isTess2 0Format ; screen . y , screen . y + screen . height −
p r o t e c t e d RowHeaderList rowHeader ; getHeight () ) ) ;
p r o t e c t e d Font f o n t ;
K e y E v e n t D i s p a t c h e r d i s p a t c h e r = new
protected s t a t i c i n t iconMargin = 3 ; KeyEventDispatcher ( ) {
protected s t a t i c boolean invertControls =
false ; @O verr ide

163
p u b l i c b o o l e a n d i s p a t c h K e y E v e n t ( KeyEvent e ) j L a b e l 1 = new j a v a x . s w i n g . J L a b e l ( ) ;
{ j T e x t F i e l d L a n g = new j a v a x . s w i n g . J T e x t F i e l d
i f ( e . g e t I D ( ) == KeyEvent . KEY PRESSED) { () ;
i f ( e . getKeyCode ( ) == KeyEvent . VK F3 ) { j L a b e l 2 = new j a v a x . s w i n g . J L a b e l ( ) ;
jButtonFind . doClick ( ) ; j T e x t F i e l d B o o t s t r a p L a n g = new j a v a x . s w i n g .
} JTextField () ;
} jCheckBoxRTL = new j a v a x . s w i n g . JCheckBox ( ) ;
return f a l s e ; jComboBoxOps = new j a v a x . s w i n g . JComboBox ( ) ;
} j B u t t o n T r a i n = new j a v a x . s w i n g . JButton ( ) ;
}; j B u t t o n C a n c e l = new j a v a x . s w i n g . JButton ( ) ;
DefaultKeyboardFocusManager . jButtonCancel . setEnabled ( f a l s e ) ;
getCurrentKeyboardFocusManager ( ) . j B u t t o n V a l i d a t e = new j a v a x . s w i n g . JButton ( ) ;
addKeyEventDispatcher ( d i s p a t c h e r ) ; j B u t t o n S a v e L o g = new j a v a x . s w i n g . JButton ( ) ;
j B u t t o n C l e a r L o g = new j a v a x . s w i n g . JButton ( ) ;
/∗ j S c r o l l P a n e 1 = new j a v a x . s w i n g . J S c r o l l P a n e ( )
∗ E d i t e d by Anter Aaron C u s t o d i o . ;
∗ Change T e x t s o f Button j T ex t A r ea O u t pu t = new j a v a x . s w i n g . JTextArea
∗ Waits f o r UI t o c o m p l e t e and t h e n () ;
a u t o m a t i c a l l y open p a s s e d f i l e j P a n e l S t a t u s 1 = new j a v a x . s w i n g . J P a n e l ( ) ;
∗/ f i l l e r 2 = new j a v a x . s w i n g . Box . F i l l e r ( new
Thread t h r e a d = new Thread ( new Runnable ( ) { j a v a . awt . Dimension ( 0 , 1 7 ) , new j a v a . awt .
Dimension ( 0 , 1 7 ) , new j a v a . awt . Dimension
@Ov err ide (32767 , 17) ) ;
p u b l i c v o i d run ( ) { j P r o g r e s s B a r 1 = new j a v a x . s w i n g . J P r o g r e s s B a r
w h i l e ( ! f i n i s h e d ) {} () ;
i f ( i n p u t T i f f s . length > 0) { jProgressBar1 . s e t V i s i b l e ( f a l s e ) ;
openFile ( inputTiffs [ currentIndex ] ) ; j L a b e l T i m e = new j a v a x . s w i n g . J L a b e l ( ) ;
c u r r e n t I n d e x ++; j P a n e l E d i t o r = new j a v a x . s w i n g . J P a n e l ( ) ;
} j T o o l B a r E d i t o r = new j a v a x . s w i n g . JToolBar ( ) ;
j P a n e l 4 = new j a v a x . s w i n g . J P a n e l ( ) ;
i f ( c u r r e n t I n d e x == i n p u t T i f f s . l e n g t h ) jButtonOpen = new j a v a x . s w i n g . JButton ( ) ;
{ j B u t t o n S a v e = new j a v a x . s w i n g . JButton ( ) ;
// T r a i n i f l a s t i n d e x i s r e a c h e d j B u t t o n R e l o a d = new j a v a x . s w i n g . JButton ( ) ;
jButtonOpen . s e t T e x t ( ” F i n i s h ” ) ; j B u t t o n M e r g e = new j a v a x . s w i n g . JButton ( ) ;
} else { j B u t t o n S p l i t = new j a v a x . s w i n g . JButton ( ) ;
jButtonOpen . s e t T e x t ( ” Next ” ) ; j B u t t o n I n s e r t = new j a v a x . s w i n g . JButton ( ) ;
} j B u t t o n D e l e t e = new j a v a x . s w i n g . JButton ( ) ;
j P a n e l S p i n n e r = new j a v a x . s w i n g . J P a n e l ( ) ;
} j L a b e l C h a r a c t e r = new j a v a x . s w i n g . J L a b e l ( ) ;
}) ; j T e x t F i e l d C h a r a c t e r = new j a v a x . s w i n g .
thread . s t a r t () ; JTextField () ;
} j T e x t F i e l d C h a r a c t e r . setDocument ( new
LimitedLengthDocument ( 1 2 ) ) ;
p r i v a t e i n t snap ( f i n a l i n t i d e a l , f i n a l i n t j B u t t o n C o n v e r t = new j a v a x . s w i n g . JButton ( ) ;
min , f i n a l i n t max ) { j L a b e l X = new j a v a x . s w i n g . J L a b e l ( ) ;
f i n a l i n t TOLERANCE = 0 ; j S p i n n e r X = new j a v a x . s w i n g . J S p i n n e r ( ) ;
r e t u r n i d e a l < min + TOLERANCE ? min : ( j L a b e l Y = new j a v a x . s w i n g . J L a b e l ( ) ;
i d e a l > max − TOLERANCE ? max : i d e a l ) ; j S p i n n e r Y = new j a v a x . s w i n g . J S p i n n e r ( ) ;
} jLabelW = new j a v a x . s w i n g . J L a b e l ( ) ;
jSpinnerW = new j a v a x . s w i n g . J S p i n n e r ( ) ;
/∗ ∗ j L a b e l H = new j a v a x . s w i n g . J L a b e l ( ) ;
∗ P o p u l a t e s MRU L i s t . j S p i n n e r H = new j a v a x . s w i n g . J S p i n n e r ( ) ;
∗/ j S p l i t P a n e E d i t o r = new j a v a x . s w i n g .
p r o t e c t e d v o i d populateMRUList ( ) { JSplitPane () ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , jTabbedPaneBoxData = new j a v a x . s w i n g .
TO BE IMPLEMENTED) ; JTabbedPane ( ) ;
} j P a n e l C o o r d = new j a v a x . s w i n g . J P a n e l ( ) ;
j S c r o l l P a n e C o o r d = new j a v a x . s w i n g .
/∗ ∗ JScrollPane () ;
∗ T h i s method i s c a l l e d from w i t h i n t h e j T a b l e = new j a v a x . s w i n g . J T a b l e ( ) {
c o n s t r u c t o r t o i n i t i a l i z e t h e form . private s t a t i c f i n a l long
∗ WARNING: Do NOT m o d i f y t h i s c o d e . The s e r i a l V e r s i o n U I D = 1L ;
c o n t e n t o f t h i s method i s a l w a y s
∗ r e g e n e r a t e d by t h e Form E d i t o r . p u b l i c Component p r e p a r e R e n d e r e r (
∗/ T a b l e C e l l R e n d e r e r r e n d e r e r , i n t row
@SuppressWarnings ( { ” u n c h e c k e d ” , ” r a w t y p e s ” , i n t column ) {
}) Component c = s u p e r . p r e p a r e R e n d e r e r (
// <e d i t o r −f o l d d e f a u l t s t a t e =” c o l l a p s e d ” d e s c r e n d e r e r , row , column ) ;
=”G e n e r a t e d Code”>//GEN−BEGIN : i f ( f o n t != n u l l && column == 0 ) {
initComponents c . setFont ( font ) ;
p r i v a t e void initComponents ( ) { }

j F i l e C h o o s e r I n p u t I m a g e = new j a v a x . s w i n g . /∗
JFileChooser () ; ∗Added by Anter Aaron C u s t o d i o
j D i a l o g V a l i d a t i o n R e s u l t = new j a v a x . s w i n g . f o r changing c o l o r of
JDialog () ; s e l e c t e d rows
j S c r o l l P a n e 2 = new j a v a x . s w i n g . J S c r o l l P a n e ( ) ∗/
; i f ( ! i s R o w S e l e c t e d ( row ) && j T a b l e . g e t M o d e l
j T e x t A r e a V a l i d a t i o n R e s u l t = new j a v a x . s w i n g . ( ) . g e t V a l u e A t ( row , 5 ) != n u l l && ( b o o l e a n
JTextArea ( ) ; ) j T a b l e . g e t M o d e l ( ) . g e t V a l u e A t ( row , 5 ) ==
jPanelCommand = new j a v a x . s w i n g . J P a n e l ( ) ; true ) {
j B u t t o n C l o s e D i a l o g = new j a v a x . s w i n g . JButton c . s e t B a c k g r o u n d ( C o l o r .GREEN) ;
() ; } e l s e i f ( i s R o w S e l e c t e d ( row ) ) {
jTabbedPaneMain = new j a v a x . s w i n g . c . s e t B a c k g r o u n d ( C o l o r . BLUE) ;
JTabbedPane ( ) ; } else {
j P a n e l T r a i n e r = new j a v a x . s w i n g . J P a n e l ( ) ; c . s e t B a c k g r o u n d ( C o l o r .WHITE) ;
j T o o l B a r T r a i n e r = new j a v a x . s w i n g . JToolBar ( ) }
;
j P a n e l M a i n = new j a v a x . s w i n g . J P a n e l ( ) ; return c ;
j L a b e l 4 = new j a v a x . s w i n g . J L a b e l ( ) ; }
j T e x t F i e l d T e s s D i r = new j a v a x . s w i n g . };
JTextField () ; j P a n e l F i n d = new j a v a x . s w i n g . J P a n e l ( ) ;
j B u t t o n B r o w s e T e s s = new j a v a x . s w i n g . JButton j T e x t F i e l d F i n d = new j a v a x . s w i n g . J T e x t F i e l d
() ; () ;
j L a b e l 3 = new j a v a x . s w i n g . J L a b e l ( ) ; j B u t t o n F i n d = new j a v a x . s w i n g . JButton ( ) ;
j T e x t F i e l d D a t a D i r = new j a v a x . s w i n g . j S c r o l l P a n e B o x D a t a = new j a v a x . s w i n g .
JTextField () ; JScrollPane () ;
j B u t t o n B r o w s e D a t a = new j a v a x . s w i n g . JButton jTextAreaBoxData = new j a v a x . s w i n g . JTextArea
() ; () ;

164
jPanelBoxView = new j a v a x . s w i n g . J P a n e l ( ) ; jMenuLookAndFeel = new j a v a x . s w i n g . JMenu ( ) ;
j P a n e l N o r t h C o n t a i n e r = new j a v a x . s w i n g . jMenuTools = new j a v a x . s w i n g . JMenu ( ) ;
JPanel ( ) ; j M e n u I t e m M e r g e T i f f = new j a v a x . s w i n g .
j P a n e l C h a r = new j a v a x . s w i n g . J P a n e l ( ) ; JMenuItem ( ) ;
j L a b e l C o d e p o i n t = new j a v a x . s w i n g . J L a b e l ( ) ; j M e n u I t e m S p l i t T i f f = new j a v a x . s w i n g .
jLabelCodepoint . setFont ( jLabelCodepoint . JMenuItem ( ) ;
getFont ( ) . deriveFont ( 1 4 . 0 f ) ) ; jMenuHelp = new j a v a x . s w i n g . JMenu ( ) ;
j T e x t F i e l d C h a r = new j a v a x . s w i n g . J T e x t F i e l d jMenuItemHelp = new j a v a x . s w i n g . JMenuItem ( ) ;
() ; j S e p a r a t o r A b o u t = new j a v a x . s w i n g . JPopupMenu
jTextFieldChar . setFont ( jTextFieldChar . . Separator () ;
getFont ( ) . deriveFont ( 1 4 . 0 f ) ) ; jMenuItemAbout = new j a v a x . s w i n g . JMenuItem ( )
j T e x t F i e l d C o d e p o i n t V a l u e = new j a v a x . s w i n g . ;
JTextField () ;
jTextFieldCodepointValue . setFont ( java . u t i l . ResourceBundle bundle = java . u t i l .
jTextFieldCodepointValue . getFont ( ) . ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
deriveFont (14.0 f ) ) ; / t e s s b o x e d i t o r / Gui ” ) ; // NOI18N
j P a n e l C o n t r o l s = new j a v a x . s w i n g . J P a n e l ( ) ; jFileChooserInputImage . s e t D i a l o g T i t l e ( bundle
j L a b e l S p i n n e r M a r g i n = new j a v a x . s w i n g . J L a b e l . g e t S t r i n g ( ” jButtonOpen . ToolTipText ” ) ) ;
() ; // NOI18N
j S p i n n e r M a r g i n = new j a v a x . s w i n g . J S p i n n e r ( ) ;
j L a b e l S p i n n e r S c a l e = new j a v a x . s w i n g . J L a b e l currentDirectory = prefs . get ( ”
() ; currentDirectory ” , null ) ;
j S p i n n e r S c a l e = new j a v a x . s w i n g . J S p i n n e r ( ) ; outputDirectory = prefs . get ( ” outputDirectory
j L a b e l S u b i m a g e = new SubImageView ( ) ; ” , null ) ;
j P a n e l B u t t o n s = new j a v a x . s w i n g . J P a n e l ( ) ; jFileChooserInputImage . setCurrentDirectory (
j B u t t o n P r e v = new j a v a x . s w i n g . JButton ( ) ; c u r r e n t D i r e c t o r y == n u l l ? n u l l : new
j B u t t o n N e x t = new j a v a x . s w i n g . JButton ( ) ; File ( currentDirectory ) ) ;
j S c r o l l P a n e I m a g e = new j a v a x . s w i n g . f i l t e r I n d e x = p r e f s . g e t I n t ( ” f i l t e r I n d e x ” , 0)
JScrollPane () ; ;
jScrollPaneImage . getVerticalScrollBar () . F i l e F i l t e r a l l I m a g e F i l t e r = new S i m p l e F i l t e r
setUnitIncrement (20) ; ( ”bmp ; j p g ; j p e g ; png ; t i f ; t i f f ” , b u n d l e .
jScrollPaneImage . getHorizontalScrollBar () . getString (” All Image Files ”) ) ;
setUnitIncrement (20) ; F i l e F i l t e r p n g F i l t e r = new S i m p l e F i l t e r ( ” png
j L a b e l I m a g e = new J I m a g e L a b e l ( ) ; ” , ”PNG” ) ;
j P a n e l S t a t u s = new j a v a x . s w i n g . J P a n e l ( ) ; F i l e F i l t e r t i f f F i l t e r = new S i m p l e F i l t e r ( ”
j L a b e l S t a t u s = new j a v a x . s w i n g . J L a b e l ( ) ; t i f ; t i f f ” , ”TIFF” ) ;
j L a b e l P a g e N b r = new j a v a x . s w i n g . J L a b e l ( ) ; // F i l e F i l t e r t e x t F i l t e r = new S i m p l e F i l t e r ( ”
j B u t t o n P r e v P a g e = new j a v a x . s w i n g . JButton ( ) ; box ; t x t ” , ”Box F i l e s ” ) ;
j B u t t o n N e x t P a g e = new j a v a x . s w i n g . JButton ( ) ;
jPanelTIFFBox = new j a v a x . s w i n g . J P a n e l ( ) ; jFileChooserInputImage .
j T o o l B a r G e n e r a t o r = new j a v a x . s w i n g . JToolBar setAcceptAllFileFilterUsed ( false ) ;
() ; jFileChooserInputImage .
j P a n e l 3 = new j a v a x . s w i n g . J P a n e l ( ) ; addChoosableFileFilter ( allImageFilter ) ;
j B u t t o n I n p u t = new j a v a x . s w i n g . JButton ( ) ; jFileChooserInputImage .
j L a b e l O u t p u t = new j a v a x . s w i n g . J L a b e l ( ) ; addChoosableFileFilter ( pngFilter ) ;
j T e x t F i e l d O u p u t D i r = new j a v a x . s w i n g . jFileChooserInputImage .
JTextField () ; addChoosableFileFilter ( t i f f F i l t e r ) ;
j B u t t o n B r o w s e O u t p u t D i r = new j a v a x . s w i n g . // j F i l e C h o o s e r . a d d C h o o s a b l e F i l e F i l t e r (
JButton ( ) ; textFilter ) ;
j T e x t F i e l d P r e f i x = new j a v a x . s w i n g . f i l e F i l t e r s = jFileChooserInputImage .
JTextField () ; getChoosableFileFilters () ;
jTextFieldPrefix . setText ( p r e f s . get ( ” i f ( f i l t e r I n d e x < f i l e F i l t e r s . length ) {
t r a i n L a n g u a g e ” , ” eng ” ) ) ; jFileChooserInputImage . s e t F i l e F i l t e r (
j T e x t F i e l d F i l e N a m e = new j a v a x . s w i n g . fileFilters [ filterIndex ]) ;
JTextField () ; }
j B u t t o n F o n t = new j a v a x . s w i n g . JButton ( ) ;
j C h e c k B o x A n t i A l i a s i n g = new j a v a x . s w i n g . jDialogValidationResult . setTitle (” Validation
JCheckBox ( ) ; Result ” ) ;
j L a b e l N o i s e = new j a v a x . s w i n g . J L a b e l ( ) ; j D i a l o g V a l i d a t i o n R e s u l t . setMinimumSize ( new
j S p i n n e r N o i s e = new j a v a x . s w i n g . J S p i n n e r ( ) ; j a v a . awt . Dimension ( 6 0 0 , 4 5 0 ) ) ;
j L a b e l T r a c k i n g = new j a v a x . s w i n g . J L a b e l ( ) ;
j S p i n n e r T r a c k i n g = new j a v a x . s w i n g . J S p i n n e r jTextAreaValidationResult . setEditable ( f a l s e )
() ; ;
jLabelW1 = new j a v a x . s w i n g . J L a b e l ( ) ; j T e x t A r e a V a l i d a t i o n R e s u l t . setColumns ( 2 0 ) ;
jSpinnerW1 = new j a v a x . s w i n g . J S p i n n e r ( ) ; j T e x t A r e a V a l i d a t i o n R e s u l t . setRows ( 5 ) ;
j L a b e l H 1 = new j a v a x . s w i n g . J L a b e l ( ) ; j T e x t A r e a V a l i d a t i o n R e s u l t . s e t M a r g i n ( new j a v a
j S p i n n e r H 1 = new j a v a x . s w i n g . J S p i n n e r ( ) ; . awt . I n s e t s ( 5 , 5 , 2 , 2 ) ) ;
j B u t t o n G e n e r a t e = new j a v a x . s w i n g . JButton ( ) ; j S c r o l l P a n e 2 . setViewportView (
j B u t t o n C l e a r = new j a v a x . s w i n g . JButton ( ) ; jTextAreaValidationResult ) ;
j S c r o l l P a n e T e x t = new j a v a x . s w i n g .
JScrollPane () ; j D i a l o g V a l i d a t i o n R e s u l t . g e t C o n t e n t P a n e ( ) . add
j T e x t A r e a I n p u t = new j a v a x . s w i n g . JTextArea ( ) ( j S c r o l l P a n e 2 , j a v a . awt . B o r d e r L a y o u t .
; CENTER) ;
jMenuBar = new j a v a x . s w i n g . JMenuBar ( ) ;
j M e n u F i l e = new j a v a x . s w i n g . JMenu ( ) ; jPanelCommand . s e t B o r d e r ( j a v a x . s w i n g .
jMenuItemOpen = new j a v a x . s w i n g . JMenuItem ( ) ; BorderFactory . createEmptyBorder ( 5 , 1, 5,
jMenuItemSave = new j a v a x . s w i n g . JMenuItem ( ) ; 1) ) ;
jMenuItemSaveAs = new j a v a x . s w i n g . JMenuItem
() ; jButtonCloseDialog . setText ( ” Close ” ) ;
j S e p a r a t o r R e c e n t F i l e s = new j a v a x . s w i n g . jButtonCloseDialog . setToolTipText ( ” Close
JPopupMenu . S e p a r a t o r ( ) ; Dialog ” ) ;
j M e n u R e c e n t F i l e s = new j a v a x . s w i n g . JMenu ( ) ; j B u t t o n C l o s e D i a l o g . a d d A c t i o n L i s t e n e r ( new
j S e p a r a t o r E x i t = new j a v a x . s w i n g . JPopupMenu . j a v a . awt . e v e n t . A c t i o n L i s t e n e r ( ) {
Separator () ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jMenuItemExit = new j a v a x . s w i n g . JMenuItem ( ) ; ActionEvent evt ) {
jMenuEdit = new j a v a x . s w i n g . JMenu ( ) ; jButtonCloseDialogActionPerformed ( evt ) ;
t h i s . jMenuEdit . s e t V i s i b l e ( f a l s e ) ; }
jMenuItemMerge = new j a v a x . s w i n g . JMenuItem ( ) }) ;
; jPanelCommand . add ( j B u t t o n C l o s e D i a l o g ) ;
j M e n u I t e m S p l i t = new j a v a x . s w i n g . JMenuItem ( )
; j D i a l o g V a l i d a t i o n R e s u l t . g e t C o n t e n t P a n e ( ) . add
j M e n u I t e m I n s e r t = new j a v a x . s w i n g . JMenuItem ( jPanelCommand , j a v a . awt . B o r d e r L a y o u t .
() ; SOUTH) ;
j M e n u I t e m D e l e t e = new j a v a x . s w i n g . JMenuItem
() ; jDialogValidationResult .
j M e n u S e t t i n g s = new j a v a x . s w i n g . JMenu ( ) ; setLocationRelativeTo ( this ) ;
jMenuItemFont = new j a v a x . s w i n g . JMenuItem ( ) ;
j S e p a r a t o r L A F = new j a v a x . s w i n g . JPopupMenu . s e t D e f a u l t C l o s e O p e r a t i o n ( javax . swing .
Separator () ; WindowConstants . EXIT ON CLOSE ) ;

165
s e t T i t l e ( ” jTessBoxEditor ” ) ; DefaultComboBoxModel ( TrainingMode . v a l u e s
() ) ) ;
jTabbedPaneMain . s e t B o r d e r ( j a v a x . s w i n g . jComboBoxOps . s e t T o o l T i p T e x t ( ” T r a i n i n g Mode” )
B o r d e r F a c t o r y . c r e a t e E m p t y B o r d e r ( −2 , 0 , 0 , ;
0) ) ; j P a n e l M a i n . add ( jComboBoxOps ) ;
jTabbedPaneMain . a d d C h a n g e L i s t e n e r ( new j a v a x .
swing . event . ChangeListener ( ) { j B u t t o n T r a i n . s e t T e x t ( ”Run” ) ;
p u b l i c void stateChanged ( javax . swing . event . jButtonTrain . setToolTipText ( ” Start Training ”
ChangeEvent e v t ) { );
jTabbedPaneMainStateChanged ( e v t ) ; j B u t t o n T r a i n . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
} event . ActionListener ( ) {
}) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
ActionEvent evt ) {
j P a n e l T r a i n e r . s e t L a y o u t ( new j a v a . awt . jButtonTrainActionPerformed ( evt ) ;
BorderLayout ( ) ) ; }
}) ;
jToolBarTrainer . setRollover ( true ) ; j P a n e l M a i n . add ( j B u t t o n T r a i n ) ;

j P a n e l M a i n . s e t L a y o u t ( new j a v a . awt . FlowLayout jButtonCancel . setText ( ” Cancel ” ) ;


( j a v a . awt . FlowLayout . LEFT) ) ; jButtonCancel . setToolTipText ( ” Cancel
Training ” ) ;
jLabel4 . setText ( ” Tesseract Executables ” ) ; j B u t t o n C a n c e l . a d d A c t i o n L i s t e n e r ( new j a v a . awt
j P a n e l M a i n . add ( j L a b e l 4 ) ; . event . ActionListener ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jTextFieldTessDir . setToolTipText ( ” Location ActionEvent evt ) {
of Tesseract Executables ” ) ; jButtonCancelActionPerformed ( evt ) ;
jTextFieldTessDir . setEnabled ( f a l s e ) ; }
j T e x t F i e l d T e s s D i r . s e t P r e f e r r e d S i z e ( new j a v a . }) ;
awt . Dimension ( 1 8 0 , 2 4 ) ) ; j P a n e l M a i n . add ( j B u t t o n C a n c e l ) ;
j P a n e l M a i n . add ( j T e x t F i e l d T e s s D i r ) ;
jButtonValidate . setText ( ” Validate ” ) ;
jButtonBrowseTess . setText ( ” . . . ” ) ; jButtonValidate . setToolTipText ( ” Validate
j B u t t o n B r o w s e T e s s . s e t T o o l T i p T e x t ( ” Browse ” ) ; Generated Traineddata ” ) ;
j B u t t o n B r o w s e T e s s . setMaximumSize ( new j a v a . j B u t t o n V a l i d a t e . a d d A c t i o n L i s t e n e r ( new j a v a .
awt . Dimension ( 3 0 , 2 3 ) ) ; awt . e v e n t . A c t i o n L i s t e n e r ( ) {
j B u t t o n B r o w s e T e s s . setMinimumSize ( new j a v a . p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
awt . Dimension ( 3 0 , 2 3 ) ) ; ActionEvent evt ) {
j B u t t o n B r o w s e T e s s . s e t P r e f e r r e d S i z e ( new j a v a . jButtonValidateActionPerformed ( evt ) ;
awt . Dimension ( 2 4 , 2 3 ) ) ; }
j B u t t o n B r o w s e T e s s . a d d A c t i o n L i s t e n e r ( new j a v a }) ;
. awt . e v e n t . A c t i o n L i s t e n e r ( ) { j P a n e l M a i n . add ( j B u t t o n V a l i d a t e ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
ActionEvent evt ) { j B u t t o n S a v e L o g . s e t T e x t ( ” Save ” ) ;
jButtonBrowseTessActionPerformed ( evt ) ; j B u t t o n S a v e L o g . s e t T o o l T i p T e x t ( ” Save Log ” ) ;
} j B u t t o n S a v e L o g . a d d A c t i o n L i s t e n e r ( new j a v a .
}) ; awt . e v e n t . A c t i o n L i s t e n e r ( ) {
j P a n e l M a i n . add ( j B u t t o n B r o w s e T e s s ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
ActionEvent evt ) {
j L a b e l 3 . s e t T e x t ( ” T r a i n i n g Data ” ) ; jButtonSaveLogActionPerformed ( evt ) ;
j P a n e l M a i n . add ( j L a b e l 3 ) ; }
}) ;
jTextFieldDataDir . setToolTipText ( ” Location j P a n e l M a i n . add ( j B u t t o n S a v e L o g ) ;
o f S o u r c e T r a i n i n g Data ” ) ;
jTextFieldDataDir . setEnabled ( f a l s e ) ; jButtonClearLog . setText ( ” Clear ” ) ;
j T e x t F i e l d D a t a D i r . s e t P r e f e r r e d S i z e ( new j a v a . jButtonClearLog . setToolTipText ( ” Clear
awt . Dimension ( 1 8 0 , 2 4 ) ) ; Textaera ” ) ;
j P a n e l M a i n . add ( j T e x t F i e l d D a t a D i r ) ; j B u t t o n C l e a r L o g . a d d A c t i o n L i s t e n e r ( new j a v a .
awt . e v e n t . A c t i o n L i s t e n e r ( ) {
jButtonBrowseData . s e t T e x t ( ” . . . ” ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j B u t t o n B r o w s e D a t a . s e t T o o l T i p T e x t ( ” Browse ” ) ; ActionEvent evt ) {
j B u t t o n B r o w s e D a t a . setMaximumSize ( new j a v a . jButtonClearLogActionPerformed ( evt ) ;
awt . Dimension ( 3 0 , 2 3 ) ) ; }
j B u t t o n B r o w s e D a t a . setMinimumSize ( new j a v a . }) ;
awt . Dimension ( 3 0 , 2 3 ) ) ; j P a n e l M a i n . add ( j B u t t o n C l e a r L o g ) ;
j B u t t o n B r o w s e D a t a . s e t P r e f e r r e d S i z e ( new j a v a .
awt . Dimension ( 2 4 , 2 3 ) ) ; j T o o l B a r T r a i n e r . add ( j P a n e l M a i n ) ;
j B u t t o n B r o w s e D a t a . a d d A c t i o n L i s t e n e r ( new j a v a
. awt . e v e n t . A c t i o n L i s t e n e r ( ) { j P a n e l T r a i n e r . add ( j T o o l B a r T r a i n e r , j a v a . awt .
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . B o r d e r L a y o u t . PAGE START) ;
ActionEvent evt ) {
jButtonBrowseDataActionPerformed ( evt ) ; j T ex t A r ea O u t pu t . s e t E d i t a b l e ( f a l s e ) ;
} j T ex t A r ea O u t pu t . s e t C o l u m n s ( 2 0 ) ;
}) ; j T ex t A r ea O u t pu t . setRows ( 5 ) ;
j P a n e l M a i n . add ( j B u t t o n B r o w s e D a t a ) ; j T ex t A r ea O u t pu t . s e t M a r g i n ( new j a v a . awt .
I n s e t s (5 , 5 , 2 , 2) ) ;
j L a b e l 1 . s e t T e x t ( ” Language ” ) ; j S c r o l l P a n e 1 . s e t V i e w p o r t V i e w ( j Te x t A re a O u tp u t
j P a n e l M a i n . add ( j L a b e l 1 ) ; );

j T e x t F i e l d L a n g . setMinimumSize ( new j a v a . awt . j P a n e l T r a i n e r . add ( j S c r o l l P a n e 1 , j a v a . awt .


Dimension ( 3 4 , 1 9 ) ) ; B o r d e r L a y o u t .CENTER) ;
j T e x t F i e l d L a n g . s e t P r e f e r r e d S i z e ( new j a v a . awt
. Dimension ( 3 0 , 2 4 ) ) ; j P a n e l S t a t u s 1 . s e t L a y o u t ( new j a v a . awt .
j P a n e l M a i n . add ( j T e x t F i e l d L a n g ) ; FlowLayout ( j a v a . awt . FlowLayout . LEFT) ) ;
j P a n e l S t a t u s 1 . add ( f i l l e r 2 ) ;
j L a b e l 2 . s e t T e x t ( ” B o o t s t r a p Language ” ) ;
j P a n e l M a i n . add ( j L a b e l 2 ) ; jProgressBar1 . setStringPainted ( true ) ;
j P a n e l S t a t u s 1 . add ( j P r o g r e s s B a r 1 ) ;
j T e x t F i e l d B o o t s t r a p L a n g . setMinimumSize ( new j P a n e l S t a t u s 1 . add ( j L a b e l T i m e ) ;
j a v a . awt . Dimension ( 3 4 , 1 9 ) ) ;
j T e x t F i e l d B o o t s t r a p L a n g . s e t P r e f e r r e d S i z e ( new j P a n e l T r a i n e r . add ( j P a n e l S t a t u s 1 , j a v a . awt .
j a v a . awt . Dimension ( 3 0 , 2 4 ) ) ; B o r d e r L a y o u t .SOUTH) ;
j P a n e l M a i n . add ( j T e x t F i e l d B o o t s t r a p L a n g ) ;
// jTabbedPaneMain . addTab ( ” T r a i n e r ” ,
jCheckBoxRTL . s e t T e x t ( ”RTL” ) ; jPanelTrainer ) ;
jCheckBoxRTL . s e t T o o l T i p T e x t ( ” Right−To−L e f t
Text D i r e c t i o n ” ) ; j P a n e l E d i t o r . s e t L a y o u t ( new j a v a . awt .
j P a n e l M a i n . add ( jCheckBoxRTL ) ; BorderLayout ( ) ) ;

jComboBoxOps . s e t M o d e l ( new jToolBarEditor . setRollover ( true ) ;

166
jButtonInsert . setFocusable ( f a l s e ) ;
j P a n e l 4 . s e t L a y o u t ( new j a v a . awt . FlowLayout ( jButtonInsert . setHorizontalTextPosition (
j a v a . awt . FlowLayout . LEFT, 1 , 5 ) ) ; j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ;
jButtonInsert . s e t V e r t i c a l T e x t P o s i t i o n ( javax .
jButtonOpen . s e t T e x t ( b u n d l e . g e t S t r i n g ( ” s w i n g . S w i n g C o n s t a n t s .BOTTOM) ;
jButtonOpen . Text ” ) ) ; // NOI18N j B u t t o n I n s e r t . a d d A c t i o n L i s t e n e r ( new j a v a . awt
jButtonOpen . s e t T o o l T i p T e x t ( b u n d l e . g e t S t r i n g ( . event . ActionListener ( ) {
” jButtonOpen . ToolTipText ” ) ) ; // NOI18N p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jButtonOpen . s e t F o c u s a b l e ( f a l s e ) ; ActionEvent evt ) {
jButtonOpen . s e t H o r i z o n t a l T e x t P o s i t i o n ( j a v a x . jButtonInsertActionPerformed ( evt ) ;
s w i n g . S w i n g C o n s t a n t s .CENTER) ; }
jButtonOpen . s e t V e r t i c a l T e x t P o s i t i o n ( j a v a x . }) ;
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j P a n e l 4 . add ( j B u t t o n I n s e r t ) ;
jButtonOpen . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
event . ActionListener ( ) { jButtonDelete . setText ( bundle . g e t S t r i n g ( ”
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j B u t t o n D e l e t e . Text ” ) ) ; // NOI18N
ActionEvent evt ) { jButtonDelete . setToolTipText ( bundle .
jButtonOpenActionPerformed ( evt ) ; g e t S t r i n g ( ” j B u t t o n D e l e t e . ToolTipText ” ) ) ;
} // NOI18N
}) ; jButtonDelete . setFocusable ( f a l s e ) ;
j P a n e l 4 . add ( jButtonOpen ) ; jButtonDelete . setHorizontalTextPosition (
j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ;
jButtonSave . setText ( bundle . g e t S t r i n g ( ” jButtonDelete . s e t V e r t i c a l T e x t P o s i t i o n ( javax .
j B u t t o n S a v e . Text ” ) ) ; // NOI18N s w i n g . S w i n g C o n s t a n t s .BOTTOM) ;
jButtonSave . setToolTipText ( bundle . g e t S t r i n g ( j B u t t o n D e l e t e . a d d A c t i o n L i s t e n e r ( new j a v a . awt
” j B u t t o n S a v e . ToolTipText ” ) ) ; // NOI18N . event . ActionListener ( ) {
jButtonSave . setFocusable ( f a l s e ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jButtonSave . s e t H o r i z o n t a l T e x t P o s i t i o n ( javax . ActionEvent evt ) {
s w i n g . S w i n g C o n s t a n t s .CENTER) ; jButtonDeleteActionPerformed ( evt ) ;
jButtonSave . s e t V e r t i c a l T e x t P o s i t i o n ( javax . }
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; }) ;
j B u t t o n S a v e . a d d A c t i o n L i s t e n e r ( new j a v a . awt . j P a n e l 4 . add ( j B u t t o n D e l e t e ) ;
event . ActionListener ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j T o o l B a r E d i t o r . add ( j P a n e l 4 ) ;
ActionEvent evt ) {
jButtonSaveActionPerformed ( evt ) ; jLabelCharacter . setLabelFor (
} jTextFieldCharacter ) ;
}) ; jLabelCharacter . setText ( ” Character ” ) ;
j P a n e l 4 . add ( j B u t t o n S a v e ) ; j P a n e l S p i n n e r . add ( j L a b e l C h a r a c t e r ) ;

jButtonReload . s e t T e x t ( ” Reload ” ) ; j T e x t F i e l d C h a r a c t e r . setColumns ( 4 ) ;


j B u t t o n R e l o a d . s e t T o o l T i p T e x t ( ” R e l o a d Box jTextFieldCharacter . setEnabled ( f a l s e ) ;
File ”) ; j T e x t F i e l d C h a r a c t e r . s e t M a r g i n ( new j a v a . awt .
jButtonReload . setFocusable ( f a l s e ) ; I n s e t s (0 , 2 , 0 , 2) ) ;
jButtonReload . s e t H o r i z o n t a l T e x t P o s i t i o n ( j T e x t F i e l d C h a r a c t e r . s e t P r e f e r r e d S i z e ( new
j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ; j a v a . awt . Dimension ( 4 0 , 2 4 ) ) ;
jButtonReload . s e t V e r t i c a l T e x t P o s i t i o n ( javax . j T e x t F i e l d C h a r a c t e r . a d d A c t i o n L i s t e n e r ( new
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j a v a . awt . e v e n t . A c t i o n L i s t e n e r ( ) {
j B u t t o n R e l o a d . a d d A c t i o n L i s t e n e r ( new j a v a . awt p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
. event . ActionListener ( ) { ActionEvent evt ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . jTextFieldCharacterActionPerformed ( evt ) ;
ActionEvent evt ) { }
jButtonReloadActionPerformed ( evt ) ; }) ;
} j T e x t F i e l d C h a r a c t e r . a d d K e y L i s t e n e r ( new j a v a .
}) ; awt . e v e n t . KeyAdapter ( ) {
j P a n e l 4 . add ( j B u t t o n R e l o a d ) ; p u b l i c v o i d k e y R e l e a s e d ( j a v a . awt . e v e n t .
j P a n e l 4 . add ( Box . c r e a t e H o r i z o n t a l S t r u t ( 1 0 0 ) ) ; KeyEvent e v t ) {
jTextFieldCharacterKeyReleased ( evt ) ;
jButtonMerge . setText ( bundle . g e t S t r i n g ( ” }
j B u t t o n M e r g e . Text ” ) ) ; // NOI18N }) ;
jButtonMerge . setToolTipText ( bundle . g e t S t r i n g j P a n e l S p i n n e r . add ( j T e x t F i e l d C h a r a c t e r ) ;
( ” j B u t t o n M e r g e . ToolTipText ” ) ) ; // NOI18N
jButtonMerge . s e t F o c u s a b l e ( f a l s e ) ; j B u t t o n C o n v e r t . s e t I c o n ( new j a v a x . s w i n g .
jButtonMerge . s e t H o r i z o n t a l T e x t P o s i t i o n ( javax ImageIcon ( g e t C l a s s ( ) . getResource ( ”/ net /
. s w i n g . S w i n g C o n s t a n t s .CENTER) ; s o u r c e f o r g e / t e s s b o x e d i t o r / i c o n s / t o o l s . png
jButtonMerge . s e t V e r t i c a l T e x t P o s i t i o n ( javax . ” ) ) ) ; // NOI18N
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j B u t t o n C o n v e r t . s e t T o o l T i p T e x t ( ”<html>C o n v e r t
j B u t t o n M e r g e . a d d A c t i o n L i s t e n e r ( new j a v a . awt . NCR and Escape<b r/>S e q u e n c e t o Unicode </
event . ActionListener ( ) { html>” ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j B u t t o n C o n v e r t . s e t P r e f e r r e d S i z e ( new j a v a . awt
ActionEvent evt ) { . Dimension ( 2 0 , 2 0 ) ) ;
jButtonMergeActionPerformed ( evt ) ; j B u t t o n C o n v e r t . a d d A c t i o n L i s t e n e r ( new j a v a .
} awt . e v e n t . A c t i o n L i s t e n e r ( ) {
}) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j P a n e l 4 . add ( j B u t t o n M e r g e ) ; ActionEvent evt ) {
jButtonConvertActionPerformed ( evt ) ;
j B u t t o n S p l i t . setText ( bundle . g e t S t r i n g ( ” }
j B u t t o n S p l i t . Text ” ) ) ; // NOI18N }) ;
j B u t t o n S p l i t . setToolTipText ( bundle . g e t S t r i n g j P a n e l S p i n n e r . add ( j B u t t o n C o n v e r t ) ;
( ” j B u t t o n S p l i t . ToolTipText ” ) ) ; // NOI18N j P a n e l S p i n n e r . add ( Box . c r e a t e H o r i z o n t a l S t r u t
jButtonSplit . setFocusable ( f a l s e ) ; (10) ) ;
jButtonSplit . setHorizontalTextPosition ( javax
. s w i n g . S w i n g C o n s t a n t s .CENTER) ; jLabelX . setLabelFor ( jSpinnerX ) ;
jButtonSplit . s e t V e r t i c a l T e x t P o s i t i o n ( javax . j L a b e l X . s e t T e x t ( ”X” ) ;
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j P a n e l S p i n n e r . add ( j L a b e l X ) ;
j B u t t o n S p l i t . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
event . ActionListener ( ) { j S p i n n e r X . s e t E d i t o r ( new j a v a x . s w i n g . J S p i n n e r
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . . NumberEditor ( j S p i n n e r X , ”#” ) ) ;
ActionEvent evt ) { jSpinnerX . setEnabled ( f a l s e ) ;
jButtonSplitActionPerformed ( evt ) ; j S p i n n e r X . s e t P r e f e r r e d S i z e ( new j a v a . awt .
} Dimension ( 6 3 , 2 2 ) ) ;
}) ; j S p i n n e r X . a d d C h a n g e L i s t e n e r ( new j a v a x . s w i n g .
j P a n e l 4 . add ( j B u t t o n S p l i t ) ; event . ChangeListener ( ) {
p u b l i c void stateChanged ( javax . swing . event .
j B u t t o n I n s e r t . setText ( bundle . g e t S t r i n g ( ” ChangeEvent e v t ) {
j B u t t o n I n s e r t . Text ” ) ) ; // NOI18N jSpinnerXStateChanged ( evt ) ;
j B u t t o n I n s e r t . setToolTipText ( bundle . }
g e t S t r i n g ( ” j B u t t o n I n s e r t . ToolTipText ” ) ) ; }) ;
// NOI18N j P a n e l S p i n n e r . add ( j S p i n n e r X ) ;

167
jLabelY . setLabelFor ( jSpinnerY ) ; p u b l i c b o o l e a n i s C e l l E d i t a b l e ( i n t rowIndex ,
j L a b e l Y . s e t T e x t ( ”Y” ) ; i n t columnIndex ) {
j P a n e l S p i n n e r . add ( j L a b e l Y ) ; r e t u r n canEdit [ columnIndex ] ;
}
j S p i n n e r Y . s e t E d i t o r ( new j a v a x . s w i n g . J S p i n n e r }) ;
. NumberEditor ( j S p i n n e r Y , ”#” ) ) ;
jSpinnerY . setEnabled ( f a l s e ) ; jTable . s e t S e l e c t i o n M o d e ( javax . swing .
j S p i n n e r Y . s e t P r e f e r r e d S i z e ( new j a v a . awt . ListSelectionModel .
Dimension ( 6 3 , 2 2 ) ) ; MULTIPLE INTERVAL SELECTION) ;
j S p i n n e r Y . a d d C h a n g e L i s t e n e r ( new j a v a x . s w i n g . jScrollPaneCoord . setViewportView ( jTable ) ;
event . ChangeListener ( ) { tableModel = ( DefaultTableModel ) t h i s . jTable
p u b l i c void stateChanged ( javax . swing . event . . getModel ( ) ;
ChangeEvent e v t ) { t a b l e M o d e l . a d d T a b l e M o d e l L i s t e n e r ( new
jSpinnerYStateChanged ( evt ) ; TableModelListener () {
} p u b l i c v o i d t a b l e C h a n g e d ( TableModelEvent e )
}) ; {
j P a n e l S p i n n e r . add ( j S p i n n e r Y ) ; i n t row = e . g e t F i r s t R o w ( ) ;
i n t column = e . getColumn ( ) ;
jLabelW . s e t L a b e l F o r ( jSpinnerW ) ; // u p d a t e o n l y i f c h a n g e t o column 0 ( Char
jLabelW . s e t T e x t ( ”W” ) ; )
j P a n e l S p i n n e r . add ( jLabelW ) ; i f ( row != −1 && column == 0 ) {
TableModel model = ( TableModel ) e .
jSpinnerW . s e t M o d e l ( new j a v a x . s w i n g . getSource () ;
SpinnerNumberModel ( ) ) ; O b j e c t d a t a = model . g e t V a l u e A t ( row ,
jSpinnerW . s e t E d i t o r ( new j a v a x . s w i n g . J S p i n n e r column ) ;
. NumberEditor ( jSpinnerW , ”#” ) ) ; S t r i n g value = ( S t r i n g ) data ;
jSpinnerW . s e t E n a b l e d ( f a l s e ) ; TessBox box = b o x e s . t o L i s t ( ) . g e t ( row ) ;
jSpinnerW . s e t P r e f e r r e d S i z e ( new j a v a . awt . box . s e t C h r s ( v a l u e ) ;
Dimension ( 4 8 , 2 2 ) ) ; jTextFieldCharacter . setText ( value ) ;
jSpinnerW . a d d C h a n g e L i s t e n e r ( new j a v a x . s w i n g . jTextFieldChar . setText ( value ) ;
event . ChangeListener ( ) { jTextFieldCodepointValue . setText ( net .
p u b l i c void stateChanged ( javax . swing . event . s o u r c e f o r g e . v i e t o c r . u t i l . U t i l s . toHex (
ChangeEvent e v t ) { value ) ) ;
jSpinnerWStateChanged ( evt ) ; updateSave ( t r u e ) ;
} }
}) ; }
j P a n e l S p i n n e r . add ( jSpinnerW ) ; }) ;
ListSelectionModel cellSelectionModel =
jLabelH . setLabelFor ( jSpinnerH ) ; jTable . getSelectionModel () ;
j L a b e l H . s e t T e x t ( ”H” ) ; cellSelectionModel . addListSelectionListener (
j P a n e l S p i n n e r . add ( j L a b e l H ) ; new L i s t S e l e c t i o n L i s t e n e r ( ) {
p u b l i c v o i d va lu eCh ang ed ( L i s t S e l e c t i o n E v e n t
j S p i n n e r H . s e t M o d e l ( new j a v a x . s w i n g . e) {
SpinnerNumberModel ( ) ) ;
j S p i n n e r H . s e t E d i t o r ( new j a v a x . s w i n g . J S p i n n e r i f ( ! e . getValueIsAdjusting () ) {
. NumberEditor ( j S p i n n e r H , ”#” ) ) ; i n t s e l e c t e d I n d e x = jTable . getSelectedRow
jSpinnerH . setEnabled ( f a l s e ) ; () ;
j S p i n n e r H . s e t P r e f e r r e d S i z e ( new j a v a . awt . i f ( s e l e c t e d I n d e x != −1) {
Dimension ( 4 8 , 2 2 ) ) ; i f ( ! ( ( JImageLabel ) jLabelImage ) .
j S p i n n e r H . a d d C h a n g e L i s t e n e r ( new j a v a x . s w i n g . i s B o x C l i c k A c t i o n ( ) ) { // n o t from image
event . ChangeListener ( ) { block c l i c k
p u b l i c void stateChanged ( javax . swing . event . boxes . d e s e l e c t A l l ( ) ;
ChangeEvent e v t ) { }
jSpinnerHStateChanged ( evt ) ; L i s t <TessBox> boxesOfCurPage = b o x e s .
} t o L i s t ( ) ; // b o x e s o f c u r r e n t page
}) ; f o r ( i n t index : jTable . getSelectedRows
j P a n e l S p i n n e r . add ( j S p i n n e r H ) ; () ) {
TessBox box = boxesOfCurPage . g e t ( i n d e x )
j T o o l B a r E d i t o r . add ( j P a n e l S p i n n e r ) ; ;
j T o o l B a r E d i t o r . add ( Box . c r e a t e H o r i z o n t a l G l u e // s e l e c t box
() ) ; box . s e t S e l e c t e d ( t r u e ) ;
j L a b e l I m a g e . s c r o l l R e c t T o V i s i b l e ( box .
j P a n e l E d i t o r . add ( j T o o l B a r E d i t o r , j a v a . awt . getRect ( ) ) ;
B o r d e r L a y o u t . PAGE START) ; }

jSplitPaneEditor . setDividerSize (2) ; /∗


∗ Code added by Anter
j P a n e l C o o r d . s e t L a y o u t ( new j a v a . awt . Aaron C u s t o d i o .
BorderLayout ( ) ) ; Highlight selected
rows
j S c r o l l P a n e C o o r d . s e t P r e f e r r e d S i z e ( new j a v a . ∗/
awt . Dimension ( 2 0 0 , 2 7 5 ) ) ; j T a b l e . getModel ( ) . setValueAt ( true ,
jTable . getSelectedRow ( ) , 5) ;
j T a b l e . s e t M o d e l ( new j a v a x . s w i n g . t a b l e .
DefaultTableModel ( jLabelImage . repaint ( ) ;
new O b j e c t [ ] [ ] { i f ( j T a b l e . g e t S e l e c t e d R o w s ( ) . l e n g t h ==
1) {
}, enableReadout ( true ) ;
new S t r i n g [ ] { // u p d a t e C h a r a c t e r f i e l d
” Char ” , ”X” , ”Y” , ” Width ” , ” H e i g h t ” , ”Ok” jTextFieldCharacter . setText (( String )
} tableModel . getValueAt ( s e l e c t e d I n d e x , 0) ) ;
) { jTextFieldChar . setText (
private s t a t i c f i n a l long jTextFieldCharacter . getText ( ) ) ;
s e r i a l V e r s i o n U I D = 1L ; jTextFieldCodepointValue . setText ( net .
C l a s s [ ] t y p e s = new C l a s s [ ] { s o u r c e f o r g e . v i e t o c r . u t i l . U t i l s . toHex (
java . lang . S t r i n g . c l a s s , java . lang . Object . jTextFieldCharacter . getText ( ) ) ) ;
c l a s s , java . lang . Object . c l a s s , java . lang . // u p d a t e su b i ma g e l a b e l
Object . c l a s s , java . lang . Object . c l a s s , Icon icon = jLabelImage . getIcon ( ) ;
java . lang . Boolean . c l a s s TessBox curBox = boxesOfCurPage . g e t (
}; selectedIndex ) ;
b o o l e a n [ ] c a n E d i t = new b o o l e a n [ ] { R e c t a n g l e r e c t = curBox . g e t R e c t ( ) ;
true , f a l s e , f a l s e , f a l s e , f a l s e , f a l s e try {
}; Image subImage = g e t S u b i m a g e ( (
BufferedImage ) ( ( ImageIcon ) i c o n ) .
p u b l i c C l a s s getColumnClass ( i n t columnIndex getImage ( ) , r e c t ) ;
) { I m a g e I c o n S c a l a b l e s u b I c o n = new
r e t u r n t y p e s [ columnIndex ] ; I m a g e I c o n S c a l a b l e ( subImage ) ;
} subIcon . setScaledFactor ( s c a l e F a c t o r ) ;

168
jLabelSubimage . s e t I c o n ( subIcon ) ; jTabbedPaneBoxData . addTab ( ”Box C o o r d i n a t e s ” ,
} catch ( Exception exc ) { jPanelCoord ) ;
// i g n o r e
} jTextAreaBoxData . s e t E d i t a b l e ( f a l s e ) ;
// mark t h i s a s t a b l e a c t i o n e v e n t t o jTextAreaBoxData . s e t C o l u m n s ( 2 0 ) ;
p r e v e n t c y c l i c f i r i n g o f e v e n t s by jTextAreaBoxData . setRows ( 5 ) ;
spinners jTextAreaBoxData . s e t M a r g i n ( new j a v a . awt .
tableSelectAction = true ; I n s e t s (8 , 8 , 2 , 2) ) ;
// u p d a t e s p i n n e r s jScrollPaneBoxData . setViewportView (
jSpinnerX . setValue ( r e c t . x ) ; jTextAreaBoxData ) ;
jSpinnerY . setValue ( r e c t . y ) ;
jSpinnerH . setValue ( r e c t . height ) ; jTabbedPaneBoxData . addTab ( ”Box Data ” ,
jSpinnerW . s e t V a l u e ( r e c t . w i d t h ) ; jScrollPaneBoxData ) ;
tableSelectAction = false ;
} else { jPanelBoxView . s e t B a c k g r o u n d ( j a v a . awt . C o l o r .
enableReadout ( f a l s e ) ; lightGray ) ;
resetReadout () ; jPanelBoxView . s e t L a y o u t ( new j a v a . awt .
} BorderLayout ( ) ) ;
} else {
boxes . d e s e l e c t A l l ( ) ; j P a n e l N o r t h C o n t a i n e r . s e t L a y o u t ( new j a v a x .
jLabelImage . repaint ( ) ; s w i n g . BoxLayout ( j P a n e l N o r t h C o n t a i n e r ,
enableReadout ( f a l s e ) ; j a v a x . s w i n g . BoxLayout . Y AXIS ) ) ;
tableSelectAction = true ;
resetReadout () ; j P a n e l C h a r . s e t B a c k g r o u n d ( j a v a . awt . C o l o r .
tableSelectAction = false ; lightGray ) ;
j P a n e l C h a r . s e t L a y o u t ( new j a v a . awt . FlowLayout
} ( j a v a . awt . FlowLayout . LEFT) ) ;

j L a b e l C o d e p o i n t . s e t T e x t ( ” Char / C o d e p o i n t : ” ) ;
j P a n e l C h a r . add ( j L a b e l C o d e p o i n t ) ;

} jTextFieldChar . setEditable ( f a l s e ) ;
} j T e x t F i e l d C h a r . setOpaque ( f a l s e ) ;
}) ; j P a n e l C h a r . add ( j T e x t F i e l d C h a r ) ;

TableCellRenderer tcr = t h i s . jTable . jTextFieldCodepointValue . setEditable ( f a l s e ) ;


getDefaultRenderer ( String . c l a s s ) ; j T e x t F i e l d C o d e p o i n t V a l u e . setOpaque ( f a l s e ) ;
DefaultTableCellRenderer dtcr = ( j P a n e l C h a r . add ( j T e x t F i e l d C o d e p o i n t V a l u e ) ;
DefaultTableCellRenderer ) tcr ;
dtcr . setHorizontalAlignment ( j P a n e l N o r t h C o n t a i n e r . add ( j P a n e l C h a r ) ;
D e f a u l t T a b l e C e l l R e n d e r e r .CENTER) ;
( ( JLabel ) jTable . getTableHeader ( ) . j P a n e l C o n t r o l s . s e t B a c k g r o u n d ( j a v a . awt . C o l o r .
getDefaultRenderer () ) . lightGray ) ;
s e t H o r i z o n t a l A l i g n m e n t ( SwingConstants . j P a n e l C o n t r o l s . s e t L a y o u t ( new j a v a . awt .
CENTER) ; FlowLayout ( j a v a . awt . FlowLayout . LEFT) ) ;
( ( JImageLabel ) t h i s . jLabelImage ) . s e t T a b l e (
jTable ) ; jLabelSpinnerMargin . setLabelFor (
j T a b l e . getInputMap ( JComponent . jSpinnerMargin ) ;
WHEN ANCESTOR OF FOCUSED COMPONENT) . put ( j L a b e l S p i n n e r M a r g i n . s e t T e x t ( ” Margins ” ) ;
K e y S t r o k e . g e t K e y S t r o k e ( ” c o n t r o l C” ) , ” j P a n e l C o n t r o l s . add ( j L a b e l S p i n n e r M a r g i n ) ;
none ” ) ;
j T a b l e . getInputMap ( JComponent . j S p i n n e r M a r g i n . s e t M o d e l ( new j a v a x . s w i n g .
WHEN ANCESTOR OF FOCUSED COMPONENT) . put ( SpinnerNumberModel ( 3 , 0 , 2 0 , 1 ) ) ;
K e y S t r o k e . g e t K e y S t r o k e ( ” c o n t r o l X” ) , ” jSpinnerMargin . setFocusable ( f a l s e ) ;
none ” ) ; (( DefaultEditor ) jSpinnerMargin . getEditor () )
j T a b l e . getInputMap ( JComponent . . getTextField () . setEditable ( f a l s e ) ;
WHEN ANCESTOR OF FOCUSED COMPONENT) . put ( (( DefaultEditor ) jSpinnerMargin . getEditor () )
K e y S t r o k e . g e t K e y S t r o k e ( ” c o n t r o l V” ) , ” . getTextField () . setFocusable ( f a l s e ) ;
none ” ) ; j S p i n n e r M a r g i n . a d d C h a n g e L i s t e n e r ( new j a v a x .
rowHeader = new RowHeaderList ( t h i s . j T a b l e ) ; swing . event . ChangeListener ( ) {
t h i s . j S c r o l l P a n e C o o r d . setRowHeaderView ( p u b l i c void stateChanged ( javax . swing . event .
rowHeader ) ; ChangeEvent e v t ) {
t h i s . j T a b l e . p u t C l i e n t P r o p e r t y ( ” JTable . jSpinnerMarginStateChanged ( evt ) ;
a u t o S t a r t s E d i t ” , B o o l e a n . FALSE) ; }
t h i s . jTable . putClientProperty ( ” }) ;
t e r m i n a t e E d i t O n F o c u s L o s t ” , B o o l e a n .TRUE) ; j P a n e l C o n t r o l s . add ( j S p i n n e r M a r g i n ) ;
t h i s . jTable . setDefaultEditor ( String . class ,
new M y T a b l e C e l l E d i t o r ( ) ) ; jLabelSpinnerScale . setLabelFor ( jSpinnerScale
);
j P a n e l C o o r d . add ( j S c r o l l P a n e C o o r d , j a v a . awt . jLabelSpinnerScale . setText ( ” Scale ” ) ;
B o r d e r L a y o u t .CENTER) ; j P a n e l C o n t r o l s . add ( Box . c r e a t e H o r i z o n t a l S t r u t
(10) ) ;
j T e x t F i e l d F i n d . s e t P r e f e r r e d S i z e ( new j a v a . awt j P a n e l C o n t r o l s . add ( j L a b e l S p i n n e r S c a l e ) ;
. Dimension ( 2 0 0 , 2 0 ) ) ;
j T e x t F i e l d F i n d . a d d A c t i o n L i s t e n e r ( new j a v a . j S p i n n e r S c a l e . s e t M o d e l ( new j a v a x . s w i n g .
awt . e v e n t . A c t i o n L i s t e n e r ( ) { SpinnerNumberModel ( 4 , 1 , 1 0 , 1 ) ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . jSpinnerScale . setFocusable ( f a l s e ) ;
ActionEvent evt ) { (( DefaultEditor ) jSpinnerScale . getEditor () ) .
jTextFieldFindActionPerformed ( evt ) ; getTextField () . setEditable ( f a l s e ) ;
} (( DefaultEditor ) jSpinnerScale . getEditor () ) .
}) ; getTextField () . setFocusable ( f a l s e ) ;
j P a n e l F i n d . add ( j T e x t F i e l d F i n d ) ; j S p i n n e r S c a l e . a d d C h a n g e L i s t e n e r ( new j a v a x .
swing . event . ChangeListener ( ) {
jButtonFind . setText ( bundle . g e t S t r i n g ( ” p u b l i c void stateChanged ( javax . swing . event .
j B u t t o n F i n d . Text ” ) ) ; // NOI18N ChangeEvent e v t ) {
jButtonFind . setToolTipText ( bundle . g e t S t r i n g ( jSpinnerScaleStateChanged ( evt ) ;
” j B u t t o n F i n d . ToolTipText ” ) ) ; // NOI18N }
j B u t t o n F i n d . a d d A c t i o n L i s t e n e r ( new j a v a . awt . }) ;
event . ActionListener ( ) { j P a n e l C o n t r o l s . add ( j S p i n n e r S c a l e ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
ActionEvent evt ) { j P a n e l N o r t h C o n t a i n e r . add ( j P a n e l C o n t r o l s ) ;
jButtonFindActionPerformed ( evt ) ;
} jPanelBoxView . add ( j P a n e l N o r t h C o n t a i n e r , java
}) ; . awt . B o r d e r L a y o u t .NORTH) ;
j P a n e l F i n d . add ( j B u t t o n F i n d ) ;
jLabelSubimage . setHorizontalAlignment ( javax .
j P a n e l C o o r d . add ( j P a n e l F i n d , j a v a . awt . s w i n g . S w i n g C o n s t a n t s .CENTER) ;
B o r d e r L a y o u t .SOUTH) ; jPanelBoxView . add ( j L a b e l S u b i m a g e , j a v a . awt .
B o r d e r L a y o u t .CENTER) ;

169
j P a n e l B u t t o n s . s e t B a c k g r o u n d ( new j a v a . awt . jToolBarGenerator . s e t R o l l o v e r ( true ) ;
Color (192 , 192 , 192) ) ;
j P a n e l 3 . s e t L a y o u t ( new j a v a . awt . FlowLayout (
j B u t t o n P r e v . s e t T e x t ( ” Prev ” ) ; j a v a . awt . FlowLayout . LEFT) ) ;
j B u t t o n P r e v . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
event . ActionListener ( ) { jButtonInput . setText ( ” Input ” ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j B u t t o n I n p u t . s e t T o o l T i p T e x t ( ” Load Text F i l e ”
ActionEvent evt ) { );
jButtonPrevActionPerformed ( evt ) ; jButtonInput . setFocusable ( f a l s e ) ;
} jButtonInput . setHorizontalTextPosition ( javax
}) ; . s w i n g . S w i n g C o n s t a n t s .CENTER) ;
j P a n e l B u t t o n s . add ( j B u t t o n P r e v ) ; jButtonInput . s e t V e r t i c a l T e x t P o s i t i o n ( javax .
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ;
j B u t t o n N e x t . s e t T e x t ( ” Next ” ) ; j B u t t o n I n p u t . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
j B u t t o n N e x t . a d d A c t i o n L i s t e n e r ( new j a v a . awt . event . ActionListener ( ) {
event . ActionListener ( ) { p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . ActionEvent evt ) {
ActionEvent evt ) { jButtonInputActionPerformed ( evt ) ;
jButtonNextActionPerformed ( evt ) ; }
} }) ;
}) ; j P a n e l 3 . add ( j B u t t o n I n p u t ) ;
j P a n e l B u t t o n s . add ( j B u t t o n N e x t ) ;
j L a b e l O u t p u t . s e t T e x t ( ” Output ” ) ;
jPanelBoxView . add ( j P a n e l B u t t o n s , j a v a . awt . j P a n e l 3 . add ( j L a b e l O u t p u t ) ;
B o r d e r L a y o u t .SOUTH) ;
j T e x t F i e l d O u p u t D i r . s e t T o o l T i p T e x t ( ”Ouput
jTabbedPaneBoxData . addTab ( ”Box View ” , Directory ”) ;
jPanelBoxView ) ; jTextFieldOuputDir . setEnabled ( f a l s e ) ;
j T e x t F i e l d O u p u t D i r . s e t P r e f e r r e d S i z e ( new j a v a
j S p l i t P a n e E d i t o r . setLeftComponent ( . awt . Dimension ( 1 8 0 , 2 4 ) ) ;
jTabbedPaneBoxData ) ; j P a n e l 3 . add ( j T e x t F i e l d O u p u t D i r ) ;

jLabelImage . s e t V e r t i c a l A l i g n m e n t ( javax . swing jButtonBrowseOutputDir . setText ( ” . . . ” ) ;


. S w i n g C o n s t a n t s .TOP) ; jButtonBrowseOutputDir . setToolTipText ( ”
jScrollPaneImage . setViewportView ( jLabelImage Browse ” ) ;
); j B u t t o n B r o w s e O u t p u t D i r . s e t P r e f e r r e d S i z e ( new
j a v a . awt . Dimension ( 2 4 , 2 3 ) ) ;
j S p l i t P a n e E d i t o r . setRightComponent ( j B u t t o n B r o w s e O u t p u t D i r . a d d A c t i o n L i s t e n e r ( new
jScrollPaneImage ) ; j a v a . awt . e v e n t . A c t i o n L i s t e n e r ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j P a n e l E d i t o r . add ( j S p l i t P a n e E d i t o r , j a v a . awt . ActionEvent evt ) {
B o r d e r L a y o u t .CENTER) ; jButtonBrowseOutputDirActionPerformed ( evt )
;
j P a n e l S t a t u s . add ( j L a b e l S t a t u s ) ; }
j P a n e l S t a t u s . add ( j L a b e l P a g e N b r ) ; }) ;
t h i s . j P a n e l S t a t u s . add ( Box . j P a n e l 3 . add ( j B u t t o n B r o w s e O u t p u t D i r ) ;
createHorizontalStrut (10) ) ;
j T e x t F i e l d P r e f i x . setToolTipText ( ” P r e f i x (
j B u t t o n P r e v P a g e . s e t I c o n ( new j a v a x . s w i n g . Language Code ) ” ) ;
ImageIcon ( g e t C l a s s ( ) . getResource ( ”/ net / j T e x t F i e l d P r e f i x . s e t P r e f e r r e d S i z e ( new j a v a .
s o u r c e f o r g e / t e s s b o x e d i t o r / i c o n s / PrevPage . awt . Dimension ( 3 8 , 2 4 ) ) ;
g i f ” ) ) ) ; // NOI18N j P a n e l 3 . add ( j T e x t F i e l d P r e f i x ) ;
jButtonPrevPage . setToolTipText ( bundle .
g e t S t r i n g ( ” j B u t t o n P r e v P a g e . ToolTipText ” ) ) jTextFieldFileName . setToolTipText ( ” Filename ”
; // NOI18N );
jButtonPrevPage . s e t F o c u s a b l e ( f a l s e ) ; j T e x t F i e l d F i l e N a m e . s e t P r e f e r r e d S i z e ( new j a v a
jButtonPrevPage . s e t H o r i z o n t a l T e x t P o s i t i o n ( . awt . Dimension ( 1 4 0 , 2 4 ) ) ;
j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ; j P a n e l 3 . add ( j T e x t F i e l d F i l e N a m e ) ;
jButtonPrevPage . s e t V e r t i c a l T e x t P o s i t i o n (
j a v a x . s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j B u t t o n F o n t . s e t T e x t ( ” Font ” ) ;
j B u t t o n P r e v P a g e . a d d A c t i o n L i s t e n e r ( new j a v a . j B u t t o n F o n t . s e t T o o l T i p T e x t ( ” S e l e c t Font ” ) ;
awt . e v e n t . A c t i o n L i s t e n e r ( ) { jButtonFont . s e t F o c u s a b l e ( f a l s e ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . jButtonFont . s e t H o r i z o n t a l T e x t P o s i t i o n ( javax .
ActionEvent evt ) { s w i n g . S w i n g C o n s t a n t s .CENTER) ;
jButtonPrevPageActionPerformed ( evt ) ; jButtonFont . s e t V e r t i c a l T e x t P o s i t i o n ( javax .
} s w i n g . S w i n g C o n s t a n t s .BOTTOM) ;
}) ; j B u t t o n F o n t . a d d A c t i o n L i s t e n e r ( new j a v a . awt .
j P a n e l S t a t u s . add ( j B u t t o n P r e v P a g e ) ; event . ActionListener ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j B u t t o n N e x t P a g e . s e t I c o n ( new j a v a x . s w i n g . ActionEvent evt ) {
ImageIcon ( g e t C l a s s ( ) . getResource ( ”/ net / jButtonFontActionPerformed ( evt ) ;
s o u r c e f o r g e / t e s s b o x e d i t o r / i c o n s / NextPage . }
g i f ” ) ) ) ; // NOI18N }) ;
jButtonNextPage . setToolTipText ( bundle . j P a n e l 3 . add ( j B u t t o n F o n t ) ;
g e t S t r i n g ( ” j B u t t o n N e x t P a g e . ToolTipText ” ) )
; // NOI18N j C h e c k B o x A n t i A l i a s i n g . s e t T e x t ( ” Anti−A l i a s i n g
jButtonNextPage . s e t F o c u s a b l e ( f a l s e ) ; ”) ;
jButtonNextPage . s e t H o r i z o n t a l T e x t P o s i t i o n ( j P a n e l 3 . add ( j C h e c k B o x A n t i A l i a s i n g ) ;
j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ;
jButtonNextPage . s e t V e r t i c a l T e x t P o s i t i o n ( jLabelNoise . setText ( ” Noise ” ) ;
j a v a x . s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j P a n e l 3 . add ( j L a b e l N o i s e ) ;
j B u t t o n N e x t P a g e . a d d A c t i o n L i s t e n e r ( new j a v a .
awt . e v e n t . A c t i o n L i s t e n e r ( ) { j S p i n n e r N o i s e . s e t M o d e l ( new j a v a x . s w i n g .
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . SpinnerNumberModel ( 0 , 0 , 5 , 1 ) ) ;
ActionEvent evt ) { j S p i n n e r N o i s e . s e t T o o l T i p T e x t ( ”Add N o i s e t o
jButtonNextPageActionPerformed ( evt ) ; Image ” ) ;
} j S p i n n e r N o i s e . setName ( ” N o i s e ” ) ; // NOI18N
}) ; j S p i n n e r N o i s e . s e t P r e f e r r e d S i z e ( new j a v a . awt .
j P a n e l S t a t u s . add ( j B u t t o n N e x t P a g e ) ; Dimension ( 4 7 , 2 2 ) ) ;
j P a n e l 3 . add ( j S p i n n e r N o i s e ) ;
j P a n e l E d i t o r . add ( j P a n e l S t a t u s , j a v a . awt .
B o r d e r L a y o u t .SOUTH) ; jLabelTracking . setText ( ” Letter Tracking ” ) ;
j P a n e l 3 . add ( j L a b e l T r a c k i n g ) ;
jTabbedPaneMain . addTab ( ”Box E d i t o r ” ,
jPanelEditor ) ; j S p i n n e r T r a c k i n g . s e t M o d e l ( new j a v a x . s w i n g .
SpinnerNumberModel ( F l o a t . v a l u e O f ( 0 . 0 f ) ,
jPanelTIFFBox . s e t L a y o u t ( new j a v a . awt . F l o a t . v a l u e O f ( −0.04 f ) , F l o a t . v a l u e O f ( 0 . 1 f
BorderLayout ( ) ) ; ) , Float . valueOf ( 0 . 0 1 f ) ) ) ;

170
jSpinnerTracking . setToolTipText ( ” Adjust j M e n u F i l e . Text ” ) ) ; // NOI18N
L e t t e r Tracking ” ) ;
j S p i n n e r T r a c k i n g . s e t P r e f e r r e d S i z e ( new j a v a . jMenuItemOpen . s e t A c c e l e r a t o r ( j a v a x . s w i n g .
awt . Dimension ( 6 4 , 2 2 ) ) ; K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
j S p i n n e r T r a c k i n g . a d d C h a n g e L i s t e n e r ( new j a v a x KeyEvent . VK O , j a v a . awt . e v e n t . I n p u t E v e n t .
. swing . event . ChangeListener ( ) { CTRL MASK) ) ;
p u b l i c void stateChanged ( javax . swing . event . jMenuItemOpen . setMnemonic ( j a v a . u t i l .
ChangeEvent e v t ) { ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
jSpinnerTrackingStateChanged ( evt ) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
} jMenuItemOpen . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
}) ; jMenuItemOpen . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
j P a n e l 3 . add ( j S p i n n e r T r a c k i n g ) ; jMenuItemOpen . Text ” ) ) ; // NOI18N
jMenuItemOpen . a d d A c t i o n L i s t e n e r ( new j a v a . awt
jLabelW1 . s e t T e x t ( ”W” ) ; . event . ActionListener ( ) {
j P a n e l 3 . add ( jLabelW1 ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
ActionEvent evt ) {
jSpinnerW1 . s e t M o d e l ( new j a v a x . s w i n g . jMenuItemOpenActionPerformed ( e v t ) ;
SpinnerNumberModel ( 2 5 5 0 , 6 0 0 , 2 5 5 0 , 1 0 ) ) ; }
jSpinnerW1 . s e t T o o l T i p T e x t ( ” Image Width ” ) ; }) ;
jSpinnerW1 . s e t E d i t o r ( new j a v a x . s w i n g . j M e n u F i l e . add ( jMenuItemOpen ) ;
J S p i n n e r . NumberEditor ( jSpinnerW1 , ”#” ) ) ;
jSpinnerW1 . s e t P r e f e r r e d S i z e ( new j a v a . awt . jMenuItemSave . s e t A c c e l e r a t o r ( j a v a x . s w i n g .
Dimension ( 6 3 , 2 2 ) ) ; K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
j P a n e l 3 . add ( jSpinnerW1 ) ; KeyEvent . VK S , j a v a . awt . e v e n t . I n p u t E v e n t .
CTRL MASK) ) ;
j L a b e l H 1 . s e t T e x t ( ”H” ) ; jMenuItemSave . setMnemonic ( j a v a . u t i l .
j P a n e l 3 . add ( j L a b e l H 1 ) ; ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
j S p i n n e r H 1 . s e t M o d e l ( new j a v a x . s w i n g . jMenuItemSave . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
SpinnerNumberModel ( 3 3 0 0 , 4 0 0 , 3 3 0 0 , 1 0 ) ) ; jMenuItemSave . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
j S p i n n e r H 1 . s e t T o o l T i p T e x t ( ” Image H e i g h t ” ) ; jMenuItemSave . Text ” ) ) ; // NOI18N
j S p i n n e r H 1 . s e t E d i t o r ( new j a v a x . s w i n g . jMenuItemSave . a d d A c t i o n L i s t e n e r ( new j a v a . awt
J S p i n n e r . NumberEditor ( j S p i n n e r H 1 , ”#” ) ) ; . event . ActionListener ( ) {
j S p i n n e r H 1 . s e t P r e f e r r e d S i z e ( new j a v a . awt . p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
Dimension ( 6 3 , 2 2 ) ) ; ActionEvent evt ) {
j P a n e l 3 . add ( j S p i n n e r H 1 ) ; jMenuItemSaveActionPerformed ( evt ) ;
}
jButtonGenerate . setText ( ” Generate ” ) ; }) ;
jButtonGenerate . setToolTipText ( ” Generate j M e n u F i l e . add ( jMenuItemSave ) ;
TIFF/Box” ) ;
jButtonGenerate . setFocusable ( f a l s e ) ; jMenuItemSaveAs . s e t A c c e l e r a t o r ( j a v a x . s w i n g .
jButtonGenerate . s e t H o r i z o n t a l T e x t P o s i t i o n ( K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
j a v a x . s w i n g . S w i n g C o n s t a n t s .CENTER) ; KeyEvent . VK S , j a v a . awt . e v e n t . I n p u t E v e n t .
jButtonGenerate . s e t V e r t i c a l T e x t P o s i t i o n ( SHIFT MASK | j a v a . awt . e v e n t . I n p u t E v e n t .
j a v a x . s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; CTRL MASK) ) ;
j B u t t o n G e n e r a t e . a d d A c t i o n L i s t e n e r ( new j a v a . jMenuItemSaveAs . setMnemonic ( j a v a . u t i l .
awt . e v e n t . A c t i o n L i s t e n e r ( ) { ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
ActionEvent evt ) { jMenuItemSaveAs . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
jButtonGenerateActionPerformed ( evt ) ; jMenuItemSaveAs . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
} jMenuItemSaveAs . Text ” ) ) ; // NOI18N
}) ; jMenuItemSaveAs . a d d A c t i o n L i s t e n e r ( new j a v a .
j P a n e l 3 . add ( j B u t t o n G e n e r a t e ) ; awt . e v e n t . A c t i o n L i s t e n e r ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jButtonClear . setText ( ” Clear ” ) ; ActionEvent evt ) {
jButtonClear . setToolTipText ( ” Clear Textarea ” jMenuItemSaveAsActionPerformed ( ev t ) ;
); }
jButtonClear . setFocusable ( f a l s e ) ; }) ;
jButtonClear . setHorizontalTextPosition ( javax j M e n u F i l e . add ( jMenuItemSaveAs ) ;
. s w i n g . S w i n g C o n s t a n t s .CENTER) ; j M e n u F i l e . add ( j S e p a r a t o r R e c e n t F i l e s ) ;
jButtonClear . s e t V e r t i c a l T e x t P o s i t i o n ( javax .
s w i n g . S w i n g C o n s t a n t s .BOTTOM) ; j M e n u R e c e n t F i l e s . setMnemonic ( j a v a . u t i l .
j B u t t o n C l e a r . a d d A c t i o n L i s t e n e r ( new j a v a . awt . ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
event . ActionListener ( ) { / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j M e n u R e c e n t F i l e s . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
ActionEvent evt ) { jMenuRecentFiles . setText ( bundle . g e t S t r i n g ( ”
jButtonClearActionPerformed ( evt ) ; j M e n u R e c e n t F i l e s . Text ” ) ) ; // NOI18N
} j M e n u F i l e . add ( j M e n u R e c e n t F i l e s ) ;
}) ; j M e n u F i l e . add ( j S e p a r a t o r E x i t ) ;
j P a n e l 3 . add ( j B u t t o n C l e a r ) ;
jMenuItemExit . setMnemonic ( j a v a . u t i l .
j T o o l B a r G e n e r a t o r . add ( j P a n e l 3 ) ; ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
jPanelTIFFBox . add ( j T o o l B a r G e n e r a t o r , java . jMenuItemExit . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
awt . B o r d e r L a y o u t . PAGE START) ; jMenuItemExit . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
jMenuItemExit . Text ” ) ) ; // NOI18N
jTextAreaInput . setColumns ( 2 0 ) ; jMenuItemExit . a d d A c t i o n L i s t e n e r ( new j a v a . awt
jTextAreaInput . setLineWrap ( t r u e ) ; . event . ActionListener ( ) {
j T e x t A r e a I n p u t . setRows ( 5 ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j T e x t A r e a I n p u t . setWrapStyleWord ( t r u e ) ; ActionEvent evt ) {
j T e x t A r e a I n p u t . s e t M a r g i n ( new j a v a . awt . I n s e t s jMenuItemExitActionPerformed ( evt ) ;
(5 , 5 , 2 , 2) ) ; }
jScrollPaneText . setViewportView ( }) ;
jTextAreaInput ) ; j M e n u F i l e . add ( jMenuItemExit ) ;

jPanelTIFFBox . add ( j S c r o l l P a n e T e x t , j a v a . awt . jMenuBar . add ( j M e n u F i l e ) ;


B o r d e r L a y o u t .CENTER) ;
jMenuEdit . setMnemonic ( j a v a . u t i l .
// jTabbedPaneMain . addTab ( ” TIFF/Box G e n e r a t o r ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
” , jPanelTIFFBox ) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” jMenuEdit
. Mnemonic ” ) . c h a r A t ( 0 ) ) ;
g e t C o n t e n t P a n e ( ) . add ( jTabbedPaneMain , java . jMenuEdit . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
awt . B o r d e r L a y o u t .CENTER) ; jMenuEdit . Text ” ) ) ; // NOI18N

j M e n u F i l e . setMnemonic ( j a v a . u t i l . jMenuItemMerge . s e t A c c e l e r a t o r ( j a v a x . s w i n g .
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” j M e n u F i l e KeyEvent . VK C , j a v a . awt . e v e n t . I n p u t E v e n t .
. Mnemonic ” ) . c h a r A t ( 0 ) ) ; CTRL MASK) ) ;
jMenuFile . setText ( bundle . g e t S t r i n g ( ” jMenuItemMerge . setMnemonic ( j a v a . u t i l .

171
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
jMenuItemMerge . Mnemonic ” ) . c h a r A t ( 0 ) ) ; jMenuLookAndFeel . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
jMenuItemMerge . s e t T e x t ( b u n d l e . g e t S t r i n g ( ” jMenuLookAndFeel . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
jMenuItemMerge . Text ” ) ) ; // NOI18N jMenuLookAndFeel . Text ” ) ) ; // NOI18N
jMenuItemMerge . a d d A c t i o n L i s t e n e r ( new j a v a . j M e n u S e t t i n g s . add ( jMenuLookAndFeel ) ;
awt . e v e n t . A c t i o n L i s t e n e r ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . jMenuBar . add ( j M e n u S e t t i n g s ) ;
ActionEvent evt ) {
jMenuItemMergeActionPerformed ( e v t ) ; jMenuTools . setMnemonic ( j a v a . u t i l .
} ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
}) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
jMenuEdit . add ( jMenuItemMerge ) ; jMenuTools . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
jMenuTools . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
jMenuItemSplit . s e t A c c e l e r a t o r ( javax . swing . jMenuTools . Text ” ) ) ; // NOI18N
K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
KeyEvent . VK X , j a v a . awt . e v e n t . I n p u t E v e n t . jMenuItemMergeTiff . s e t A c c e l e r a t o r ( javax .
CTRL MASK) ) ; s w i n g . K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt .
j M e n u I t e m S p l i t . setMnemonic ( j a v a . u t i l . e v e n t . KeyEvent . VK M, j a v a . awt . e v e n t .
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e I n p u t E v e n t . CTRL MASK) ) ;
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” j M e n u I t e m M e r g e T i f f . setMnemonic ( j a v a . u t i l .
j M e n u I t e m S p l i t . Mnemonic ” ) . c h a r A t ( 0 ) ) ; ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
jMenuItemSplit . setText ( bundle . g e t S t r i n g ( ” / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
j M e n u I t e m S p l i t . Text ” ) ) ; // NOI18N j M e n u I t e m M e r g e T i f f . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
j M e n u I t e m S p l i t . a d d A c t i o n L i s t e n e r ( new j a v a . jMenuItemMergeTiff . setText ( bundle . g e t S t r i n g (
awt . e v e n t . A c t i o n L i s t e n e r ( ) { ” j M e n u I t e m M e r g e T i f f . Text ” ) ) ; // NOI18N
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j M e n u I t e m M e r g e T i f f . a d d A c t i o n L i s t e n e r ( new
ActionEvent evt ) { j a v a . awt . e v e n t . A c t i o n L i s t e n e r ( ) {
jMenuItemSplitActionPerformed ( evt ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
} ActionEvent evt ) {
}) ; jMenuItemMergeTiffActionPerformed ( evt ) ;
jMenuEdit . add ( j M e n u I t e m S p l i t ) ; }
}) ;
jMenuItemInsert . s e t A c c e l e r a t o r ( javax . swing . jMenuTools . add ( j M e n u I t e m M e r g e T i f f ) ;
K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
KeyEvent . VK V , j a v a . awt . e v e n t . I n p u t E v e n t . jMenuItemSplitTiff . s e t A c c e l e r a t o r ( javax .
CTRL MASK) ) ; s w i n g . K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt .
j M e n u I t e m I n s e r t . setMnemonic ( j a v a . u t i l . e v e n t . KeyEvent . VK L , j a v a . awt . e v e n t .
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e I n p u t E v e n t . CTRL MASK) ) ;
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” j M e n u I t e m S p l i t T i f f . setMnemonic ( j a v a . u t i l .
j M e n u I t e m I n s e r t . Mnemonic ” ) . c h a r A t ( 0 ) ) ; ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
jMenuItemInsert . setText ( bundle . g e t S t r i n g ( ” / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
j M e n u I t e m I n s e r t . Text ” ) ) ; // NOI18N j M e n u I t e m S p l i t T i f f . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
j M e n u I t e m I n s e r t . a d d A c t i o n L i s t e n e r ( new j a v a . j M e n uI t e m S p l i tT i f f . setText ( bundle . g e t S t r i n g (
awt . e v e n t . A c t i o n L i s t e n e r ( ) { ” j M e n u I t e m S p l i t T i f f . Text ” ) ) ; // NOI18N
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . j M e n u I t e m S p l i t T i f f . a d d A c t i o n L i s t e n e r ( new
ActionEvent evt ) { j a v a . awt . e v e n t . A c t i o n L i s t e n e r ( ) {
jMenuItemInsertActionPerformed ( evt ) ; p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
} ActionEvent evt ) {
}) ; jMenuItemSplitTiffActionPerformed ( evt ) ;
jMenuEdit . add ( j M e n u I t e m I n s e r t ) ; }
}) ;
jMenuItemDelete . s e t A c c e l e r a t o r ( javax . swing . jMenuTools . add ( j M e n u I t e m S p l i t T i f f ) ;
K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t .
KeyEvent . VK DELETE, 0 ) ) ; jMenuBar . add ( jMenuTools ) ;
j M e n u I t e m D e l e t e . setMnemonic ( j a v a . u t i l .
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e jMenuHelp . setMnemonic ( j a v a . u t i l .
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
j M e n u I t e m D e l e t e . Mnemonic ” ) . c h a r A t ( 0 ) ) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” jMenuHelp
jMenuItemDelete . setText ( bundle . g e t S t r i n g ( ” . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
j M e n u I t e m D e l e t e . Text ” ) ) ; // NOI18N jMenuHelp . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
j M e n u I t e m D e l e t e . a d d A c t i o n L i s t e n e r ( new j a v a . jMenuHelp . Text ” ) ) ; // NOI18N
awt . e v e n t . A c t i o n L i s t e n e r ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . jMenuItemHelp . setMnemonic ( j a v a . u t i l .
ActionEvent evt ) { ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
jMenuItemDeleteActionPerformed ( evt ) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
} jMenuItemHelp . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
}) ; jMenuItemHelp . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
jMenuEdit . add ( j M e n u I t e m D e l e t e ) ; jMenuItemHelp . Text ” ) ) ; // NOI18N
jMenuItemHelp . a d d A c t i o n L i s t e n e r ( new j a v a . awt
jMenuBar . add ( jMenuEdit ) ; . event . ActionListener ( ) {
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
j M e n u S e t t i n g s . setMnemonic ( j a v a . u t i l . ActionEvent evt ) {
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e jMenuItemHelpActionPerformed ( evt ) ;
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” }
j M e n u S e t t i n g s . Mnemonic ” ) . c h a r A t ( 0 ) ) ; }) ;
jMenuSettings . setText ( ” S e t t i n g s ” ) ; jMenuHelp . add ( jMenuItemHelp ) ;
jMenuHelp . add ( j S e p a r a t o r A b o u t ) ;
jMenuItemFont . s e t A c c e l e r a t o r ( j a v a x . s w i n g .
K e y S t r o k e . g e t K e y S t r o k e ( j a v a . awt . e v e n t . jMenuItemAbout . setMnemonic ( j a v a . u t i l .
KeyEvent . VK T , j a v a . awt . e v e n t . I n p u t E v e n t . ResourceBundle . getBundle ( ” net / s o u r c e f o r g e
CTRL MASK) ) ; / t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ”
jMenuItemFont . setMnemonic ( j a v a . u t i l . jMenuItemAbout . Mnemonic ” ) . c h a r A t ( 0 ) ) ;
ResourceBundle . getBundle ( ” net / s o u r c e f o r g e jMenuItemAbout . s e t T e x t ( b u n d l e . g e t S t r i n g ( ”
/ t e s s b o x e d i t o r / Gui ” ) . g e t S t r i n g ( ” jMenuItemAbout . Text ” ) ) ; // NOI18N
jMenuItemFont . Mnemonic ” ) . c h a r A t ( 0 ) ) ; jMenuItemAbout . a d d A c t i o n L i s t e n e r ( new j a v a .
jMenuItemFont . s e t T e x t ( b u n d l e . g e t S t r i n g ( ” awt . e v e n t . A c t i o n L i s t e n e r ( ) {
jMenuItemFont . Text ” ) ) ; // NOI18N p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t .
jMenuItemFont . a d d A c t i o n L i s t e n e r ( new j a v a . awt ActionEvent evt ) {
. event . ActionListener ( ) { jMenuItemAboutActionPerformed ( e v t ) ;
p u b l i c v o i d a c t i o n P e r f o r m e d ( j a v a . awt . e v e n t . }
ActionEvent evt ) { }) ;
jMenuItemFontActionPerformed ( evt ) ; jMenuHelp . add ( jMenuItemAbout ) ;
}
}) ; jMenuBar . add ( jMenuHelp ) ;
j M e n u S e t t i n g s . add ( jMenuItemFont ) ;
j M e n u S e t t i n g s . add ( j S e p a r a t o r L A F ) ; setJMenuBar ( jMenuBar ) ;

jMenuLookAndFeel . setMnemonic ( j a v a . u t i l . KeyboardFocusManager manager =

172
KeyboardFocusManager . jButtonNext . doClick ( ) ;
getCurrentKeyboardFocusManager ( ) ; } e l s e i f ( c == ’ x ’ ) {
manager . a d d K e y E v e n t D i s p a t c h e r ( new jTextFieldCharacter . requestFocus () ;
KeyEventDispatcher ( ) { } else {
return f a l s e ;
p r i v a t e void inc ( JSpinner s ) { }
i f ( s == j S p i n n e r X | | s == j S p i n n e r Y ) {
i f (! invertControls ) { return true ;
s . s e t V a l u e ( Math . max ( 0 , ( ( I n t e g e r ) s . }
getValue ( ) ) − movementMultiplier ) ) ; }) ;
} else { pack ( ) ;
s . setValue ( ( ( I n t e g e r ) s . getValue ( ) ) +
movementMultiplier ) ;
} } // </ e d i t o r −f o l d >//GEN−END: i n i t C o m p o n e n t s
} else {
s . setValue ( ( ( I n t e g e r ) s . getValue ( ) ) + p r i v a t e v o i d jMenuItemOpenActionPerformed (
movementMultiplier ) ; j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
} FIRST : e v e n t j M e n u I t e m O p e n A c t i o n P e r f o r m e d
} // Old s o u r c e c o d e
/∗
@SuppressWarnings ( ” unused ” ) i f ( jFileChooserInputImage .
p r i v a t e v o i d i n c ( J S p i n n e r s , i n t max ) { showOpenDialog ( t h i s ) ==
i f ( ( s == j S p i n n e r X | | s == j S p i n n e r Y ) && J F i l e C h o o s e r . APPROVE OPTION) {
! invertControls ) { currentDirectory =
s . s e t V a l u e ( Math . max ( 0 , ( ( I n t e g e r ) s . jFileChooserInputImage .
getValue ( ) ) − movementMultiplier ) ) ; g e t C u r r e n t D i r e c t o r y ( ) . getPath
} else { () ;
s . setValue ( ( ( I n t e g e r ) s . getValue ( ) ) + openFile ( jFileChooserInputImage .
movementMultiplier ) ; getSelectedFile () ) ;
}
} for ( int i = 0; i < f i l e F i l t e r s .
l e n g t h ; i ++) {
p r i v a t e void dec ( JSpinner s ) { i f ( f i l e F i l t e r s [ i ] ==
i f ( ( s == j S p i n n e r X | | s == j S p i n n e r Y ) && jFileChooserInputImage .
! invertControls ) { getFileFilter () ) {
s . setValue ( ( ( I n t e g e r ) s . getValue ( ) ) + filterIndex = i ;
movementMultiplier ) ; break ;
} else { }
s . s e t V a l u e ( Math . max ( 0 , ( ( I n t e g e r ) s . }
getValue ( ) ) − movementMultiplier ) ) ; }
} ∗/
}
// Code by Aaron
@O verr ide i f ( c u r r e n t I n d e x == i n p u t T i f f s . l e n g t h ) {
p u b l i c b o o l e a n d i s p a t c h K e y E v e n t ( KeyEvent e ) // T r a i n i f l a s t i n d e x i s r e a c h e d
{ saveBoxFile () ;
System . e x i t ( 0 ) ;
i f ( e . g e t I D ( ) != KeyEvent . KEY TYPED) {
return f a l s e ; } else {
} openFile ( inputTiffs [ currentIndex ] ) ;
c u r r e n t I n d e x ++;
Component f o c u s O w n e r =
KeyboardFocusManager . if ( c u r r e n t I n d e x == i n p u t T i f f s . l e n g t h ) {
getCurrentKeyboardFocusManager ( ) . t h i s . jButtonOpen . s e t T e x t ( ” F i n i s h ” ) ;
getFocusOwner ( ) ; }

i f ( ( focusOwner i n s t a n c e o f JSpinner ) }
| | ( focusOwner i n s t a n c e o f J T e x t F i e l d ) ) { } //GEN−LAST :
return f a l s e ; event jMenuItemOpenActionPerformed
} public void openFile ( f i n a l F i l e s e l e c t e d F i l e )
{
i f ( j L a b e l C h a r a c t e r . hasFocus ( ) ) { i f (! selectedFile . exists () ) {
return f a l s e ; JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , b u n d l e .
} g e t S t r i n g ( ” F i l e n o t e x i s t ” ) , APP NAME,
JOptionPane . ERROR MESSAGE) ;
i f ( ! jPanelBoxView . i s S h o w i n g ( ) ) { return ;
return f a l s e ; }
} i f ( ! promptToSave ( ) ) {
return ;
i f ( e . isShiftDown () ) { }
movementMultiplier = 10;
} // j L a b e l S t a t u s . setText ( bundle .
else { g e t S t r i n g (” Loading image . . . ” ) ) ;
movementMultiplier = 1 ; getGlassPane ( ) . s e t C u r s o r ( Cursor .
g e t P r e d e f i n e d C u r s o r ( C u r s o r . WAIT CURSOR) ) ;
} getGlassPane ( ) . s e t V i s i b l e ( true ) ;

c h a r c = C h a r a c t e r . toLowerCase ( e . SwingWorker<Void , Void> loadWorker = new


getKeyChar ( ) ) ; SwingWorker<Void , Void >() {

i f ( c == ’w ’ ) { @O verr ide
inc ( jSpinnerY ) ; p r o t e c t e d Void doInBackground ( ) t h r o w s
} e l s e i f ( c == ’ s ’ ) { Exception {
dec ( jSpinnerY ) ; readImageFile ( s e l e c t e d F i l e ) ;
} e l s e i f ( c == ’ d ’ ) { updateMRUList ( s e l e c t e d F i l e . g e t P a t h ( ) ) ;
dec ( jSpinnerX ) ; i n t l a s t D o t = s e l e c t e d F i l e . getName ( ) .
} e l s e i f ( c == ’ a ’ ) { lastIndexOf (” . ”) ;
inc ( jSpinnerX ) ; b o x F i l e = new F i l e ( s e l e c t e d F i l e .
} e l s e i f ( c == ’ q ’ ) { g e t P a r e n t F i l e ( ) , s e l e c t e d F i l e . getName ( ) .
d e c ( jSpinnerW ) ; s u b s t r i n g ( 0 , l a s t D o t ) + ” . box ” ) ;
} e l s e i f ( c == ’ e ’ ) { readBoxFile ( boxFile ) ;
i n c ( jSpinnerW ) ; return null ;
} e l s e i f ( c == ’ r ’ ) { }
dec ( jSpinnerH ) ;
} e l s e i f ( c == ’ f ’ ) { @O verr ide
inc ( jSpinnerH ) ; p r o t e c t e d v o i d done ( ) {
} e l s e i f ( c == ’ , ’ ) { // j L a b e l S t a t u s . setText ( bundle .
jButtonPrev . doClick ( ) ; g e t S t r i n g (” Loading completed ”) ) ;
} e l s e i f ( c == ’ . ’ ) { getGlassPane ( ) . s e t C u r s o r ( Cursor .

173
g e t P r e d e f i n e d C u r s o r ( C u r s o r . DEFAULT CURSOR } else {
)); page = 0 ; // T e s s 2 . 0 x f o r m a t
getGlassPane ( ) . s e t V i s i b l e ( f a l s e ) ; }
} i f ( page > c u r P a g e ) {
}; s t a r t B o x I n d e x = i ; // mark b e g i n o f
n e x t page
loa dWorker . e x e c u t e ( ) ; break ;
} }
boxCol . add ( new TessBox ( c h r s , new
void readImageFile ( F i l e s e l e c t e d F i l e ) { R e c t a n g l e ( x , y , w, h ) , page ) ) ;
try { }
i m a g e L i s t = ImageIOHelper . g e t I m a g e L i s t ( boxPages . add ( boxCol ) ; // add t h e l a s t
selectedFile ) ; page
i f ( i m a g e L i s t == n u l l ) { }
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , b u n d l e loadTable ( ) ;
. g e t S t r i n g ( ” C a n n o t l o a d i m a g e ” ) , APP NAME, updateSave ( f a l s e ) ;
JOptionPane . ERROR MESSAGE) ; } c a t c h ( OutOfMemoryError oome ) {
return ; l o g g e r . l o g ( L e v e l . SEVERE, oome . g e t M e s s a g e ( )
} , oome ) ;
imageIndex = 0 ; JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , oome .
loadImage ( ) ; g e t M e s s a g e ( ) , ”Out−Of−Memory E x c e p t i o n ” ,
t h i s . jScrollPaneImage . getViewport ( ) . JOptionPane . ERROR MESSAGE) ;
s e t V i e w P o s i t i o n ( new P o i n t ( 0 , 0 ) ) ; } catch ( IOException |
t h i s . s e t T i t l e (APP NAME + ” − ” + NumberFormatException e ) {
s e l e c t e d F i l e . getName ( ) ) ; l o g g e r . l o g ( L e v e l . SEVERE, e . g e t M e s s a g e ( ) , e
} c a t c h ( OutOfMemoryError oome ) { );
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , oome . i f ( e . g e t M e s s a g e ( ) != n u l l ) {
g e t M e s s a g e ( ) , ”Out−Of−Memory E x c e p t i o n ” , JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , e .
JOptionPane . ERROR MESSAGE) ; g e t M e s s a g e ( ) , APP NAME, JOptionPane .
} catch ( IOException | HeadlessException e ) ERROR MESSAGE) ;
{ }
l o g g e r . l o g ( L e v e l . SEVERE, e . g e t M e s s a g e ( ) , e ) }
; } else {
i f ( e . g e t M e s s a g e ( ) != n u l l ) { // c l e a r t a b l e and box d i s p l a y
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , e . tableModel . setDataVector ( ( Object [ ] [ ] ) null ,
g e t M e s s a g e ( ) , APP NAME, JOptionPane . ( Object [ ] ) n u l l ) ;
ERROR MESSAGE) ; ( ( JImageLabel ) t h i s . jLabelImage ) . setBoxes (
} null ) ;
} jTextAreaBoxData . s e t T e x t ( n u l l ) ;
} }
}
void readBoxFile ( f i n a l F i l e boxFile ) {
i f ( boxFile . e x i s t s () ) { void loadTable ( ) {
try { i f ( ! t h i s . boxPages . isEmpty ( ) ) {
boxPages . c l e a r ( ) ; b o x e s = t h i s . boxPages . g e t ( i m a g e I n d e x ) ;
tableModel . setDataVector ( boxes .
// l o a d i n t o t e x t a r e a f i r s t g e t T a b l e D a t a L i s t ( ) . t o A r r a y ( new S t r i n g
t r y ( B u f f e r e d R e a d e r i n = new [ 0 ] [ 5 ] ) , h e a d e r s ) ; // e d i t e d by Aaron
B u f f e r e d R e a d e r ( new I n p u t S t r e a m R e a d e r ( new ( ( JImageLabel ) t h i s . jLabelImage ) . setBoxes (
F i l e I n p u t S t r e a m ( b o x F i l e ) , ”UTF8” ) ) ) { boxes ) ;
t h i s . jTextAreaBoxData . r e a d ( i n , n u l l ) ; }
} j T a b l e . getColumnModel ( ) . removeColumn ( j T a b l e .
getColumnModel ( ) . getColumn ( 5 ) ) ;
// l o a d i n t o c o o r d i n a t e t a b }
S t r i n g [ ] b o x d a t a = t h i s . jTextAreaBoxData .
g e t T e x t ( ) . s p l i t ( ” \\n” ) ; /∗ ∗
i f ( boxdata . l e n g t h > 0) { ∗ Displays a d i a l o g to d i s c a r d changes .
// i f o n l y 5 f i e l d s , i t ’ s T e s s 2 . 0 x ∗
format ∗ @return f a l s e i f u s e r c a n c e l e d or
i s T e s s 2 0 F o r m a t = b o x d a t a [ 0 ] . s p l i t ( ” \\ s+” discard , true e l s e
) . l e n g t h == 5 ; ∗/
} p r o t e c t e d b o o l e a n promptToDiscardChanges ( ) {
i f ( ! boxChanged ) {
int startBoxIndex = 0; return f a l s e ;
}
f o r ( i n t curPage = 0 ; curPage < i m a g e L i s t . s w i t c h ( JOptionPane . s h o w C o n f i r m D i a l o g ( t h i s ,
s i z e ( ) ; c u r P a g e++) { bundle . g e t S t r i n g ( ”
T e s s B o x C o l l e c t i o n boxCol = new Do you want to discard the changes to ”)
TessBoxCollection () ; + b o x F i l e . getName ( ) + ” ? ” ,
// Note t h a t t h e c o o r d i n a t e s y s t e m u s e d APP NAME, JOptionPane . YES NO CANCEL OPTION
i n t h e box f i l e h a s ( 0 , 0 ) a t t h e bottom− , JOptionPane . INFORMATION MESSAGE) ) {
left . c a s e JOptionPane . YES OPTION :
// On computer g r a p h i c s d e v i c e , ( 0 , 0 ) i s return true ;
d e f i n e d a s top− l e f t . default :
i n t pageHeight = i m a g e L i s t . g e t ( curPage ) . return f a l s e ;
getHeight () ; }
f o r ( i n t i = s t a r t B o x I n d e x ; i < boxdata . }
l e n g t h ; i ++) {
S t r i n g [ ] i t e m s = b o x d a t a [ i ] . s p l i t ( ” \\ s+” /∗ ∗
); ∗ Displays a d i a l o g to save changes .

// s k i p i n v a l i d d a t a ∗ @return f a l s e i f u s e r canceled , t r u e
i f ( items . length < 5 || items . length > else
6) { ∗/
continue ; p r o t e c t e d b o o l e a n promptToSave ( ) {
} i f ( ! boxChanged ) {
return true ;
String chrs = items [ 0 ] ; }
i nt x = Integer . parseInt ( items [ 1 ] ) ; s w i t c h ( JOptionPane . s h o w C o n f i r m D i a l o g ( t h i s ,
i nt y = Integer . parseInt ( items [ 2 ] ) ; bundle . g e t S t r i n g ( ”
i nt w = Integer . parseInt ( items [ 3 ] ) − x ; Do you want to save the changes to ”)
i nt h = Integer . parseInt ( items [ 4 ] ) − y ; + ( b o x F i l e == n u l l ? b u n d l e . g e t S t r i n g ( ”
y = p a g e H e i g h t − y − h ; // f l i p t h e y− U n t i t l e d ” ) : b o x F i l e . getName ( ) ) + ” ? ” ,
coordinate APP NAME, JOptionPane . YES NO CANCEL OPTION
, JOptionPane . INFORMATION MESSAGE) ) {
s h o r t page ; c a s e JOptionPane . YES OPTION :
i f ( i t e m s . l e n g t h == 6 ) { return saveAction () ;
page = S h o r t . p a r s e S h o r t ( i t e m s [ 5 ] ) ; // c a s e JOptionPane . NO OPTION :
Tess 3 . 0 x format return true ;

174
default : }
return f a l s e ;
} return true ;
} }

boolean saveAction () { String formatOutputString ( ) {


i f ( b o x F i l e == n u l l | | ! boxFile . e x i s t s () ) { S t r i n g B u i l d e r s b = new S t r i n g B u i l d e r ( ) ;
return saveFileDlg () ; f o r ( s h o r t i = 0 ; i < i m a g e L i s t . s i z e ( ) ; i ++)
} else { {
return saveBoxFile () ; i n t pageHeight = ( ( BufferedImage ) imageList
} . g e t ( i ) ) . g e t H e i g h t ( ) ; // e a c h page ( i n an
} image ) can have d i f f e r e n t h e i g h t
f o r ( TessBox box : boxPages . g e t ( i ) . t o L i s t ( )
boolean saveFileDlg () { ) {
J F i l e C h o o s e r s a v e C h o o s e r = new J F i l e C h o o s e r ( R e c t a n g l e r e c t = box . g e t R e c t ( ) ;
outputDirectory ) ; s b . append ( S t r i n g . f o r m a t ( ”%s %d %d %d %d %d
F i l e F i l t e r t e x t F i l t e r = new S i m p l e F i l t e r ( ” ” , box . g e t C h r s ( ) , r e c t . x , p a g e H e i g h t −
box ” , ”Box F i l e s ” ) ; r e c t . y − r e c t . h e i g h t , r e c t . x + r e c t . width
saveChooser . addChoosableFileFilter ( , p a g e H e i g h t − r e c t . y , i ) ) . append (EOL) ;
textFilter ) ; }
saveChooser . s e t F i l e F i l t e r ( t e x t F i l t e r ) ; }
saveChooser . s e t D i a l o g T i t l e ( bundle . g e t S t r i n g ( i f ( isTess2 0Format ) {
” Save As ” ) ) ; r e t u r n sb . t o S t r i n g ( ) . r e p l a c e ( ” 0 ” + EOL,
i f ( b o x F i l e != n u l l ) { EOL) ; // s t r i p t h e e n d i n g z e r o e s
saveChooser . s e t S e l e c t e d F i l e ( boxFile ) ; }
} r e t u r n sb . t o S t r i n g ( ) ;
}
if ( s a v e C h o o s e r . s h o w S a v e D i a l o g ( t h i s ) ==
J F i l e C h o o s e r . APPROVE OPTION) { /∗ ∗
outputDirectory = saveChooser . ∗ Update MRU L i s t .
g e t C u r r e n t D i r e c t o r y ( ) . getPath ( ) ; ∗
F i l e f = saveChooser . g e t S e l e c t e d F i l e ( ) ; ∗ @param f i l e N a m e
i f ( s a v e C h o o s e r . g e t F i l e F i l t e r ( ) == ∗/
textFilter ) { p r o t e c t e d v o i d updateMRUList ( S t r i n g fileName )
i f ( ! f . getName ( ) . endsWith ( ” . box ” ) ) { {
f = new F i l e ( f . g e t P a t h ( ) + ” . box ” ) ; // t o be i m p l e m e n t e d i n s u b c l a s s
} }
i f ( b o x F i l e != n u l l && b o x F i l e . g e t P a t h ( ) .
e q u a l s ( f . getPath ( ) ) ) { p r i v a t e void jMenuItemSaveActionPerformed (
i f ( JOptionPane . NO OPTION == JOptionPane . j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
showConfirmDialog ( FIRST : e v e n t j M e n u I t e m S a v e A c t i o n P e r f o r m e d
Gui . t h i s , saveAction () ;
b o x F i l e . getName ( ) + b u n d l e . g e t S t r i n g ( ” } //GEN−LAST :
file already exist ”) , event jMenuItemSaveActionPerformed
bundle . g e t S t r i n g ( ” Confirm Save As ” ) ,
JOptionPane . YES NO OPTION , p r i v a t e void jMenuItemExitActionPerformed (
JOptionPane .WARNING MESSAGE) ) { j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
return f a l s e ; FIRST : e v e n t j M e n u I t e m E x i t A c t i o n P e r f o r m e d
} quit () ;
} else { } //GEN−LAST :
boxFile = f ; event jMenuItemExitActionPerformed
}
} else { void quit () {
boxFile = f ; i f ( ! promptToSave ( ) ) {
} return ;
return saveBoxFile () ; }
} else {
return f a l s e ; i f ( c u r r e n t D i r e c t o r y != n u l l ) {
} p r e f s . put ( ” c u r r e n t D i r e c t o r y ” ,
} currentDirectory ) ;
}
boolean saveBoxFile () { i f ( o u t p u t D i r e c t o r y != n u l l ) {
getGlassPane ( ) . s e t C u r s o r ( Cursor . p r e f s . put ( ” o u t p u t D i r e c t o r y ” ,
g e t P r e d e f i n e d C u r s o r ( C u r s o r . WAIT CURSOR) ) ; outputDirectory ) ;
getGlassPane ( ) . s e t V i s i b l e ( true ) ; }

try { p r e f s . p u t I n t ( ” windowState ” , g et Ex ten de dS ta te


t r y ( B u f f e r e d W r i t e r o u t = new () ) ;
B u f f e r e d W r i t e r ( new O ut p u tS t r e am W r it e r ( new
F i l e O u t p u t S t r e a m ( b o x F i l e ) , UTF8) ) ) { i f ( g e t E x t e n d e d S t a t e ( ) == NORMAL) {
out . w r i t e ( formatOutputString ( ) ) ; p r e f s . putInt ( ” frameHeight ” , getHeight ( ) ) ;
} p r e f s . p u t I n t ( ” frameWidth ” , getWidth ( ) ) ;
// updateMRUList ( b o x F i l e . g e t P a t h ( ) ) p r e f s . p u t I n t ( ” frameX ” , getX ( ) ) ;
; p r e f s . p u t I n t ( ” frameY ” , getY ( ) ) ;
updateSave ( f a l s e ) ; }
} c a t c h ( OutOfMemoryError oome ) {
l o g g e r . l o g ( L e v e l . SEVERE, oome . g e t M e s s a g e ( ) , p r e f s . putInt ( ” f i l t e r I n d e x ” , filterIndex ) ;
oome ) ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , oome . System . e x i t ( 0 ) ;
getMessage ( ) , bundle . g e t S t r i n g ( ” }
OutOfMemoryError ” ) , JOptionPane .
ERROR MESSAGE) ; p r i v a t e v o i d jMenuItemAboutActionPerformed (
} catch ( FileNotFoundException f n f e ) { j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
l o g g e r . l o g ( L e v e l . SEVERE, f n f e . g e t M e s s a g e ( ) , FIRST : e v e n t j M e n u I t e m A b o u t A c t i o n P e r f o r m e d
fnfe ) ; about ( ) ;
} catch ( Exception e ) { } //GEN−LAST :
l o g g e r . l o g ( L e v e l . SEVERE, e . g e t M e s s a g e ( ) , e ) event jMenuItemAboutActionPerformed
;
} finally { void about ( ) {
S w i n g U t i l i t i e s . i n v o k e L a t e r ( new Runnable ( ) { try {
P r o p e r t i e s c o n f i g = new P r o p e r t i e s ( ) ;
@Ov err ide c o n f i g . loadFromXML ( g e t C l a s s ( ) .
p u b l i c v o i d run ( ) { g e t R e s o u r c e A s S t r e a m ( ” c o n f i g . xml ” ) ) ;
getGlassPane ( ) . s e t C u r s o r ( Cursor . String version = config . getProperty ( ”
g e t P r e d e f i n e d C u r s o r ( C u r s o r . DEFAULT CURSOR Version ” ) ;
)); SimpleDateFormat s d f = new SimpleDateFormat
getGlassPane ( ) . s e t V i s i b l e ( f a l s e ) ; ( ” yyyy /MM/dd” ) ;
} Date r e l e a s e D a t e = s d f . p a r s e ( c o n f i g .
}) ; getProperty ( ” ReleaseDate ” ) ) ;

175
t h i s . jButtonSave . setEnabled ( modified ) ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , t h i s . jMenuItemSave . s e t E n a b l e d ( m o d i f i e d ) ;
APP NAME + ” ” + v e r s i o n + ” \ u00a9 2011\ rootPane . p u t C l i e n t P r o p e r t y ( ” windowModified ”
n” , modified ) ;
+ ” T e s s e r a c t Box E d i t o r & T r a i n e r \n” // s e e h t t p : / / d e v e l o p e r . a p p l e . com/ qa / qa200 1
+ DateFormat . g e t D a t e I n s t a n c e ( DateFormat . / qa 1146 . html
LONG) . f o r m a t ( r e l e a s e D a t e ) }
+ ”\ nhttp : / / v i e t o c r . s o u r c e f o r g e . net ” , }
jMenuItemAbout . g e t T e x t ( ) , JOptionPane .
INFORMATION MESSAGE) ; p r i v a t e void jButtonOpenActionPerformed ( java .
} catch ( IOException | ParseException | awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
HeadlessException e ) { event jButtonOpenActionPerformed
l o g g e r . l o g ( L e v e l . SEVERE, e . g e t M e s s a g e ( ) , e ) jMenuItemOpenActionPerformed ( e v t ) ;
; } //GEN−LAST : e v e n t j B u t t o n O p e n A c t i o n P e r f o r m e d
}
} p r i v a t e void jButtonSaveActionPerformed ( java .
p r i v a t e void jButtonPrevPageActionPerformed ( awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− event jButtonSaveActionPerformed
FIRST : jMenuItemSaveActionPerformed ( evt ) ;
event jButtonPrevPageActionPerformed } //GEN−LAST : e v e n t j B u t t o n S a v e A c t i o n P e r f o r m e d
i f ( i m a g e L i s t != n u l l && i m a g e I n d e x > 0 ) {
−−i m a g e I n d e x ; p r i v a t e void jButtonReloadActionPerformed (
loadImage ( ) ; j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
loadTable ( ) ; FIRST : e v e n t j B u t t o n R e l o a d A c t i o n P e r f o r m e d
} i f ( ! promptToDiscardChanges ( ) ) {
} //GEN−LAST : return ;
event jButtonPrevPageActionPerformed }

p r i v a t e void jButtonNextPageActionPerformed ( i f ( b o x F i l e != n u l l ) {
j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− jButtonReload . setEnabled ( f a l s e ) ;
FIRST : getGlassPane ( ) . s e t C u r s o r ( Cursor .
event jButtonNextPageActionPerformed g e t P r e d e f i n e d C u r s o r ( C u r s o r . WAIT CURSOR) ) ;
i f ( i m a g e L i s t != n u l l && i m a g e I n d e x < getGlassPane ( ) . s e t V i s i b l e ( true ) ;
imageList . s i z e ( ) − 1) {
++i m a g e I n d e x ; SwingWorker<Void , Void> loadWorker = new
loadImage ( ) ; SwingWorker<Void , Void >() {
loadTable ( ) ;
} @Ov err ide
} //GEN−LAST : p r o t e c t e d Void doInBackground ( ) throws
event jButtonNextPageActionPerformed Exception {
readBoxFile ( boxFile ) ;
void loadImage ( ) { return null ;
t h i s . j L a b e l I m a g e . s e t I c o n ( new I m a g e I c o n ( }
imageList . get ( imageIndex ) ) ) ;
i f ( b o x e s != n u l l ) { @Ov err ide
boxes . d e s e l e c t A l l ( ) ; p r o t e c t e d v o i d done ( ) {
} jButtonReload . setEnabled ( true ) ;
t h i s . jLabelImage . repaint ( ) ; getGlassPane ( ) . s e t C u r s o r ( Cursor .
t h i s . jLabelPageNbr . setText ( S t r i n g . format ( ” g e t P r e d e f i n e d C u r s o r ( C u r s o r . DEFAULT CURSOR
Page : %d o f %d” , i m a g e I n d e x + 1 , ));
imageList . s i z e () ) ) ; getGlassPane ( ) . s e t V i s i b l e ( f a l s e ) ;
setButton () ; }
tableSelectAction = true ; };
resetReadout () ;
tableSelectAction = false ; loadWorker . e x e c u t e ( ) ;
} }
} //GEN−LAST :
void setButton () { event jButtonReloadActionPerformed
i f ( i m a g e I n d e x == 0 ) {
t h i s . jButtonPrevPage . setEnabled ( f a l s e ) ; v o i d j M e n u I t e m F o n t A c t i o n P e r f o r m e d ( j a v a . awt .
} else { e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
t h i s . jButtonPrevPage . setEnabled ( t r u e ) ; event jMenuItemFontActionPerformed
} JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
TO BE IMPLEMENTED) ;
i f ( i m a g e I n d e x == i m a g e L i s t . s i z e ( ) − 1 ) { } //GEN−LAST :
t h i s . jButtonNextPage . setEnabled ( f a l s e ) ; event jMenuItemFontActionPerformed
} else {
t h i s . jButtonNextPage . setEnabled ( t r u e ) ; p r i v a t e void jMenuItemHelpActionPerformed (
} j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
} FIRST : e v e n t j M e n u I t e m H e l p A c t i o n P e r f o r m e d
f i n a l S t r i n g readme = b u n d l e . g e t S t r i n g ( ”
void resetReadout () { readme ” ) ;
jTextFieldCharacter . setText ( n u l l ) ; i f (MAC OS X) {
jTextFieldChar . setText ( n u l l ) ; try {
jTextFieldCodepointValue . setText ( n u l l ) ; f i n a l F i l e s u p p o r t D i r = new F i l e ( System .
jSpinnerH . setValue (0) ; g e t P r o p e r t y ( ” u s e r . home” ) + ” / L i b r a r y /
jSpinnerW . s e t V a l u e ( 0 ) ; A p p l i c a t i o n S u p p o r t / ” + APP NAME) ;
jSpinnerX . setValue (0) ; i f ( ! supportDir . e x i s t s () ) {
jSpinnerY . setValue (0) ; supportDir . mkdirs ( ) ;
jLabelSubimage . s e t I c o n ( n u l l ) ; }
} F i l e h e l p F i l e = new F i l e ( s u p p o r t D i r , ”
readme . html ” ) ;
void enableReadout ( boolean enabled ) { copyFileFromJarToSupportDir ( h e l p F i l e ) ;
jTextFieldCharacter . setEnabled ( enabled ) ; Runtime . getRuntime ( ) . e x e c ( new S t r i n g [ ] { ”
jSpinnerX . setEnabled ( enabled ) ; open ” , ”−b” , ”com . a p p l e . h e l p v i e w e r ” ,
jSpinnerY . setEnabled ( enabled ) ; readme } , n u l l , s u p p o r t D i r ) ;
jSpinnerH . setEnabled ( enabled ) ; } catch ( IOException e ) {
jSpinnerW . s e t E n a b l e d ( e n a b l e d ) ; l o g g e r . l o g ( L e v e l . SEVERE, e . g e t M e s s a g e ( ) , e
} );
}
/∗ ∗ } else {
∗ Updates t h e Save a c t i o n . i f ( h e l p t o p i c s F r a m e == n u l l ) {
∗ h e l p t o p i c s F r a m e = new JFrame ( jMenuItemHelp
∗ @param m o d i f i e d w h e t h e r f i l e h a s been . getText ( ) ) ;
modified helptopicsFrame . getContentPane ( ) . setLayout
∗/ ( new B o r d e r L a y o u t ( ) ) ;
void updateSave ( boolean m o d i f i e d ) { HtmlPane h e l p P a n e = new HtmlPane ( readme ) ;
i f ( boxChanged != m o d i f i e d ) { h e l p t o p i c s F r a m e . g e t C o n t e n t P a n e ( ) . add (
boxChanged = m o d i f i e d ; helpPane , B o r d e r L a y o u t .CENTER) ;

176
h e l p t o p i c s F r a m e . g e t C o n t e n t P a n e ( ) . add ( FIRST : e v e n t j B u t t o n C o n v e r t A c t i o n P e r f o r m e d
helpPane . g e t S t a t u s B a r ( ) , BorderLayout . S t r i n g curChar = t h i s . j T e x t F i e l d C h a r a c t e r .
SOUTH) ; getText ( ) ;
h e l p t o p i c s F r a m e . pack ( ) ; i f ( curChar . t r i m ( ) . l e n g t h ( ) == 0 ) {
h e l p t o p i c s F r a m e . s e t L o c a t i o n ( ( s c r e e n . width return ;
− h e l p t o p i c s F r a m e . getWidth ( ) ) / 2 , 4 0 ) ; }
} // C o n v e r t NCR o r e s c a p e s e q u e n c e t o U n i c o d e
helptopicsFrame . s e t V i s i b l e ( true ) ; .
} t h i s . jTextFieldCharacter . setText (
} //GEN−LAST : T e x t U t i l i t i e s . convertNCR ( t h i s .
event jMenuItemHelpActionPerformed jTextFieldCharacter . getText ( ) ) ) ;
// Commit t h e change , i f no c o n v e r s i o n .
p r i v a t e void copyFileFromJarToSupportDir ( F i l e i f ( curChar . e q u a l s ( t h i s . j T e x t F i e l d C h a r a c t e r .
h e l p F i l e ) throws IOException { getText ( ) ) ) {
i f (! helpFile . exists () ) { jTextFieldCharacterActionPerformed ( evt ) ;
t r y ( ReadableByteChannel input = Channels . }
newChannel ( C l a s s L o a d e r . } //GEN−LAST :
getSystemResourceAsStream ( h e l p F i l e . event jButtonConvertActionPerformed
getName ( ) ) ) ; v o i d j M e n u I t e m M e r g e A c t i o n P e r f o r m e d ( j a v a . awt .
F i l e C h a n n e l o u t p u t = new F i l e O u t p u t S t r e a m e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
( h e l p F i l e ) . getChannel ( ) ) { event jMenuItemMergeActionPerformed
o u t p u t . t r a n s f e r F r o m ( i n p u t , 0 , 1 0 0 0 0 0 0L ) ; JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
} TO BE IMPLEMENTED) ;
} } //GEN−LAST :
} event jMenuItemMergeActionPerformed
v o i d j M e n u I t e m S p l i t A c t i o n P e r f o r m e d ( j a v a . awt .
p r i v a t e void jMenuItemSaveAsActionPerformed ( e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− event jMenuItemSplitActionPerformed
FIRST : JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
event jMenuItemSaveAsActionPerformed TO BE IMPLEMENTED) ;
saveFileDlg () ; } //GEN−LAST :
} //GEN−LAST : event jMenuItemSplitActionPerformed
event jMenuItemSaveAsActionPerformed v o i d j M e n u I t e m D e l e t e A c t i o n P e r f o r m e d ( j a v a . awt .
p r i v a t e void jSpinnerXStateChanged ( javax . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
s w i n g . e v e n t . ChangeEvent e v t ) { //GEN−FIRST event jMenuItemDeleteActionPerformed
: event jSpinnerXStateChanged JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
stateChanged ( evt ) ; TO BE IMPLEMENTED) ;
} //GEN−LAST : e v e n t j S p i n n e r X S t a t e C h a n g e d } //GEN−LAST :
p r i v a t e void jSpinnerYStateChanged ( javax . event jMenuItemDeleteActionPerformed
s w i n g . e v e n t . ChangeEvent e v t ) { //GEN−FIRST v o i d j M e n u I t e m I n s e r t A c t i o n P e r f o r m e d ( j a v a . awt .
: event jSpinnerYStateChanged e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
stateChanged ( evt ) ; event jMenuItemInsertActionPerformed
} //GEN−LAST : e v e n t j S p i n n e r Y S t a t e C h a n g e d JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
p r i v a t e void jSpinnerWStateChanged ( javax . TO BE IMPLEMENTED) ;
s w i n g . e v e n t . ChangeEvent e v t ) { //GEN−FIRST } //GEN−LAST :
: event jSpinnerWStateChanged event jMenuItemInsertActionPerformed
stateChanged ( evt ) ; p r i v a t e void jButtonMergeActionPerformed ( java
} //GEN−LAST : e v e n t j S p i n n e r W S t a t e C h a n g e d . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
p r i v a t e void jSpinnerHStateChanged ( javax . event jButtonMergeActionPerformed
s w i n g . e v e n t . ChangeEvent e v t ) { //GEN−FIRST jMenuItemMergeActionPerformed ( e v t ) ;
: event jSpinnerHStateChanged } //GEN−LAST : e v e n t j B u t t o n M e r g e A c t i o n P e r f o r m e d
stateChanged ( evt ) ; private void jButtonDeleteActionPerformed (
} //GEN−LAST : e v e n t j S p i n n e r H S t a t e C h a n g e d j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
void stateChanged ( javax . swing . event . FIRST : e v e n t j B u t t o n D e l e t e A c t i o n P e r f o r m e d
ChangeEvent e v t ) { jMenuItemDeleteActionPerformed ( evt ) ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , } //GEN−LAST :
TO BE IMPLEMENTED) ; event jButtonDeleteActionPerformed
} private void jButtonSplitActionPerformed ( java
private void . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
jTextFieldCharacterActionPerformed ( java . event jButtonSplitActionPerformed
awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : jMenuItemSplitActionPerformed ( evt ) ;
event jTextFieldCharacterActionPerformed } //GEN−LAST : e v e n t j B u t t o n S p l i t A c t i o n P e r f o r m e d
i f ( b o x e s == n u l l ) { private void jButtonInsertActionPerformed (
return ; j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−
} FIRST : e v e n t j B u t t o n I n s e r t A c t i o n P e r f o r m e d
L i s t <TessBox> s e l e c t e d = t h i s . b o x e s . jMenuItemInsertActionPerformed ( evt ) ;
getSelectedBoxes () ; } //GEN−LAST :
i f ( s e l e c t e d . s i z e ( ) <= 0 ) { event jButtonInsertActionPerformed
return ; p r i v a t e void jButtonFindActionPerformed ( java .
} e l s e i f ( s e l e c t e d . s i z e ( ) > 1) { awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e event jButtonFindActionPerformed
s e l e c t o n l y one box t o a p p l y t h e c h a n g e . i f ( i m a g e L i s t == n u l l ) {
”) ; return ;
return ; }
} i n t pageHeight = imageList . get ( imageIndex ) .
getHeight () ;
TessBox box = s e l e c t e d . g e t ( 0 ) ; S t r i n g [ ] items = t h i s . jTextFieldFind . getText
i n t i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box ) ( ) . s p l i t ( ” \\ s+” ) ;
; try {
// C o n v e r t NCR o r e s c a p e s e q u e n c e t o U n i c o d e TessBox f i n d B o x ;
.
t h i s . jTextFieldCharacter . setText ( i f ( i t e m s . l e n g t h == 1 ) {
T e x t U t i l i t i e s . convertNCR ( t h i s . String chrs = items [ 0 ] ;
jTextFieldCharacter . getText ( ) ) ) ; i f ( c h r s . l e n g t h ( ) == 0 ) {
String str = this . jTextFieldCharacter . throw new E x c e p t i o n ( ”Empty s e a r c h v a l u e s .
getText ( ) ; ”) ;
i f ( ! box . g e t C h r s ( ) . e q u a l s ( s t r ) ) { }
box . s e t C h r s ( s t r ) ; // C o n v e r t NCR o r e s c a p e s e q u e n c e t o
t a b l e M o d e l . s e t V a l u e A t ( box . g e t C h r s ( ) , i n d e x , Unicode .
0) ; c h r s = T e x t U t i l i t i e s . convertNCR ( c h r s ) ;
jTextFieldChar . setText ( s t r ) ;
jTextFieldCodepointValue . setText ( U t i l s . f i n d B o x = new TessBox ( c h r s , new R e c t a n g l e
toHex ( s t r ) ) ; ( ) , imageIndex ) ;
updateSave ( t r u e ) ; findBox = boxes . selectByChars ( findBox ) ;
} } else {
} //GEN−LAST : i nt x = Integer . parseInt ( items [ 0 ] ) ;
event jTextFieldCharacterActionPerformed i nt y = Integer . parseInt ( items [ 1 ] ) ;
p r i v a t e void jButtonConvertActionPerformed ( i nt w = Integer . parseInt ( items [ 2 ] ) − x ;
j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− i nt h = Integer . parseInt ( items [ 3 ] ) − y ;

177
y = p a g e H e i g h t − y − h ; // f l i p t h e y− v o i d j B u t t o n I n p u t A c t i o n P e r f o r m e d ( j a v a . awt .
coordinate e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
f i n d B o x = new TessBox ( ” ” , new R e c t a n g l e ( x , event jButtonInputActionPerformed
y , w, h ) , i m a g e I n d e x ) ; JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
findBox = boxes . s e l e c t ( findBox ) ; TO BE IMPLEMENTED) ;
} } //GEN−LAST : e v e n t j B u t t o n I n p u t A c t i o n P e r f o r m e d

i f ( f i n d B o x != n u l l ) { v o i d j B u t t o n F o n t A c t i o n P e r f o r m e d ( j a v a . awt .
i n t index = boxes . t o L i s t ( ) . indexOf ( findBox e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
); event jButtonFontActionPerformed
t h i s . jTable . s e t R o w S e l e c t i o n I n t e r v a l ( index , JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
index ) ; TO BE IMPLEMENTED) ;
Rectangle r e c t = t h i s . jTable . getCellRect ( } //GEN−LAST : e v e n t j B u t t o n F o n t A c t i o n P e r f o r m e d
index , 0 , t r u e ) ;
t h i s . jTable . scrollRectToVisible ( rect ) ; void jSpinnerTrackingStateChanged ( javax . swing
} else { . e v e n t . ChangeEvent e v t ) { //GEN−FIRST :
t h i s . jTable . c l e a r S e l e c t i o n () ; event jSpinnerTrackingStateChanged
S t r i n g msg = S t r i n g . f o r m a t ( ”No box w i t h JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
t h e s p e c i f i e d %s was f o u n d . ” , i t e m s . TO BE IMPLEMENTED) ;
l e n g t h == 1 ? ” c h a r a c t e r ( s ) ” : ” } //GEN−LAST :
coordinates ”) ; event jSpinnerTrackingStateChanged
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , msg ) ;
} v o i d j B u t t o n G e n e r a t e A c t i o n P e r f o r m e d ( j a v a . awt .
} catch ( Exception e ) { e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e event jButtonGenerateActionPerformed
e n t e r box c h a r a c t e r ( s ) o r c o o r d i n a t e s ( JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
x1 y1 x2 y2 ) . ” ) ; TO BE IMPLEMENTED) ;
} } //GEN−LAST :
} //GEN−LAST : e v e n t j B u t t o n F i n d A c t i o n P e r f o r m e d event jButtonGenerateActionPerformed

private void jTextFieldFindActionPerformed ( v o i d j B u t t o n C l e a r A c t i o n P e r f o r m e d ( j a v a . awt .


j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
FIRST : e v e n t j T e x t F i e l d F i n d A c t i o n P e r f o r m e d event jButtonClearActionPerformed
jButtonFindActionPerformed ( evt ) ; JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
} //GEN−LAST : TO BE IMPLEMENTED) ;
event jTextFieldFindActionPerformed } //GEN−LAST : e v e n t j B u t t o n C l e a r A c t i o n P e r f o r m e d

void jMenuItemMergeTiffActionPerformed ( java . void jButtonBrowseTessActionPerformed ( java .


awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
event jMenuItemMergeTiffActionPerformed event jButtonBrowseTessActionPerformed
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
TO BE IMPLEMENTED) ; TO BE IMPLEMENTED) ;
} //GEN−LAST : } //GEN−LAST :
event jMenuItemMergeTiffActionPerformed event jButtonBrowseTessActionPerformed

void jMenuItemSplitTiffActionPerformed ( java . void jButtonBrowseDataActionPerformed ( java .


awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
: event jButtonBrowseDataActionPerformed
event jMenuItemSplitTiffActionPerformed JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , TO BE IMPLEMENTED) ;
TO BE IMPLEMENTED) ; } //GEN−LAST :
} //GEN−LAST : event jButtonBrowseDataActionPerformed
event jMenuItemSplitTiffActionPerformed
v o i d j B u t t o n T r a i n A c t i o n P e r f o r m e d ( j a v a . awt .
p r i v a t e void jButtonPrevActionPerformed ( java . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : event jButtonTrainActionPerformed
event jButtonPrevActionPerformed JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
i n t index = t h i s . jTable . getSelectedRow ( ) ; TO BE IMPLEMENTED) ;
i f ( index > 0) { } //GEN−LAST : e v e n t j B u t t o n T r a i n A c t i o n P e r f o r m e d
boxes . d e s e l e c t A l l ( ) ;
t h i s . jTable . c l e a r S e l e c t i o n () ; v o i d j B u t t o n C a n c e l A c t i o n P e r f o r m e d ( j a v a . awt .
−−i n d e x ; e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
j a v a . u t i l . L i s t <TessBox> boxesOfCurPage = event jButtonCancelActionPerformed
b o x e s . t o L i s t ( ) ; // b o x e s o f c u r r e n t page JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
TessBox s e l e c t e d = boxesOfCurPage . g e t ( i n d e x TO BE IMPLEMENTED) ;
); } //GEN−LAST :
selected . setSelected ( true ) ; event jButtonCancelActionPerformed
t h i s . jTable . a d d R o w S e l e c t i o n I n t e r v a l ( index ,
index ) ; p r i v a t e v o i d jTabbedPaneMainStateChanged (
Rectangle r e c t = t h i s . jTable . getCellRect ( j a v a x . s w i n g . e v e n t . ChangeEvent e v t ) { //GEN
index , 0 , t r u e ) ; −FIRST : e v e n t j T a b b e d P a n e M a i n S t a t e C h a n g e d
t h i s . jTable . scrollRectToVisible ( rect ) ; JTabbedPane pane = ( JTabbedPane ) e v t .
} getSource () ;
} //GEN−LAST : e v e n t j B u t t o n P r e v A c t i o n P e r f o r m e d b o o l e a n b o x E d i t o r A c t i v e = pane .
g e t S e l e c t e d I n d e x ( ) == 1 ;
p r i v a t e void jButtonNextActionPerformed ( java . t h i s . jMenuEdit . s e t V i s i b l e ( b o x E d i t o r A c t i v e ) ;
awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : t h i s . jMenuItemFont . s e t V i s i b l e (
event jButtonNextActionPerformed b o x E d i t o r A c t i v e | | pane . g e t S e l e c t e d I n d e x
i f ( b o x e s == n u l l ) { ( ) == 0 ) ;
return ; t h i s . jSeparatorLAF . s e t V i s i b l e ( t h i s .
} jMenuItemFont . i s V i s i b l e ( ) ) ;
j a v a . u t i l . L i s t <TessBox> boxesOfCurPage = t h i s . jMenuItemOpen . s e t V i s i b l e (
b o x e s . t o L i s t ( ) ; // b o x e s o f c u r r e n t page boxEditorActive ) ;
i n t index = t h i s . jTable . getSelectedRow ( ) ; t h i s . jMenuItemSave . s e t V i s i b l e (
i f ( i n d e x < boxesOfCurPage . s i z e ( ) − 1 ) { boxEditorActive ) ;
boxes . d e s e l e c t A l l ( ) ; t h i s . jMenuItemSaveAs . s e t V i s i b l e (
t h i s . jTable . c l e a r S e l e c t i o n () ; boxEditorActive ) ;
++i n d e x ; t h i s . jMenuRecentFiles . s e t V i s i b l e (
TessBox s e l e c t e d = boxesOfCurPage . g e t ( i n d e x boxEditorActive ) ;
); this . jSeparatorRecentFiles . setVisible (
selected . setSelected ( true ) ; boxEditorActive ) ;
t h i s . jTable . a d d R o w S e l e c t i o n I n t e r v a l ( index , this . jSeparatorExit . setVisible (
index ) ; boxEditorActive ) ;
Rectangle r e c t = t h i s . jTable . getCellRect ( } //GEN−LAST : e v e n t j T a b b e d P a n e M a i n S t a t e C h a n g e d
index , 0 , t r u e ) ;
t h i s . jTable . scrollRectToVisible ( rect ) ; v o i d j B u t t o n C l e a r L o g A c t i o n P e r f o r m e d ( j a v a . awt .
} e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST :
} //GEN−LAST : e v e n t j B u t t o n N e x t A c t i o n P e r f o r m e d event jButtonClearLogActionPerformed
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,

178
TO BE IMPLEMENTED) ; w i d t h −= 1 ;
} //GEN−LAST : }
event jButtonClearLogActionPerformed
w h i l e ( h e i g h t + Gui . iconPosY > image .
v o i d j B u t t o n S a v e L o g A c t i o n P e r f o r m e d ( j a v a . awt . getHeight ( ) + 1) {
e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : h e i g h t −= 1 ;
event jButtonSaveLogActionPerformed }
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s ,
TO BE IMPLEMENTED) ; B u f f e r e d I m a g e subImage = image . g e t S u b i m a g e (
} //GEN−LAST : Math . max ( 0 , Math . min ( Gui . imageWidth − 1 ,
event jButtonSaveLogActionPerformed Gui . iconPosX − Gui . i c o n M a r g i n ) ) ,
Math . max ( 0 , Math . min ( Gui . i m a g e H e i g h t − 1 ,
v o i d j B u t t o n V a l i d a t e A c t i o n P e r f o r m e d ( j a v a . awt . Gui . iconPosY − Gui . i c o n M a r g i n ) ) ,
e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : width ,
event jButtonValidateActionPerformed height
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , );
TO BE IMPLEMENTED) ;
} //GEN−LAST : r e t u r n subImage ;
event jButtonValidateActionPerformed }

void jButtonCloseDialogActionPerformed ( java . /∗ ∗


awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN−FIRST : ∗ @param a r g s t h e command l i n e a r g u m e n t s
event jButtonCloseDialogActionPerformed ∗/
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
TO BE IMPLEMENTED) ;
} //GEN−LAST : j a v a . awt . EventQueue . i n v o k e L a t e r ( new Runnable
event jButtonCloseDialogActionPerformed () {

p r i v a t e void jSpinnerMarginStateChanged ( javax @O verr ide


. s w i n g . e v e n t . ChangeEvent e v t ) { //GEN− p u b l i c v o i d run ( ) {
FIRST : e v e n t j S p i n n e r M a r g i n S t a t e C h a n g e d new Gui ( ) . s e t V i s i b l e ( t r u e ) ;
iconMargin = ( I n t e g e r ) jSpinnerMargin . }
getValue ( ) ; }) ;
i n t index = jTable . getSelectedRow ( ) ; }
jTable . c l e a r S e l e c t i o n () ; // V a r i a b l e s d e c l a r a t i o n − do n o t m o d i f y //GEN
jTable . s e t R o w S e l e c t i o n I n t e r v a l ( index , index ) −BEGIN : v a r i a b l e s
; p r i v a t e j a v a x . s w i n g . Box . F i l l e r f i l l e r 2 ;
jLabelSubimage . requestFocus ( ) ; p r o t e c t e d j a v a x . s w i n g . JButton
} //GEN−LAST : e v e n t j S p i n n e r M a r g i n S t a t e C h a n g e d jButtonBrowseData ;
p r i v a t e j a v a x . s w i n g . JButton
p r i v a t e void jSpinnerScaleStateChanged ( javax . jButtonBrowseOutputDir ;
s w i n g . e v e n t . ChangeEvent e v t ) { //GEN−FIRST p r o t e c t e d j a v a x . s w i n g . JButton
: event jSpinnerScaleStateChanged jButtonBrowseTess ;
scaleFactor = ( Integer ) jSpinnerScale . p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n C a n c e l ;
getValue ( ) ; p r i v a t e j a v a x . s w i n g . JButton j B u t t o n C l e a r ;
i n t index = jTable . getSelectedRow ( ) ; p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n C l e a r L o g
jTable . c l e a r S e l e c t i o n () ; ;
jTable . s e t R o w S e l e c t i o n I n t e r v a l ( index , index ) p r i v a t e j a v a x . s w i n g . JButton
; jButtonCloseDialog ;
jLabelSubimage . requestFocus ( ) ; p r i v a t e j a v a x . s w i n g . JButton j B u t t o n C o n v e r t ;
} //GEN−LAST : e v e n t j S p i n n e r S c a l e S t a t e C h a n g e d p r i v a t e j a v a x . s w i n g . JButton j B u t t o n D e l e t e ;
p r i v a t e j a v a x . s w i n g . JButton j B u t t o n F i n d ;
private void jTextFieldCharacterKeyReleased ( p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n F o n t ;
j a v a . awt . e v e n t . KeyEvent e v t ) { //GEN−FIRST p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n G e n e r a t e
: event jTextFieldCharacterKeyReleased ;
i f ( e v t . getKeyCode ( ) == KeyEvent . VK ESCAPE p r i v a t e j a v a x . s w i n g . JButton j B u t t o n I n p u t ;
| | e v t . getKeyCode ( ) == KeyEvent . VK ENTER) p r i v a t e j a v a x . s w i n g . JButton j B u t t o n I n s e r t ;
{ p r i v a t e j a v a x . s w i n g . JButton j B u t t o n M e r g e ;
jLabelSubimage . requestFocus ( ) ; p r i v a t e j a v a x . s w i n g . JButton j B u t t o n N e x t ;
} p r i v a t e j a v a x . s w i n g . JButton j B u t t o n N e x t P a g e ;
} //GEN−LAST : p r i v a t e j a v a x . s w i n g . JButton jButtonOpen ;
event jTextFieldCharacterKeyReleased p r i v a t e j a v a x . s w i n g . JButton j B u t t o n P r e v ;
p r i v a t e j a v a x . s w i n g . JButton j B u t t o n P r e v P a g e ;
void jButtonBrowseOutputDirActionPerformed ( p r i v a t e j a v a x . s w i n g . JButton j B u t t o n R e l o a d ;
j a v a . awt . e v e n t . A c t i o n E v e n t e v t ) { //GEN− p r i v a t e j a v a x . s w i n g . JButton j B u t t o n S a v e ;
FIRST : p r i v a t e j a v a x . s w i n g . JButton j B u t t o n S a v e L o g ;
event jButtonBrowseOutputDirActionPerformed p r i v a t e j a v a x . s w i n g . JButton j B u t t o n S p l i t ;
p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n T r a i n ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , p r o t e c t e d j a v a x . s w i n g . JButton j B u t t o n V a l i d a t e
TO BE IMPLEMENTED) ; ;
} //GEN−LAST : p r o t e c t e d j a v a x . s w i n g . JCheckBox
event jButtonBrowseOutputDirActionPerformed jCheckBoxAntiAliasing ;
p r o t e c t e d j a v a x . s w i n g . JCheckBox jCheckBoxRTL ;
@SuppressWarnings ( ” r a w t y p e s ” )
/∗ ∗ p r o t e c t e d j a v a x . s w i n g . JComboBox jComboBoxOps
∗ Gets a s u bi m a ge f o r d i s p l a y i n boxview . ;
∗ p r o t e c t e d javax . swing . JDialog
∗ @param image jDialogValidationResult ;
∗ @param r e c t p r i v a t e javax . swing . JFileChooser
∗ @return jFileChooserInputImage ;
∗/ p r i v a t e javax . swing . JLabel j L a b e l 1 ;
B u f f e r e d I m a g e g e t S u b i m a g e ( B u f f e r e d I m a g e image p r i v a t e javax . swing . JLabel j L a b e l 2 ;
, Rectangle r e c t ) { p r i v a t e javax . swing . JLabel j L a b e l 3 ;
Gui . iconPosX = r e c t . x ; p r i v a t e javax . swing . JLabel j L a b e l 4 ;
Gui . iconPosY = r e c t . y ; p r i v a t e javax . swing . JLabel j L a b e l C h a r a c t e r ;
p r i v a t e javax . swing . JLabel jLabelCodepoint ;
Gui . imageWidth = image . getWidth ( ) ; p r i v a t e javax . swing . JLabel jLabelH ;
Gui . i m a g e H e i g h t = image . g e t H e i g h t ( ) ; p r i v a t e javax . swing . JLabel jLabelH1 ;
p r o t e c t e d javax . swing . JLabel jLabelImage ;
Gui . i c o n H e i g h t = r e c t . h e i g h t ; p r i v a t e javax . swing . JLabel j L a b e l N o i s e ;
Gui . i c o n W i d t h = r e c t . w i d t h ; p r i v a t e javax . swing . JLabel jLabelOutput ;
p r i v a t e javax . swing . JLabel jLabelPageNbr ;
int h e i g h t = Gui . i c o n H e i g h t + Gui . i c o n M a r g i n p r i v a t e javax . swing . JLabel
∗ 2; jLabelSpinnerMargin ;
int w i d t h = Gui . i c o n W i d t h + Gui . i c o n M a r g i n ∗ p r i v a t e javax . swing . JLabel j L a b e l S p i n n e r S c a l e
2; ;
p r o t e c t e d javax . swing . JLabel j L a b e l S t a t u s ;
w h i l e ( w i d t h + Gui . iconPosX > image . getWidth p r o t e c t e d javax . swing . JLabel jLabelSubimage ;
( ) + 1) { p r o t e c t e d javax . swing . JLabel jLabelTime ;

179
p r i v a t e javax . swing . JLabel jLabelTracking ; p r i v a t e j a v a x . s w i n g . JPopupMenu . S e p a r a t o r
p r i v a t e j a v a x . s w i n g . J L a b e l jLabelW ; jSeparatorExit ;
p r i v a t e j a v a x . s w i n g . J L a b e l jLabelW1 ; p r i v a t e j a v a x . s w i n g . JPopupMenu . S e p a r a t o r
p r i v a t e javax . swing . JLabel jLabelX ; jSeparatorLAF ;
p r i v a t e javax . swing . JLabel jLabelY ; p r i v a t e j a v a x . s w i n g . JPopupMenu . S e p a r a t o r
p r i v a t e j a v a x . s w i n g . JMenuBar jMenuBar ; jSeparatorRecentFiles ;
p r i v a t e j a v a x . s w i n g . JMenu jMenuEdit ; p r o t e c t e d javax . swing . JSpinner jSpinnerH ;
p r i v a t e j a v a x . s w i n g . JMenu j M e n u F i l e ; p r o t e c t e d javax . swing . JSpinner jSpinnerH1 ;
p r i v a t e j a v a x . s w i n g . JMenu jMenuHelp ; p r i v a t e javax . swing . JSpinner jSpinnerMargin ;
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemAbout ; p r o t e c t e d javax . swing . JSpinner j S p i n n e r N o i s e ;
p r i v a t e j a v a x . s w i n g . JMenuItem j M e n u I t e m D e l e t e p r i v a t e javax . swing . JSpinner j S p i n n e r S c a l e ;
; p r o t e c t e d javax . swing . JSpinner
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemExit ; jSpinnerTracking ;
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemFont ; p r o t e c t e d j a v a x . s w i n g . J S p i n n e r jSpinnerW ;
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemHelp ; p r o t e c t e d j a v a x . s w i n g . J S p i n n e r jSpinnerW1 ;
p r i v a t e j a v a x . s w i n g . JMenuItem j M e n u I t e m I n s e r t p r o t e c t e d javax . swing . JSpinner jSpinnerX ;
; p r o t e c t e d javax . swing . JSpinner jSpinnerY ;
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemMerge ; p r i v a t e javax . swing . JSplitPane
p r i v a t e j a v a x . s w i n g . JMenuItem jSplitPaneEditor ;
jMenuItemMergeTiff ; p r i v a t e j a v a x . s w i n g . JTabbedPane
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemOpen ; jTabbedPaneBoxData ;
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemSave ; p r i v a t e j a v a x . s w i n g . JTabbedPane
p r i v a t e j a v a x . s w i n g . JMenuItem jMenuItemSaveAs jTabbedPaneMain ;
; p r o t e c t e d javax . swing . JTable j T a b l e ;
p r i v a t e j a v a x . s w i n g . JMenuItem j M e n u I t e m S p l i t ; p r o t e c t e d j a v a x . s w i n g . JTextArea
p r i v a t e j a v a x . s w i n g . JMenuItem jTextAreaBoxData ;
jMenuItemSplitTiff ; p r o t e c t e d j a v a x . s w i n g . JTextArea
p r o t e c t e d j a v a x . s w i n g . JMenu jMenuLookAndFeel ; jTextAreaInput ;
p r o t e c t e d j a v a x . s w i n g . JMenu j M e n u R e c e n t F i l e s ; p r o t e c t e d j a v a x . s w i n g . JTextArea
p r i v a t e j a v a x . s w i n g . JMenu j M e n u S e t t i n g s ; j T ex t A r ea O u t pu t ;
p r i v a t e j a v a x . s w i n g . JMenu jMenuTools ; p r o t e c t e d j a v a x . s w i n g . JTextArea
p r i v a t e javax . swing . JPanel jPanel3 ; jTextAreaValidationResult ;
p r i v a t e javax . swing . JPanel jPanel4 ; p r o t e c t e d javax . swing . JTextField
p r i v a t e j a v a x . s w i n g . J P a n e l jPanelBoxView ; jTextFieldBootstrapLang ;
p r i v a t e javax . swing . JPanel jPanelButtons ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . JPanel jPanelChar ; jTextFieldChar ;
p r i v a t e j a v a x . s w i n g . J P a n e l jPanelCommand ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . JPanel j P a n e l C o n t r o l s ; jTextFieldCharacter ;
p r o t e c t e d javax . swing . JPanel jPanelCoord ; p r i v a t e javax . swing . JTextField
p r i v a t e javax . swing . JPanel j P a n e l E d i t o r ; jTextFieldCodepointValue ;
p r i v a t e javax . swing . JPanel jPanelFind ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . JPanel jPanelMain ; jTextFieldDataDir ;
p r i v a t e javax . swing . JPanel p r o t e c t e d javax . swing . JTextField
jPanelNorthContainer ; jTextFieldFileName ;
p r i v a t e javax . swing . JPanel j P a n e l S p i n n e r ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . JPanel j P a n e l S t a t u s ; jTextFieldFind ;
p r i v a t e javax . swing . JPanel j P a n e l S t a t u s 1 ; p r o t e c t e d javax . swing . JTextField
p r i v a t e j a v a x . s w i n g . J P a n e l jPanelTIFFBox ; jTextFieldLang ;
p r i v a t e javax . swing . JPanel j P a n e l T r a i n e r ; p r o t e c t e d javax . swing . JTextField
p r o t e c t e d javax . swing . JProgressBar jTextFieldOuputDir ;
jProgressBar1 ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . J S c r o l l P a n e j S c r o l l P a n e 1 ; jTextFieldPrefix ;
p r i v a t e javax . swing . J S c r o l l P a n e j S c r o l l P a n e 2 ; p r o t e c t e d javax . swing . JTextField
p r i v a t e javax . swing . J S c r o l l P a n e jTextFieldTessDir ;
jScrollPaneBoxData ; p r i v a t e j a v a x . s w i n g . JToolBar j T o o l B a r E d i t o r ;
p r i v a t e javax . swing . J S c r o l l P a n e p r i v a t e j a v a x . s w i n g . JToolBar
jScrollPaneCoord ; jToolBarGenerator ;
p r i v a t e javax . swing . J S c r o l l P a n e p r i v a t e j a v a x . s w i n g . JToolBar j T o o l B a r T r a i n e r ;
jScrollPaneImage ; // End o f v a r i a b l e s d e c l a r a t i o n //GEN−END:
p r i v a t e javax . swing . J S c r o l l P a n e variables
jScrollPaneText ; p r i v a t e JFrame h e l p t o p i c s F r a m e ;
p r i v a t e j a v a x . s w i n g . JPopupMenu . S e p a r a t o r }
jSeparatorAbout ;

Path = Tess2SpeechTrainer/src/jTessBoxEditor/src/net/sourceforge/
tessboxeditor/GuiWithEdit.java

/∗ ∗ i m p o r t j a v a . awt . R e c t a n g l e ;
∗ C o p y r i g h t @ 2011 Quan Nguyen i m p o r t j a v a . awt . e v e n t . A c t i o n E v e n t ;
∗ import java . u t i l . ArrayList ;
∗ L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n import java . u t i l . L i s t ;
2 . 0 ( t h e ” L i c e n s e ” ) ; you may n o t i m p o r t j a v a x . s w i n g . JOptionPane ;
∗ use t h i s f i l e except i n compliance with the import net . s o u r c e f o r g e . t e s s b o x e d i t o r . datamodel
L i c e n s e . You may o b t a i n a copy o f . TessBox ;
∗ the License at
∗ public class GuiWithEdit e x t e n d s GuiWithMRU {
∗ h t t p : / /www. a p a c h e . o r g / l i c e n s e s /LICENSE−2.0
∗ @O verr ide
∗ U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d v o i d j M e n u I t e m M e r g e A c t i o n P e r f o r m e d ( j a v a . awt .
to in writing , software event . ActionEvent evt ) {
∗ d i s t r i b u t e d under the L i c e n s e i s i f ( b o x e s == n u l l ) {
d i s t r i b u t e d on an ”AS I S ” BASIS , WITHOUT return ;
∗ WARRANTIES OR CONDITIONS OF ANY KIND , }
e i t h e r e x p r e s s or i m p l i e d . See the
∗ License f o r the s p e c i f i c language governing L i s t <TessBox> s e l e c t e d = b o x e s .
p e r m i s s i o n s and l i m i t a t i o n s u n d e r getSelectedBoxes () ;
∗ the License . i f ( s e l e c t e d . s i z e ( ) <= 1 ) {
∗/ JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e
package net . s o u r c e f o r g e . t e s s b o x e d i t o r ; s e l e c t more than one box f o r Merge
operation . ”) ;

180
return ; return ;
} } e l s e i f ( s e l e c t e d . s i z e ( ) > 1) {
/∗ JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e
∗ Added by Anter Aaron C u s t o d i o t o s e l e c t o n l y one box f o r S p l i t o p e r a t i o n .
save the h i g h l i g h t e d c h a r a ct e r ”) ;
∗/ return ;
f o r ( i n t i = 0 ; i < j T a b l e . getRowCount ( ) ; i }
++) {
i f ( j T a b l e . g e t M o d e l ( ) . g e t V a l u e A t ( i , 5 ) != boolean modifierKeyPressed = f a l s e ;
n u l l && ( b o o l e a n ) j T a b l e . g e t M o d e l ( ) . i n t modifiers = evt . getModifiers () ;
g e t V a l u e A t ( i , 5 ) == t r u e ) { i f ( ( m o d i f i e r s & A c t i o n E v e n t . CTRL MASK) ==
boxes . t o L i s t ( ) . get ( i ) . s e t S e l e c t e d ( true ) ; A c t i o n E v e n t . CTRL MASK
} | | ( m o d i f i e r s & A c t i o n E v e n t . ALT MASK) ==
} A c t i o n E v e n t . ALT MASK
| | ( m o d i f i e r s & A c t i o n E v e n t .META MASK) ==
i n t minX = I n t e g e r . MAX VALUE, minY = I n t e g e r A c t i o n E v e n t .META MASK) {
. MAX VALUE, maxX = 0 , maxY = 0 ; modifierKeyPressed = true ;
}
S t r i n g chrs = ”” ;
s h o r t page = 0 ; TessBox box = s e l e c t e d . g e t ( 0 ) ;
i n t index = 0 ; i n t i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box )
;
f o r ( TessBox box : s e l e c t e d ) { R e c t a n g l e r e c t = box . g e t R e c t ( ) ;
c h r s += box . g e t C h r s ( ) ; i f ( ! modifierKeyPressed ) {
page = box . g e t P a g e ( ) ; r e c t . w i d t h /= 2 ;
i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box ) ; tableModel . setValueAt ( S t r i n g . valueOf ( r e c t .
R e c t a n g l e r e c t = box . g e t R e c t ( ) ; width ) , index , 3) ;
minX = Math . min ( minX , r e c t . x ) ; } else {
minY = Math . min ( minY , r e c t . y ) ; r e c t . h e i g h t /= 2 ;
maxX = Math . max (maxX , r e c t . x + r e c t . w i d t h ) ; tableModel . setValueAt ( S t r i n g . valueOf ( r e c t .
maxY = Math . max (maxY , r e c t . y + r e c t . h e i g h t ) h e i g h t ) , index , 4) ;
; }
t h i s . b o x e s . remove ( box ) ;
} TessBox newBox = new TessBox ( box . g e t C h r s ( ) ,
new R e c t a n g l e ( r e c t ) , box . g e t P a g e ( ) ) ;
A r r a y L i s t <I n t e g e r > s e l e c t e d I n d e x = new newBox . s e t S e l e c t e d ( t r u e ) ;
A r r a y L i s t <>() ; // Added by Anter Aaron b o x e s . add ( i n d e x + 1 , newBox ) ;
Custodio R e c t a n g l e newRect = newBox . g e t R e c t ( ) ;
i f ( ! modifierKeyPressed ) {
i f ( chrs . length ( ) > 0) { newRect . x += newRect . w i d t h ;
TessBox newBox = new TessBox ( c h r s , new } else {
R e c t a n g l e ( minX , minY , maxX − minX , maxY − newRect . y += newRect . h e i g h t ;
minY ) , page ) ; }
newBox . s e t S e l e c t e d ( t r u e ) ;
b o x e s . add ( i n d e x , newBox ) ; O b j e c t [ ] newRow = {newBox . g e t C h r s ( ) , newRect
i n t t a b l e I n d e x = t h i s . boxes . t o L i s t ( ) . . x , newRect . y , newRect . width , newRect .
i n d e x O f ( newBox ) ; height };
t a b l e M o d e l . i n s e r t R o w ( i n d e x + 1 , newRow ) ;
/∗ jTable . s e t R o w S e l e c t i o n I n t e r v a l ( index , index
∗ Added by Anter Aaron C u s t o d i o + 1) ;
∗/ resetReadout () ;
f o r ( i n t i = 0 ; i < boxes . t o L i s t ( ) . s i z e ( ) ; t h i s . jLabelImage . repaint ( ) ;
i ++) { updateSave ( t r u e ) ;
i f ( boxes . t o L i s t ( ) . get ( i ) . i s S e l e c t e d ( ) ) { }
s e l e c t e d I n d e x . add ( i ) ;
} @O verr ide
} v o i d j M e n u I t e m I n s e r t A c t i o n P e r f o r m e d ( j a v a . awt .
event . ActionEvent evt ) {
i f ( b o x e s == n u l l ) {
tableModel . setDataVector ( boxes . return ;
g e t T a b l e D a t a L i s t ( ) . t o A r r a y ( new S t r i n g }
[ 0 ] [ 5 ] ) , headers ) ; L i s t <TessBox> s e l e c t e d = b o x e s .
t h i s . jTable . setRowSelectionInterval ( getSelectedBoxes () ;
tableIndex , tableIndex ) ; i f ( s e l e c t e d . s i z e ( ) <= 0 ) {
Rectangle r e c t = t h i s . jTable . getCellRect ( JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e
tableIndex , 0 , true ) ; s e l e c t t h e box t o i n s e r t a f t e r . ” ) ;
t h i s . jTable . scrollRectToVisible ( rect ) ; return ;
} } e l s e i f ( s e l e c t e d . s i z e ( ) > 1) {
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e
/∗ s e l e c t o n l y one box f o r I n s e r t o p e r a t i o n
∗ Added by Anter Aaron C u s t o d i o Get . ”) ;
a l l the h i g h l i g h t e d boxes a f t e r return ;
r e m o v i n g merged b o x e s }
∗/
for ( int i = 0; i < selectedIndex . size () ; i TessBox box = s e l e c t e d . g e t ( 0 ) ;
++) { i n t i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box )
j T a b l e . getModel ( ) . setValueAt ( true , ;
s e l e c t e d I n d e x . get ( i ) , 5) ; i n d e x ++;
} TessBox newBox = new TessBox ( box . g e t C h r s ( ) ,
new R e c t a n g l e ( box . g e t R e c t ( ) ) , box . g e t P a g e
t h i s . jLabelImage . repaint ( ) ; () ) ;
updateSave ( t r u e ) ; newBox . s e t S e l e c t e d ( t r u e ) ;
b o x e s . add ( i n d e x , newBox ) ;
R e c t a n g l e newRect = newBox . g e t R e c t ( ) ;
j T a b l e . getColumnModel ( ) . removeColumn ( j T a b l e . newRect . x += 1 5 ; // o f f s e t t h e new box 15
getColumnModel ( ) . getColumn ( 5 ) ) ; p i x e l from t h e b a s e one
} O b j e c t [ ] newRow = {newBox . g e t C h r s ( ) , newRect
. x , newRect . y , newRect . width , newRect .
@O verr ide height };
v o i d j M e n u I t e m S p l i t A c t i o n P e r f o r m e d ( j a v a . awt . t a b l e M o d e l . i n s e r t R o w ( i n d e x , newRow ) ;
event . ActionEvent evt ) { jTable . s e t R o w S e l e c t i o n I n t e r v a l ( index , index )
i f ( b o x e s == n u l l ) { ;
return ; t h i s . jLabelImage . repaint ( ) ;
} updateSave ( t r u e ) ;
L i s t <TessBox> s e l e c t e d = b o x e s . }
getSelectedBoxes () ;
i f ( s e l e c t e d . s i z e ( ) <= 0 ) { @O verr ide
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e v o i d j M e n u I t e m D e l e t e A c t i o n P e r f o r m e d ( j a v a . awt .
s e l e c t a box t o s p l i t . ” ) ; event . ActionEvent evt ) {

181
i f ( b o x e s == n u l l ) { t h i s . jLabelImage . repaint ( ) ;
return ; updateSave ( t r u e ) ;
} }
L i s t <TessBox> s e l e c t e d = b o x e s .
getSelectedBoxes () ; /∗ ∗
i f ( s e l e c t e d . s i z e ( ) <= 0 ) { ∗ @param a r g s t h e command l i n e a r g u m e n t s
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , ” P l e a s e ∗/
s e l e c t a box o r more t o d e l e t e . ” ) ; p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
return ; j a v a . awt . EventQueue . i n v o k e L a t e r ( new Runnable
} () {

f o r ( TessBox box : s e l e c t e d ) { @O verr ide


i n t i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box p u b l i c v o i d run ( ) {
); new GuiWithEdit ( ) . s e t V i s i b l e ( t r u e ) ;
t h i s . b o x e s . remove ( box ) ; }
t a b l e M o d e l . removeRow ( i n d e x ) ; }) ;
} }
}
resetReadout () ;

Path = Tess2SpeechTrainer/jTessBoxEditor/src/net/sourceforge/tessboxeditor/
GuiWithSpinner.java

/∗ ∗ ;
∗ C o p y r i g h t @ 2 0 0 1 1 Quan Nguyen
∗ box . s e t C h r s ( t h i s . j T e x t F i e l d C h a r a c t e r . g e t T e x t
∗ L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n () ) ;
2.0 ( the ” License ”) ; t a b l e M o d e l . s e t V a l u e A t ( box . g e t C h r s ( ) , i n d e x ,
∗ you may n o t u s e t h i s f i l e e x c e p t i n 0) ;
compliance with the L i c e n s e . R e c t a n g l e r e c t = box . g e t R e c t ( ) ;
∗ You may o b t a i n a copy o f t h e L i c e n s e a t JSpinner sp = ( JSpinner ) e v t . g e t S o u r c e ( ) ;
∗ i f ( s p == t h i s . j S p i n n e r X ) {
∗ h t t p : / /www. a p a c h e . o r g / l i c e n s e s /LICENSE−2.0 r e c t . x = ( I n t e g e r ) t h i s . jSpinnerX . getValue
∗ () ;
∗ U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d tableModel . setValueAt ( S t r i n g . valueOf ( r e c t . x
to in writing , software ) , index , 1) ;
∗ d i s t r i b u t e d under the L i c e n s e i s } e l s e i f ( s p == t h i s . j S p i n n e r Y ) {
d i s t r i b u t e d on an ”AS I S ” BASIS , r e c t . y = ( I n t e g e r ) t h i s . jSpinnerY . getValue
∗ WITHOUT WARRANTIES OR CONDITIONS OF ANY () ;
KIND , e i t h e r e x p r e s s o r i m p l i e d . tableModel . setValueAt ( S t r i n g . valueOf ( r e c t . y
∗ See the L i c e n s e f o r the s p e c i f i c language ) , index , 2) ;
g o v e r n i n g p e r m i s s i o n s and } e l s e i f ( s p == t h i s . jSpinnerW ) {
∗ l i m i t a t i o n s under the L i c e n s e . r e c t . w i d t h = ( I n t e g e r ) t h i s . jSpinnerW .
∗/ getValue ( ) ;
package net . s o u r c e f o r g e . t e s s b o x e d i t o r ; tableModel . setValueAt ( S t r i n g . valueOf ( r e c t .
width ) , index , 3) ;
i m p o r t j a v a . awt . Image ; } e l s e i f ( s p == t h i s . j S p i n n e r H ) {
i m p o r t j a v a . awt . R e c t a n g l e ; r e c t . height = ( I n t e g e r ) t h i s . jSpinnerH .
i m p o r t j a v a . awt . image . B u f f e r e d I m a g e ; getValue ( ) ;
import java . u t i l . L i s t ; tableModel . setValueAt ( S t r i n g . valueOf ( r e c t .
import java . u t i l . l o g g i n g . Level ; h e i g h t ) , index , 4) ;
import java . u t i l . l o g g i n g . Logger ; }
import javax . swing . Icon ;
import javax . swing . ImageIcon ; Icon icon = jLabelImage . getIcon ( ) ;
import javax . swing . JSpinner ; try {
import net . s o u r c e f o r g e . t e s s b o x e d i t o r . Image subImage = g e t S u b i m a g e ( ( B u f f e r e d I m a g e
components . I m a g e I c o n S c a l a b l e ; ) ( ( ImageIcon ) i c o n ) . getImage ( ) , r e c t ) ;
import net . s o u r c e f o r g e . t e s s b o x e d i t o r . datamodel I m a g e I c o n S c a l a b l e s u b I c o n = new
. TessBox ; I m a g e I c o n S c a l a b l e ( subImage ) ;
subIcon . setScaledFactor ( s c a l e F a c t o r ) ;
p u b l i c c l a s s GuiWithSpinner e x t e n d s jLabelSubimage . s e t I c o n ( subIcon ) ;
GuiWithEdit { } catch ( Exception e ) {
p r i v a t e f i n a l s t a t i c Logger l o g g e r = Logger . l o g g e r . l o g ( L e v e l .WARNING, e . g e t M e s s a g e ( ) , e
g e t L o g g e r ( GuiWithSpinner . c l a s s . getName ( ) ) );
; }
t h i s . jLabelImage . repaint ( ) ;
@O verr ide updateSave ( t r u e ) ;
void stateChanged ( javax . swing . event . }
ChangeEvent e v t ) {
i f ( tableSelectAction ) { /∗ ∗
return ; ∗ @param a r g s t h e command l i n e a r g u m e n t s
} ∗/
L i s t <TessBox> s e l e c t e d = b o x e s . p u b l i c s t a t i c v o i d main ( S t r i n g a r g s [ ] ) {
getSelectedBoxes () ; j a v a . awt . EventQueue . i n v o k e L a t e r ( new Runnable
i f ( s e l e c t e d . s i z e ( ) <= 0 ) { () {
return ;
} e l s e i f ( s e l e c t e d . s i z e ( ) > 1) { @O verr ide
// JOptionPane . s h o w M e s s a g e D i a l o g ( p u b l i c v o i d run ( ) {
t h i s , ” S e l e c t o n l y one box f o r S p i n n e r new GuiWithSpinner ( ) . s e t V i s i b l e ( t r u e ) ;
operation .”) ; }
return ; }) ;
} }
}
TessBox box = s e l e c t e d . g e t ( 0 ) ;
i n t i n d e x = t h i s . b o x e s . t o L i s t ( ) . i n d e x O f ( box )

Path = Tess2SpeechTrainer/jTessBoxEditor/src/net/sourceforge/tessboxeditor/

182
GuiWithValidator.java

/∗ ∗ jFileChooserValidatingImage .
∗ C o p y r i g h t @ 2013 Quan Nguyen s e t C u r r e n t D i r e c t o r y ( t r a i n D a t a D i r e c t o r y ==
∗ n u l l ? n u l l : new F i l e (
∗ L i c e n s e d u n d e r t h e Apache L i c e n s e , V e r s i o n trainDataDirectory ) ) ;
2 . 0 ( t h e ” L i c e n s e ” ) ; you may n o t
∗ use t h i s f i l e except i n compliance with the // p e r f o r m OCR on t h e t r a i n i n g image
L i c e n s e . You may o b t a i n a copy o f i f ( jFileChooserValidatingImage .
∗ the License at showOpenDialog ( t h i s ) == J F i l e C h o o s e r .
∗ APPROVE OPTION) {
∗ h t t p : / /www. a p a c h e . o r g / l i c e n s e s /LICENSE−2.0 jButtonValidate . setEnabled ( f a l s e ) ;
∗ t h i s . jTextAreaValidationResult . setText ( n u l l
∗ U n l e s s r e q u i r e d by a p p l i c a b l e law o r a g r e e d );
to in writing , software j L a b e l S t a t u s . setText ( bundle . g e t S t r i n g ( ”
∗ d i s t r i b u t e d under the L i c e n s e i s OCR running . . . ” ) ) ;
d i s t r i b u t e d on an ”AS I S ” BASIS , WITHOUT jProgressBar1 . setIndeterminate ( true ) ;
∗ WARRANTIES OR CONDITIONS OF ANY KIND , jProgressBar1 . s e t S t r i n g ( bundle . g e t S t r i n g ( ”
e i t h e r e x p r e s s or i m p l i e d . See the OCR running . . . ” ) ) ;
∗ License f o r the s p e c i f i c language governing jProgressBar1 . s e t V i s i b l e ( true ) ;
p e r m i s s i o n s and l i m i t a t i o n s u n d e r getGlassPane ( ) . s e t C u r s o r ( Cursor .
∗ the License . g e t P r e d e f i n e d C u r s o r ( C u r s o r . WAIT CURSOR) ) ;
∗/ getGlassPane ( ) . s e t V i s i b l e ( true ) ;
package net . s o u r c e f o r g e . t e s s b o x e d i t o r ;
File imageFile =
i m p o r t j a v a . awt . C u r s o r ; jFileChooserValidatingImage .
import java . i o . F i l e ; getSelectedFile () ;
import java . i o . FileNotFoundException ; L i s t <F i l e > f i l e s = new A r r a y L i s t <F i l e >() ;
import java . i o . IOException ; f i l e s . add ( i m a g e F i l e ) ;
import java . u t i l . ArrayList ;
import java . u t i l . L i s t ; // i n s t a n t i a t e SwingWorker f o r OCR
import java . u t i l . l o g g i n g . Level ; ocrWorker = new OcrWorker ( f i l e s ) ;
import java . u t i l . l o g g i n g . Logger ; ocrWorker . e x e c u t e ( ) ;
import javax . swing . JFileChooser ; }
i m p o r t j a v a x . s w i n g . JOptionPane ; }
i m p o r t j a v a x . s w i n g . SwingWorker ;
import javax . swing . f i l e c h o o s e r . F i l e F i l t e r ; @O verr ide
import s t a t i c net . s o u r c e f o r g e . t e s s b o x e d i t o r . void jButtonCloseDialogActionPerformed ( java .
G u i W i t h T r a i n e r . DIALOG TITLE ; awt . e v e n t . A c t i o n E v e n t e v t ) {
i m p o r t n e t . s o u r c e f o r g e . v i e t o c r .OCR; this . jDialogValidationResult . setVisible (
i m p o r t n e t . s o u r c e f o r g e . v i e t o c r . OCRFiles ; false ) ;
i m p o r t n e t . s o u r c e f o r g e . v i e t p a d . components . }
SimpleFilter ;
/∗ ∗
p u b l i c c l a s s GuiWithValidator extends ∗ A w o r k e r c l a s s f o r managing OCR p r o c e s s
GuiWithTrainer { .
∗/
private JFileChooser c l a s s OcrWorker e x t e n d s SwingWorker<Void ,
jFileChooserValidatingImage ; String> {
p r i v a t e OcrWorker ocrWorker ;
L i s t <F i l e > f i l e s ;
p r i v a t e f i n a l s t a t i c Logger l o g g e r = Logger .
g e t L o g g e r ( G u i W i t h V a l i d a t o r . c l a s s . getName OcrWorker ( L i s t <F i l e > f i l e s ) {
() ) ; this . f i l e s = f i l e s ;
}
p u b l i c GuiWithValidator ( ) {
initComponents ( ) ; @Ov err ide
} p r o t e c t e d Void doInBackground ( ) t h r o w s
Exception {
private void initComponents ( ) { OCR<F i l e > o c r E n g i n e = new OCRFiles (
tessDirectory ) ;
j F i l e C h o o s e r V a l i d a t i n g I m a g e = new ocrEngine . setDatapath ( trainDataDirectory ) ;
JFileChooser () ; ocrEngine . setLanguage ( jTextFieldLang .
jFileChooserValidatingImage . getText ( ) ) ;
setAcceptAllFileFilterUsed ( false ) ;
jFileChooserValidatingImage . f o r ( i n t i = 0 ; i < f i l e s . s i z e ( ) ; i ++) {
setApproveButtonText ( ” S e l e c t ” ) ; i f (! isCancelled () ) {
jFileChooserValidatingImage . setDialogTitle (” String r e s u l t = ocrEngine . recognizeText (
S e l e c t Image F i l e ” ) ; f i l e s . subList ( i , i + 1) ) ;
F i l e F i l t e r a l l I m a g e s F i l t e r = new p u b l i s h ( r e s u l t ) ; // i n t e r i m r e s u l t
S i m p l e F i l t e r ( ”bmp ; j p g ; j p e g ; png ; t i f ; t i f f ” , }
” A l l Images ” ) ; }
jFileChooserValidatingImage . s e t F i l e F i l t e r (
allImagesFilter ) ; return null ;
}
}
@Ov err ide
@O verr ide p r o t e c t e d v o i d p r o c e s s ( L i s t <S t r i n g > r e s u l t s )
v o i d j B u t t o n V a l i d a t e A c t i o n P e r f o r m e d ( j a v a . awt . {
event . ActionEvent evt ) { for ( String str : results ) {
S t r i n g lang = t h i s . jTextFieldLang . getText ( ) ; j T e x t A r e a V a l i d a t i o n R e s u l t . append ( s t r ) ;
F i l e t e s s d a t a = new F i l e ( t r a i n D a t a D i r e c t o r y , jTextAreaValidationResult . setCaretPosition
” tessdata ”) ; ( j T e x t A r e a V a l i d a t i o n R e s u l t . getDocument ( ) .
F i l e t r a i n e d d a t a = new F i l e ( t e s s d a t a , l a n g + getLength ( ) ) ;
” . traineddata ”) ; }
i f ( ! traineddata . exists () ) { }
S t r i n g m e s s a g e = S t r i n g . f o r m a t ( ”%s .
t r a i n e d d a t a d o e s n o t e x i s t i n %s . Be s u r e @Ov err ide
t o run t r a i n i n g f i r s t . ” , l a n g , t e s s d a t a . p r o t e c t e d v o i d done ( ) {
getPath ( ) ) ; jProgressBar1 . setIndeterminate ( f a l s e ) ;
JOptionPane . s h o w M e s s a g e D i a l o g ( t h i s , message
, DIALOG TITLE , JOptionPane . ERROR MESSAGE try {
); g e t ( ) ; // dummy method
return ; j L a b e l S t a t u s . setText ( bundle . g e t S t r i n g ( ”
} OCR completed . ” ) ) ;
jProgressBar1 . s e t S t r i n g ( bundle . g e t S t r i n g ( ”

183
OCR completed . ” ) ) ; e) ;
} catch ( InterruptedException ignore ) { j L a b e l S t a t u s . s e t T e x t ( ”OCR ” + b u n d l e .
l o g g e r . l o g ( L e v e l .WARNING, i g n o r e . getString (” canceled ”) ) ;
getMessage ( ) , i g n o r e ) ; j P r o g r e s s B a r 1 . s e t S t r i n g ( ”OCR ” + b u n d l e .
} catch ( java . u t i l . concurrent . getString (” canceled ”) ) ;
ExecutionException e ) { } finally {
S t r i n g why ; getGlassPane ( ) . s e t C u r s o r ( Cursor .
Throwable c a u s e = e . g e t C a u s e ( ) ; g e t P r e d e f i n e d C u r s o r ( C u r s o r . DEFAULT CURSOR
i f ( c a u s e != n u l l ) { ));
i f ( cause i n s t a n c e o f IOException ) { getGlassPane ( ) . s e t V i s i b l e ( f a l s e ) ;
why = b u n d l e . g e t S t r i n g ( ” jButtonValidate . setEnabled ( true ) ;
Cannot find Tesseract . jDialogValidationResult . s e t V i s i b l e ( true ) ;
Please set its path . ”) ; }
} e l s e i f ( cause i n s t a n c e o f }
FileNotFoundException ) { }
why = b u n d l e . g e t S t r i n g ( ”
l e∗ r e c o g n i z i n g t h i s i m a g e
A n e x c e p t i o n o c c u r r e d i n T e s s e r a c t e n g i n e w h i/∗
. ”) ; ∗ @param a r g s t h e command l i n e a r g u m e n t s
} else { ∗/
why = c a u s e . g e t M e s s a g e ( ) ; p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
}
} else { j a v a . awt . EventQueue . i n v o k e L a t e r ( new Runnable
why = e . g e t M e s s a g e ( ) ; () {
}
@O verr ide
l o g g e r . l o g ( L e v e l . SEVERE, why , e ) ; p u b l i c v o i d run ( ) {
jLabelStatus . setText ( n u l l ) ; new G u i W i t h V a l i d a t o r ( ) . s e t V i s i b l e ( t r u e ) ;
jProgressBar1 . setString ( null ) ; Gui . f i n i s h e d = t r u e ;
JOptionPane . s h o w M e s s a g e D i a l o g ( n u l l , why , }
DIALOG TITLE , JOptionPane . ERROR MESSAGE) ; }) ;
} catch ( java . u t i l . concurrent . }
CancellationException e ) { }
l o g g e r . l o g ( L e v e l .WARNING, e . g e t M e s s a g e ( ) ,

184
XI. Acknowledgment

Woooh! Sa wakas! Ito na ang part na inaabangan kong isulat dahil bukod sa
pwede na akong mag-tagalog dito, ibigsabihin na rin nito ay natapos ko na ”Special
Problem” ko.
Unang-una sa lahat, gusto kong pasalamatan ang aking pamilya dahil sa
walang sawang pagsuporta nila sa akin habang ginagawa ko ang thesis ko. Lahat
ng mga bagay na kailangan ko ay ibinibigay nila kahit medyo marami at medyo
magastos. Gusto ko rin magpasalamat sa kanila dahil sa tiwalang ibinigay nila sa
akin. Kahit isang beses ay hindi nila pinagdudahan ang kakayahan kong tapusin
ang thesis ko, kahit minsan ako mismo ang nagdududa sa sarili ko kung kaya ko
ba talagang tapusin ’to.
Gusto ko rin pasalamatan si Sir Greg Baes dahil siya ang nag-guide sa akin
upang maging maayos at magkaroon ng direksyon ang thesis ko. Kahit medyo
hassle pumunta sa school niya kapag magpapaconsult ka, medyo harsh magsalita
(lol), at maraming pinapagawa, alam ko namang ginagawa niya ang lahat ng iyon
para sa ikabubuti ng thesis ko. Gusto ko rin magpasalamat sa pagbibigay niya
ng tiwala sa akin na kahit next week pa dapat talaga ako magde-defense, pinag-
defense na niya ako ng araw na iyon. Medyo nakakabigla dahil hindi pa talaga
ako prepared noon at hindi ko pa talaga nade-debug yung app ko, pero nagtiwala
siya na okay na akong magdefense. Maraming salamat po at sorry din po sir sa
abala sa schedule ninyo minsan.
Salamat din kay deep learning lord Sir Marvin Ignacio na kahit hindi namin
siya adviser, hinahayaan pa rin niya kami na magpa-consult sa kanya. Siya ang
napapagtanungan ko ng mga bagay na related sa Machine Learning at training
algorithms. Maraming salamat ulit sir! LEARNING!
Siyempre gusto ko rin pasalamatan ang 2012 Block 12 B.S. Computer Science
students dahil kahit na shiftee ako, tinanggap pa rin nila ako. Medyo late ko
na nga lang sila nakakausap at nakakabiruan dahil mahiyain talaga ako kapag
hindi ko pa kilala ang mga kasama ko. Sorry medyo late ko na kayo naka-close

185
pero kahit ganoon, naging masaya pa rin naman ako sa mga kalokohan natin sa
maiksing panahon na ’yon. Gusto kong sabihin na masayang kasama ang block
niyo. Salamat din sa pagbigay niyo ng tiwala sa akin na kaya kong tapusin ang
thesis ko. Salamat sa pagsabi sa akin palagi ng ”Kaya mo ’yan, ikaw pa!” at pag-
pressure sakin na i-meet ang expectations niyo. Dahil doon, nagawa ko talagang
ibigay ang lahat ng kakayahan ko upang matapos ang thesis na ito.
Salamat U.P. Manila sa limang taon na pagpapa-realize sa akin na marami pa
akong dapat matutunan. Salamat sa pag-challenge sa akin at pagpapakita sa akin
na hindi sapat na matalino ka noong highschool, dahil pagdating mo sa U.P., doon
masusubok kung gaano ka talagang katalino. Pero ’di pala talaga ako ganoong
katalino tulad ng iniisip ko. Looool!
Syempre makakalimutan ko ba na pasalamatan ang pinaka-tumulong sa akin?
Siya ang nandiyan sa tuwing may problema ako. Maraming salamat Stack Over-
flow!! Hindi ko ito matatapos ng wala ka. You da real MVP!
Inaalay ko sa inyong lahat ang thesis na ito. Kung wala kayo, hindi ko ito
matatapos. Maraming maraming salamat talaga sa pagbibigay ninyo ng tiwala at
suporta sa akin. Good Bye U.P.?

186

Das könnte Ihnen auch gefallen