Titol Java applet for the MPEG-7 annotation of rectangular regions
Document Sample


Diego Cant Java applet for the MPEG-7
annotation of rectangular
regions in still images
Titol: “Java applet for the MPEG-7 annotation of rectangular
regions in still images”
Alumne: Diego Cant
Director: Xavier Giró i Nieto
Department: EUETIT
Data: Spring 2007
Table of Contents
1 Introduction................................................................................................................................ 4
2 Requirements ............................................................................................................................ 7
3 State of the Art............................................................................................................................ 9
3.1 Existing Annotation Tools and Formats.............................................................................. 9
3.1.1 Introduction................................................................................................................. 9
Metadata......................................................................................................................... 9
a.1 What is metadata?................................................................................................. 9
a.2 Use of metadata .................................................................................................. 10
b XML........................................................................................................................... 11
b.1 Introduction......................................................................................................... 11
3.1.2 Mpeg-7...................................................................................................................... 12
a Introduction................................................................................................................ 12
b Overview of all MPEG-standards............................................................................... 12
c Why MPEG-7............................................................................................................. 14
d What is MPEG-7........................................................................................................ 15
3.1.3 Existing Annotation Tools......................................................................................... 16
a What is an Annotation Tool........................................................................................ 17
b The Common Aim...................................................................................................... 17
c Different Approaches to Image Annotation................................................................. 17
d Examples.................................................................................................................... 19
d.1 FOTOTAGGER................................................................................................. 19
d.2 MUSCLE ANNOTATE..................................................................................... 20
d.3 VIDEOTATER .................................................................................................. 22
d.4 LABELME......................................................................................................... 23
3.2 Java-Applets...................................................................................................................... 25
3.2.1 What is a Java Applet................................................................................................ 25
3.2.2 Advantages of Applets............................................................................................... 26
3.2.3 Disadvantages of applets........................................................................................... 27
3.3 Open Source Development using Eclipse and SVN........................................................... 28
3.3.1 What is 'open source'?................................................................................................ 28
3.3.2 What is SVN?........................................................................................................... 28
3.3.3 SVN-Techniques....................................................................................................... 29
a Lock-Modify-Unlock.................................................................................................. 29
b Copy-Modify-Merge................................................................................................... 30
4 Implementation ........................................................................................................................ 31
4.1 Applet............................................................................................................................... 31
4.1.1 Architecture............................................................................................................... 31
a UML-SCHEME.......................................................................................................... 31
b Description of Classes................................................................................................. 33
b.1 Annotator.class.................................................................................................... 33
b.2 FileSelector class................................................................................................. 33
b.3 Textfile.class....................................................................................................... 34
4.1.2 MPEG-7.................................................................................................................... 34
a MPEG-7 Scheme........................................................................................................ 34
b Created Classes........................................................................................................... 35
4.1.3 Creation of Jar-file..................................................................................................... 36
a Creation of a Jar-File.................................................................................................. 36
Page 2 of 87
4.1.4 Applet Signature........................................................................................................ 37
a Keytool....................................................................................................................... 38
b Jarsigner..................................................................................................................... 39
4.1.5 How to put an Applet Online?................................................................................... 39
a HTML-Code............................................................................................................... 39
b Comments................................................................................................................... 40
4.2 Development..................................................................................................................... 40
4.2.1 Creation and Configuration of an Eclipse project....................................................... 40
a Create a New Project.................................................................................................. 40
b Packages..................................................................................................................... 41
b.1 Introduction......................................................................................................... 41
b.2 Creation of a package in Eclipse......................................................................... 42
c Creation of a New Class.............................................................................................. 43
d Configure Classpath.................................................................................................... 44
4.2.2 SVN Repository Access With SubEclipse.................................................................. 45
a Installation of SubEclipse............................................................................................ 45
b Configuring Eclipse to Connect with the repository.................................................... 46
5 Results...................................................................................................................................... 50
5.1 Example of annotation, starting from Eclipse.................................................................... 50
a Run the Project in Eclipse........................................................................................... 50
b Select an Image from your hard drive......................................................................... 51
c The Image Loads and Selection of a Rectangular Region............................................ 51
d The 'send coordinates' button....................................................................................... 53
5.1.2 Example of Annotation, starting in a Web Browser................................................... 55
6 Future Work............................................................................................................................. 56
7 Conclusion................................................................................................................................ 58
Page 3 of 87
1 Introduction
The amount of multimedia documents have faced an exponential increase during the past ten
years, promoted by Internet and an-ever advancing technology. Today, everyone has a camera and
wants to publish pictures. It is however difficult to retrieve desired documents (image, audio, video and
so on) or contents.
Nowadays, libraries and other organizations use annotations to index these contents. They put
metadata on a document which describes its contents with keywords. This allows retrieval programs to
work with simple queries, so they easily can search their databases. Existing software for indexing
these multimedia documents can be found on the internet, and a few of them are discussed in the “State
of the Art” chapter.
The main goal of this Java applet is to save the coordinates of a rectangle in a MPEG-7-file; the
applet must be available on a web server so that the user can run it embedded in his/her web browser.
The MPEG-7-file is meant to be used in a future applications in order to detect objects in this
rectangular area of the image.
Page 4 of 87
This thesis is organized as follows: “The State of the Art” starts with an introduction on MPEG-
7, followed by examples of existing image annotation tools which are found on the internet. In the end
we discuss applet technology in general, with a detailed description of the advantages and
disadvantages of the use of it.The “ Implementations” chapter first gives a detailed description on the
Java-applet itself (
architecture of the source code, MPEG-7-scheme, JAR-file,...). Then section on 'development' explains
the eclipse in general and its specific configuration in order to access the repository with Subversion.In
the next chapter (“Results”) we give a detailed example to explain the usage and the working of the
applet. Every step of the annotation of an image gets discussed in order to give the reader of this
document a complete view on the results of the project.
“Java applet for the MPEG-7 annotation of rectangular regions in still images” is the title of this
diplome thesis written by Diego Cant and supervised by Xavier Giró i Nieto, professor of the “Signal
Theory and Communications Department (TSC)” of the Technical University of Catalonia (UPC).
Page 5 of 87
Chapter 2 Requirements
2 Requirements
The most important requirement was to create an annotation tool for still images, which can
capture the coordinates from a rectangular region in an image through the mouse. The applet had to
show the image on screen and mark the rectangular boundaries of the region through a click & drag
operation.
The next demand was to develop it as a web-based Java applet usable from any platform
(GNU/Linux, MacOSX and Microsoft Windows) and browser (Firefox, Safari and Microsoft Internet
Explorer). As the applet had to access the local file system, it needed to be signed with a valid digital
signature provided by the TSC department. The applet has to be publicly available for demo from the
TSC department webserver in the Terrassa laboratori.
In a first stage, the coordinates had to be written in a text-file in the hard disk. User should be able to
browse through the local filesystem to select the desired path and filename.
In a second stage, the output format had to be able to accessible to other programs or software
using the MPEG-7 textual-based format. This MPEG-7 gets saved in the same location as the text-file,
with the same name, but with an mp7 extension.
Page 6 of 87
Chapter 2 Requirements
In order to be used by other software and developers, the final source code had to be publicly
available in the repository from the Càtedra de Programari Lliure de la UPC and released under a GPL
license. The same repository will provide a SVN version tracking system to allow a fluid
communication and testing between student and advisor.
Page 7 of 87
Chapter 3 State Of the Art
3 State of the Art
To understand how annotation tools work, we will first give an introduction on metadata and XML,
which is needed to be able to comprehend the next paragraph: MPEG-7. In the end of this chapter, I
discuss the most important and existing annotation tools at the current time.
3.1 Existing Annotation Tools and Formats
3.1.1 Introduction
Metadata
a.1 What is metadata?
Metadata is data on data, in that metadata gives us information about a certain piece of data.
For example you receive the message:
1. 037755506
2. 133
3. Perstraat
....
This message has absolutely no meaning if you have no knowledge of the format used to pass data. In
Page 8 of 87
Chapter 3 State Of the Art
this example it was;
1. telephone number
2. street number
3. street
....
a.2 Use of metadata
Metadata has many different applications, this section lists some of the most common ones.
Metadata is used to speed up and enrich searching for resources[WIK]. In general, search queries using
metadata can save users from performing more complex filter operations manually. It is now common
for web browsers (with the exception of Mozilla Firefox, P2P applications and media management
software) to automatically download and locally cache metadata, to improve the speed at which files
can be accessed and searched.
Metadata provide additional information to users of the data it describes. This information may
be descriptive ("These pictures were taken by children in the school's third grade class.") or algorithmic
("Checksum=139F").
Metadata helps to close the semantic-gap. It explains to the computer how data items are related
to each other and how these relations can be processed automatically, it makes it possible to process
even more complex filter and search operations. For example, if a search engine understands that
"ronaldo" was a "football player", it can respond to a search query on "Football Players" with a link to
Page 9 of 87
Chapter 3 State Of the Art
a web page about Ronaldo, even though the exact words "Football Player" never occur on that page.
Certain metadata is developed to improve lossy compression algorithms. For example, if a
video has metadata that allows a computer to make difference between foreground and background,
the latter can be compressed more raw to achieve a higher compression rate.
Some metadata is meant to enable variable content presentation. For example, if a picture has
metadata that indicates the most important region — the one where there is a person — an image
viewed on a small screen, such as on a mobile phone, can narrow the picture to that region and thus
show the user the most interesting details. This is, essentially , the goal of the annotation tool that I
made in this project: to pick out a certain part of an image, so that a next program can put the focus
onto this part.
b XML
b.1 Introduction
The extensible Markup Language, or XML, is a portable, human-readable format for
exchanging text or data between programs [XML2]. XML is derived from the parent standard SGML.
Also HTML, the language used on web pages worldwide, comes from SGML. IBM's GML (General
Markup Language) on his turn is the parent of SGML. Also, there is MIF (Maker Interchange Format)
from Adobe, also derived from GML, but different from SGML [XML1].
Page 10 of 87
Chapter 3 State Of the Art
Figure 3.1 XML's Ancestors,[XML1]
It can be said that XML is an improved version of HTML, consolidated, and that you can
define your own tags. In other words, XML is a general interchange format for things such as human-
editable description of things and is as diverse as word-processing files and Java documents.
3.1.2 Mpeg-7
a Introduction
The value of information often depends on how easily it can be found, retrieved, accessed and
managed. In case of audiovisual archives, it is impossible to find a certain archive if everybody uses a
different metadata scheme. MPEG-7 delivers a solution, by describing multimedia content in a
standardized way, and thus enabling easier archiving, accessing, locating,....audiovisual information.
Later, a more detailed chapter on MPEG-7 follows. [MPOV]
b Overview of all MPEG-standards
MPEG (Motion Picture Expert Group) is a working group of ISO/IEC since the end of the 80's.
The aim of MPEG is to develop international standards for compression, decompression and processing
of audio and video. They already developed several MPEG-standards [MP7W].
Page 11 of 87
Chapter 2 Requirements
The MPEG-1 compression standard dates from 1992. It design was meant for digital storage of
videos up to about 1.5MBit/sec, which is approximately the quality as on TV. The goal was to allow
Video transmission on low bandwidth networks like telephone cables [MP7HP].
MPEG-2 was a standard for digital television. MPEG-2 was released two years later then
MPEG-1, and enhances MPEG-1. Its aim is to become a standard for digital television with high data
rates, up to 80MBit/sec. The common known digital versatile disk (DVD) is a realization of MPEG-2.
MPEG-4 was developed as a standard for Multimedia applications [MPWP]. It is a context
based approach for exchange, management and production of digital content. It does not define new
compression standards for video, but offers a toolbox of advanced compression algorithms for audio
and visual data. MPEG-4 has JavaScript as internal script language. It provides a Java interface layer
(MPEG-J layer) that allows the use of Java classes within MPEG-4 content, in order to communicate
with external programs like players.
Finally, the MPEG-7-standard which is the most important for us. It is also known as
“Multimedia Content Description Interface”. The aim of MPEG-7 is to describe a wide area of
Multimedia content:
- Broadcast media selection. (radio channels, TV channels)
- Multimedia directory services. (yellow pages)
- Audiovisual databases can be organized and searched with MPEG-7
- digital libraries to describe images, videos and song catalogs
Page 12 of 87
Chapter 2 Requirements
- ....
It is able to describe still pictures, graphics, 3D models, audio, speech, video and their
combination [MP7HP]. Even content which is not audio or visual can be described, like taste or smell.
It is possible to use it independent of other MPEG standards, on an analogue movie,...
There is a relation between MPEG-4 and MPEG-7 though. The way of representing data in
MPEG-4 can be seen as the basic process of categorizing and separating data which MPEG-7 uses.
MPEG-7 descriptions can improve the functionalities of the previous standards.
At this moment, the MPEG-team works on MPEG-21, the Multimedia framework. It extends
the other MPEG standards with a Multimedia framework that allows transporting Multimedia content
over a wide range of networks and users.
c Why MPEG-7
The latest 10 years, the amount of multimedia on the Internet has grown a lot. If you try to
imagine how many movies you can find on YouTube ( www.youtube.com ) for example, you should
get a proper idea of it. In the next years, users will be confronted with such a large number of contents
provided by multiple sources, that efficient and accurate access to this almost infinite amount of content
seems impossible today. However the fact that users have increasing access to these resources,
identifying and managing them efficiently is becoming more difficult, because of the huge volume.
Page 13 of 87
Chapter 2 Requirements
This is why MPEG-7 is developed. It offers a solution, however, more correct would be, it is an
improvement. MPEG-7 offers a set of audiovisual Description Tools, to create descriptions, which will
form the basis for applications enabling the needed effective and efficient access to multimedia content
[MPOV]. Although, it must be made clear that the requirements for the development of MPEG-7 are
derived from analyzing a wide range of potential applications that could use MPEG-7 tools.
MPEG-7 is not aimed at any one application in particular, rather, the elements that MPEG-7
standardizes support as broad a range of applications as possible. For example, in this project, we use
MPEG-7 to parse the coordinates of a square in an image to another program.
d What is MPEG-7
The three main elements[MPOV] of the MPEG-7 standard are: Description Tools, Description
Definition Language (DDL), and System tools.
Description Tools, or Descriptors (D), define the syntax and the semantics of each feature
(metadata element), and Description Schemes (DS) specify the structure and semantics of the
relationships between their components.
Description Definition Language defines the syntax of the MPEG-7 Description Tools, and
allows the creation of new Description Schemes and Descriptors. They also allow the extension and
modification of existing Description Schemes.
System tools support binary coded representation for efficient storage and transmission,
transmission mechanisms, etc.
In the figure on the next page, the general situation of the usage of MPEG-7 is represented.
Page 14 of 87
Chapter 2 Requirements
The applet of this project does the Description generation. The program which will use the coordinates
does the Description Consumption.
Figure 3.2 Scope of MPEG-7 [MPOV]
The next figure summarizes the above paragraphs. As you can see, left you have the
descriptors, collected in a sort of library. In the right group they use those descriptors, put them in a
structure among others, descriptors and descriptor schemes get mixed and represent a new Description
Scheme. Finally this gets instantiated in textual format (XML). Further in this paper is a detailed
example which explains all what is written above.
Figure 3.3 MPEG-7 main elements [MPOV]
3.1.3 Existing Annotation Tools
a What is an Annotation Tool
Page 15 of 87
Chapter 2 Requirements
In general, annotation could be explained as “extra information with a particular point in a
document or other piece of information.” For example, when you add comments to source code, then
you annotate the source-code without affecting its functionality.
In this subject, digital imaging, the term annotation is commonly used for visible meta-data
superimposed on an image without changing the underlying raster image. When you talk about
'Automatic Image Annotation', then the computer system automatically assigns meta-data in the form
of captioning or keywords to a digital image.
b The Common Aim
For most image annotation tools, the goal is the ability to comprehensively describe content of
an image. This way, search engines can recognize in some way what is shown on the picture in order to
find the desired image. At the same time, human users should be also provided with complete
information about the image content so the could retrieve maximum knowledge of the image.
c Different Approaches to Image Annotation
In this section a few different approaches get explained, but we don't go into detail with this.
The aim of this section is to show that there are more then one option in annotation, and to make clear
which one we chosen [ftggr].
• Text Over Image: Clear identification can be provided by labeling an image with textual notes
placed directly on an image.
• Merged annotation: Here you put the annotations on the picture itself, the disadvantage of
Page 16 of 87
Chapter 2 Requirements
this is that the picture will contain the annotation permanently.
• Separated annotation: Here you save the meta-data in a separate file, meaning you retain
the original picture without annotations in case of future needs. The annotations are just
like another layer, on top of the picture. This also has some disadvantages, for example,
transferability. The annotations will be only visible when you use a certain application,
and if the meta-data file is present.
•
The Text over Image annotation with separate file is the one we will use. In our case the text
will be the coordinates of the square we select. The separate file will be an MPEG-7-file, which
contains all the information. More about this will follow in a later chapter. In the two figures below,
we have two screenshots of these kinds of annotations. Figure 3.4 demonstrates merged annotation,
whilst Figure 3.5 demonstrates separated annotation.
Figure 3.4 Merged Annotation
Page 17 of 87
Chapter 2 Requirements
Figure 3.5 Separate Annotation
d Examples
d.1 FOTOTAGGER
Fototagger [ftggr] is a comprehensive example. It is used to put tags on pictures, for example to
point to people and highlight who they actually are. The next two pictures will give a clear idea.
Figure 3.6 Annotated Picture in original state
Page 18 of 87
Chapter 2 Requirements
Figure 3.7 Annotated picture with XML-file loaded
The annotations are separate, as previously discussed. So there is an XML-file which contains the
information.
d.2 MUSCLE ANNOTATE
This is a pure experimental annotation tool, only developed for research[MSCL]. They use an
extension (an added segmentation section) of the XML annotation format which is used by the MIT
CSAIL database. This database is developed to test object classes which are used in object detection
algorithms. Also LABELME, which will be discussed in a later section, uses the MIT CSAIL
format. We will clarify with a detailed example found on:
http://muscle.prip.tuwien.ac.at/docs/metadata_spec.pdf.
Page 19 of 87
Chapter 2 Requirements
Figure 3.8 Figure 3.9
1 <annotation>
2 <filename>dog.tif</filename> 31 </pt>
3 <folder>images/MUSCLE_database</folder> 32 <pt>
4 <source> 33 <x>0</x>
5 <sourceImage>Photo from the WWW</sourceImage> 34 <y>30</y>
6 <sourceAnnotation>MUSCLE Annotate 35 </pt>
v0.01</sourceAnnotation> 36 <pt>
7 </source> 37 <x>280</x>
8 <keyword> 38 <y>30</y>
9 <name>dog</name> 39 </pt>
10 </keyword> 40 <pt>
11 <keyword> 41 <x>280</x>
12 <hname0>Botanic</hname0> 42 <y>0</y>
13 <hname1>grass</hname1> 43 </pt>
14 <deleted>0</deleted> 44 </polygon>
15 <verified>1</verified> 45 </object>
16 <date>20-Aug-2005 11:09:55</date> 46 <segmentation>
17 <annotator>Dennis Bloodnock</annotator> 47 <filename>dog_seg.tif</filename>
18 </keyword> ....
19 <object> 65 <label>1</label>
20 <keyword> 66 </object>
21 <name>grass</name> 67 <object>
22 </keyword> 68 <keyword>
23 <deleted>0</deleted> 69 <hname0>Zoology</hname0>
24 <verified>0</verified> 70 <hname1>dog</hname1>
25 <date>8-Aug-2005 12:03:25</date> 71 </keyword>
26 <annotator>Fred Nurque</annotator> 72 <label>2</label>
27 <polygon> 73 </object>
28 <pt> 81 </segmentation>
29 <x>0</x> 82 </annotation>
30 <y>0</y>
Line 1 to 7 give details about the file that contains the image, and the source. Line 2 gives the
filename, line 3 gives the directory where the file is saved. The keywords are indicated between
<keyword>...</keyword> tags. There are two formats for these keywords, name and hnamex.
The first one gives a description of the image or polygon, for example in line 9. The second one is a
label chosen from a hierarchy, x=0 is the top level.
Page 20 of 87
Chapter 2 Requirements
There are three different types of structure with which the keywords can be associated:
The whole image: line 8 to 18
A polygon: line 19 to 45 (compatible with the MIT CSAIL database annotations)
A segmentation: line 46-82: If you look at line 67-73, you can see very clearly the structure which is
used. First <segmentation>, then <object> for each region with a specific greylevel, and final <label>
which refers to value of the greylevel of the object.
d.3 VIDEOTATER
Videotater[VDTT] is a program made for users who work with video segments for example to
create music clips. It allows to create well detailed tags to video segments in order to create a more
sophisticated indexing in movie databases. To support the user, Videotater makes use of
understandable visualizations permits easy navigation, selection and tagging of video.
The visualization's main elements are the Timeline and the Polyfocal Visualization[VDTT] .
The timeline contains two different views of the video. The segment view, which shows seperate
segments who are already delineated; and the lower half shows information about the average value of
the pixels in every row of each frame. This last feature gives the user the possibility to guess if there is
a potential new segment. The polyfocal view gives 5 frames before and after the “in-frame”(the first
frame of a segment) and the same with the “out-frame”(the last frame of that same segment).
Page 21 of 87
Chapter 2 Requirements
Figure 3.10 “The Polyfocal view with the IN-and OUT-Frame” (a) and (b) point at the 5
frames, ( c) points at the selected segment. [VDTT]
d.4 LABELME
LabelMe is another annotation tool, based on Javascript[LBLM]. The user can label objects in
a picture by surrounding it with dots to make a clear border around the object. The dots are connected
like a polygon. When the first spot is clicked again, a popup dialog appears in which you can put the
annotation you wish to make. The annotation is put into an XML-format and it is saved in a central
database, called the LabelMe server.
Page 22 of 87
Chapter 2 Requirements
Figure 3.11 “Example of car”[LBLM]
In the above picture you can see the different object selections. Every surrounding has an
annotation, the next code shows how it becomes saved in an XML-file.
<annotation>
<filename>img_0355.JPG</filename>
<folder>oct6_static_outdoor</folder>
<source>
<sourceImage>The MIT-CSAIL database of objects and scenes</sourceImage>
<sourceAnnotation> The MIT-CSAIL database of objects and scenes</sourceAnnotation>
</source>
<scenedescription>street urban city outdoor</scenedescription>
<object>
<name>pot</name>
Page 23 of 87
Chapter 2 Requirements
<deleted>0</deleted>
<verified>1</verified>
<date>23-APR-2004 06:38:38</date>
<polygon>
<pt>
<x>1234</x>
<y>419</y>
</pt>
<pt>
<x>1230</x>
<y>435</y>
As you can see, the XML-format is similar to the format we've discussed above in the
MUSCLE-annotation. For more details, I refer to the explanation given by the example in that section.
As you can see on line 5, the MIT-CSAIL database is also used in LABELME.
3.2 Java-Applets
3.2.1 What is a Java Applet
A Java-applet extends the possibilities of a webpage, using the Java programming-language. At
the beginning, Java-applets were used to add complex graphical applications to webpages. In general,
Macromedia Flash took this over. Currently Java-applets are used for illustrating and demonstrating
scientific principals [WIK].
The usage of Java-applets demands installation of Java Virtual Machine (JVM), because Java
needs a bytecode-interpreter. This is a disadvantage comparing to Macromedia Flash: starting up JVM
takes some time and once started it occupies memory in the computer. As long as the browser is open,
JVM is working and using memory [WIK].
Page 24 of 87
Chapter 2 Requirements
3.2.2 Advantages of Applets
This section contains a list of the advantages of using applets [WIK]. The advantages which
were important for this project, get discussed in detail:
• Unless the applet requires a later version of the JRE, it can run on all installed Java versions at
the same time.
• It works on different platforms like Linux, Windows,...
• The sandbox method makes the code trusted...at least as long as you run it local in
AppletViewer, when you run it in a web browser, you need to sign a JAR-file.
• Most web browsers support it (Mozilla Firefox, Internet Explorer,...)
• it can have full access to the machine it is running on if the user agrees
• it can improve with use: after a first applet is run, the JVM is already running and starts
quickly, benefiting regular users of Java
• it can be a real time application
The advantages of Java-applets deployed on a website, is that it is often easier to locate for the
user. Especially for applications that aren't used every day, for example demo-versions: this annotation
tool. It is easier for a programmer to update only a single application on the web, then having to
reinstall it on several client desktops [JAV1].
A Java Plug-in is an extension of the functionality of a web browser. It allows applets to be run
Page 25 of 87
Chapter 2 Requirements
under Sun's Java 2 runtime environment (JRE). Without Java Plug-in, only the Java runtime
environment installed in the web browser will be able to use [SUN]. When Sun's JRE is installed, it
will be accompanied with Java Plug-in. For this annotation tool this is convenient, because on
computers without the plug-in, and an old environment, the applet will not load.
3.2.3 Disadvantages of applets
Similar to the previous section, the following disadvantages can be found on wikipedia. In this section
we'll also discuss two of them more in detail, with which I encountered problems during programming.
• Java Virtual Machine must be running before start up
• On some web browsers, the installation of Java Plug-In is required
• HTML-based technologies are considered more efficient in designing a good GUI
• When untrusted, there is limited access to the user his hard disk or clip board
• applets may require a specific JRE.
The annotation tool requires a specific JRE, thus it comes in handy to download the Java plug-
in. As previously discussed, this is memory consuming, and it is you see in the list, not default on all
web browsers. (In the 'Conclusion'-chapter there is more information about the problems and the
consequences which I have experienced.)
Page 26 of 87
Chapter 2 Requirements
Also the security policy of Java applets is very strict. In fact, every applet is considered
untrusted by web browsers. This brings us to the next problem, we need to browse the file system, and
even write on the hard disk. Therefore, we had to sign the JAR-file. This is an easy procedure, which
is explained in a later chapter.
3.3 Open Source Development using Eclipse and SVN
3.3.1 What is 'open source'?
'Open source software' is source code which users can see, adjust, or use if when desired.
After the release of the source code of Netscape Navigator in 1998, it was Eric Raymond who was one
of the pioneers to use this term. [WIK]
3.3.2 What is SVN?
Source control, or version control is one of the most important elements in open source
development. Cooperating developers use this software, in order to collaborate on code without the
necessity of unsophisticated file-sharing techniques. [SVN] Subversion is used for this project to
accomplish source control.
Page 27 of 87
Chapter 2 Requirements
Subversion uses a central repository to storage a tree of files which you want to check. It serves
as a kind of file server, but it keeps track of every change you made in your files and directories. Since
Subversion can work over networks, it made it possible to have different developers working in
parallel, to work on different computers, ... It provides the ability to make more progress, because
modifications don't have to occur through one single conduit anymore.
3.3.3 SVN-Techniques
Suppose two people work together on the same file of a project. The first user starts working on
'version 1'. The second user comes in later and works on 'version 1' as well, but the first user already
made some changes: 'version 1a'. When the first person saves his 'version 1a' and five minutes later, the
second person saves his 'version 1b', he overwrites the changes of the first person. Even if they use
different names to save it, there still would be a problem: the changes of 'version 1a' are not in 'version
1b' and vice versa. There are two techniques who solve these problems as far as possible, Lock-
Modify-Unlock, and Copy-Modify-Merge.
a Lock-Modify-Unlock
A file is exclusively dedicated to one certain developer, other developers can not edit the same
source code at the same time [SVN]. As soon as the developer is finished with editing, or adjusting, the
source code is released, and made available again for the other developers.
Page 28 of 87
Chapter 2 Requirements
b Copy-Modify-Merge
The previous technique has a big disadvantage, only one person at a time can work at the same
file[SVN]. “Copy-Modify-Merge” solves this problem, but not automatically. When committing the
file back in the repository, SVN looks for mutual changes and highlights them for the user. It is the
user his task to decide which changes can proceed and which get cancelled.
Page 29 of 87
Chapter 4 Implementation
4 Implementation
4.1 Applet
4.1.1 Architecture
a UML-SCHEME
A UML(Unified Modeling Language)-scheme is a graphical representation of object oriented
systems. It is used to design and to analyze them. It is able to describe static and dynamic systems by
putting all the information in a standardized way in different kind of diagrams. On the next page is a
class diagram of the source code.
Page 30 of 87
Chapter 4 Implementation
Figure 4.1“UML-Scheme”
Page 31 of 87
Chapter 4 Implementation
b Description of Classes
b.1 Annotator.class
The Annotator class contains the init() method. This is the method where everything begins, it
first initializes the interface. Using the FileSelector class, it loads an image to the object File. When
this is succeeded, init() instructs the paint() method to load the image in the object File to the screen.
When the user draws a rectangle (our region), the processMovement gets the coordinates of the
opposite corners of this rectangle. Every time the mouse is pressed and it makes a movement of a pixel,
it instructs to repaint.
The paint() method puts the image on the screen, and gets the coordinates of the rectangle from
processMovement() method and draws it over the picture with a transparent highlight effect.
Finally, the actionPerformed() method writes away the coordinates to a text file and an
MPEG-7 file. It gets the desired filename and filelocation from the FileSelector class, and uses
toTextFile() and ToMpeg7File() to put the content in a format and write it to a file on the harddisk.
The ToMeg7File() method will get discussed in a later section.
b.2 FileSelector class
Page 32 of 87
Chapter 4 Implementation
For the interface of the FileSelector class SWING-components are used. The main reason to
do this is because it is less depending on the underlying platform. It is possible that it appears to be
slightly slower than AWT, but the difference is essentially be small enough to ignore.
b.3 Textfile.class
SEE APPENDIX: SOURCE CODE CONTAINS DETAILED DESCRIPTION
4.1.2 MPEG-7
a MPEG-7 Scheme
1 <?xml version="1.0" encoding="UTF-8"?>
2 <Mpeg7 xmlns="urn:mpeg:mpeg7:schema:2001"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
3 <Description xsi:type="urn:ContentEntityType" xmlns:urn="urn:mpeg:mpeg7:schema:2001">
4 <MultimediaContent xsi:type="urn:ImageType">
5 <Image>
6 <SpatialLocator>
7 <Polygon>
8 <Coords urn:dim="4">196 151 250 222</Coords>
9 </Polygon>
10 </SpatialLocator>
11 </Image>
12 </MultimediaContent>
13 </Description>
1 </Mpeg7>
On the first line the version of XML needs to be specified in order to work. The encoding type
is the default UTF-8, it specifies which character set is used to encode data in the XML-document
[XML2].
Next, the XML Namespace gets declared: 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-
Page 33 of 87
Chapter 4 Implementation
instance" ' The Namespace relates an element or attribute with a specified URI, this way it allows to
have multiple elements with the same name within the same XML document, but they still have a
different semantic meaning.
The following section goes further in detail in the scheme of above. It gives a detailed
description on every line in the scheme related to the source code.
b Created Classes
First, a new instance get created by Mpeg7Document and an Mpeg7 element gets added. This is
represented on line 2 of the example in the previous section. Then the description element gets added,
Complete Description, the following figure gives a clear overview. The type of the description
element gets changed to Content Description, then to Content Entity.
Page 34 of 87
Chapter 4 Implementation
Figure 4.2“Complete Description”-scheme [MP7]
Now, a MultimediaContentType element [MP7] gets added to Content Entity and the type gets
changed into ImageType. Stillregion is a descriptor, used to subdivide the image into regions. The
data for those regions and visual descriptors are kept in this “stillregion”descriptor [UMMR]. The
“SpatialLocator” holds the coordinates of the rectangle. In the source code there is Arrays and
Matrices used. These belong to MPEG-7 specific extensions. [XSMPDL7]
4.1.3 Creation of Jar-file
a Creation of a Jar-File
Page 35 of 87
Chapter 4 Implementation
A JAR-file is an archive file which contains class-files, and if wanted, other files (images,
sound,...), in a compressed format [JAV1]. To create a JAR-file, you use the jar-tool. This tool can be
found in the default jdk/bin directory. The command used to create annotator.jar is jar cvf
Annotator.jar *.* within the directory were the project was saved. Between 'jar' and 'annotator.jar' you
see the options of the command line:
• c creates a new or empty archive and adds files to it;
• v generates a verbose output
• f specifies the JAR-filename as the second command-line argument
There are two reasons to use JAR-files: the first is minimizing network-overhead, the second is
in case you need special permissions. The first was in this case not the most important, because we
only have a few class-files. The issue with the network-overhead is that when the web browser reads
the HTML-code, which says he has to use annotator.class, will make a connection with this class.
Then he resolves the other classes used in this class, and he makes each time additional connections
what demands a lot of time. Thanks to the JAR-file, only one request is needed, which saves some time
and network-traffic. You can compare it with transporting an amount of cargo with 1 truck instead of
10 cars. The second reason on the other hand, was a necessity, the next section 'signed jar-files' goes
further into detail.
4.1.4 Applet Signature
For example the file browser used in the applet needs permissions to access the local hard disk of the
Page 36 of 87
Chapter 4 Implementation
user. To achieve this, we need to sign the JAR-file. This lets us know two things:
1. Where did the applet come from ?
2. Was the code corrupted in transit ?
To do this, you need to obtain a certificate, which may be generated by a software like keytool.
a Keytool
Keytool manages key stores (databases of certificates and private keys). [JAV2]It is a part of
the JDK. Every entry in the key store has an alias ( a name). As an example, a key pair with the alias
diego is created.
“keytool -genkey -keystore diego.store -alias diego”
As you can see on the next page, the program asks you some questions to give you a certain
identification.
Page 37 of 87
Chapter 4 Implementation
Figure4.3 “create a keystore alias diego”
b Jarsigner
Now we have to sign the JAR-file with our key. To do this, we use the next tool, jarsigner. It is
located in the /bin directory of your Java-environment. The command I've used is:
jarsigner -keystore diego.store annotator.jar diego
So the program uses the alias diego, from the keystore diego.store to sign the file annotator.jar.
Before he signs it, the program will ask for the password, and after this the procedure is completed.
4.1.5 How to put an Applet Online?
a HTML-Code
<html>
<body>
Page 38 of 87
Chapter 4 Implementation
<APPLET CODE=src.edu.upc.terrassatsc.Annotator.class
CODEBASE="http://terrassatsc.upc.edu/~diegocant/"
ARCHIVE="Sannotationtool.jar, xbean.jar, MPEG7-Ver1.jar, jsr173_1.0_api.jar"
width=860 height=560>
</APPLET>
</body>
</html>
b Comments
To put an applet online, you have to tell the browser where the code is located, this is done by
declaring CODEBASE [JAV1]. Since the code is a package (see 4.2.1. a), we add the name of the
package to the APPLET CODE-name. In the ARCHIVE statement, first of all the main jar-file has to
be added. Because we use external libraries in our source code, they have to be included in the HTML-
code as well.
4.2 Development
4.2.1 Creation and Configuration of an Eclipse project
a Create a New Project
The first step, to create a new project in Eclipse, is to click “File-->New-->Project” and select
the 'Java project' wizard. The chosen options are shown in the figure below, most important is the
environment “JRE 1.6.0”. Some of the older environments don't support everything in the sourcecode
we have used. 'Create seperate source and output folders' tells the compiler to save the *.class files in a
different directory, the /bin directory, while the source, or the *.Java files are saved in the /src directory.
Eclipse starts generating the project as soon the 'finish' button is pushed.
Page 39 of 87
Chapter 4 Implementation
Figure 4.4 “New Java Project”
b Packages
b.1 Introduction
In the project, we used the concept of Java 'packages', to have a better organization of classes.
In general, packages are used to separate classes that have the same name but different code or origin.
As you can see, the package used is named src.edu.upc.terrassatsc. The standard procedure is indeed
Page 40 of 87
Chapter 4 Implementation
to use the organization's internet domain name(which is unique), written in reverse. Moreover, you
can go further in making subpackages, like edu.src.
When a class belongs to a package, the name of the package is located at the top of your source
file, before the code that defines the classes in the package.
For example: package src.edu.upc.terrassatsc;
import Java.applet.Applet;
import Java.awt.Button;
......
In the Eclipse environment, if the package-statement is not in the source file, then it will belong to the
'default package'. It is necessary to put the files of the package in a subdirectory with the same name,
thus src\edu\upc\terrassatsc.
b.2 Creation of a package in Eclipse
In the menu, the user selects “File-->New-->Package” and types src.edu.upc.terrassatsc . The
first figure shows the window where you have to type, the second figure shows the result.
Page 41 of 87
Chapter 4 Implementation
Figure 4.5 “New Java Package window”
Figure 4.6“Result of Created Package”
c Creation of a New Class
Similar to the previous paragraphs, a class gets created by clicking “File-->New-->Class”, with
figure “New Java Class window” as result. If you left-click on 'AnnotationTool' as in the figure
“Result of Created Package”, and select “New-->Class”, then you need to type the package name as
shown in the figure “New Java Class window” to put the new class in the correct package.
Page 42 of 87
Chapter 4 Implementation
Figure 4.7“New Java Class window”
d Configure Classpath
Three external JAR-files are used as libraries, these files are a necessity because the contain
essential elements for the creation of the Mpeg-7 file. In this project, first a folder /lib was created in
the project-folder and the three libraries were imported in this /lib directory. Left-mouse-button click
on the /lib folder, select import-->File System, simply browse to the files and select them.
Page 43 of 87
Chapter 4 Implementation
The instructions to configure the class path to these files: click with left-mouse-button on the
project folder, select build path--> configure build path, and click on the tab 'Libraries'. Now you
click 'Add JARs' browse to your /lib folder and select the JAR-files [ECL].
Figure 4.8 “Configure Class Path window”
4.2.2 SVN Repository Access With SubEclipse
a Installation of SubEclipse
The user selects “Help --> Software Updates --> find and install “, then a window appears
Page 44 of 87
Chapter 4 Implementation
where he can select update sites. He clicks 'New Remote Site' and types
“http://subclipse.tigris.org/update_1.0.X” to download SubEclipse. The website comes in the list with
the other update-sites, the user now has to select the site he just added and click 'finish'. After
installation, the user has to restart Eclipse.
Figure 4.9“enter the update-site”
b Configuring Eclipse to Connect with the repository
Click “Window-->Open Perspective-->SVN Repository” and click the right-mouse-button to add
“new Repository Location”. Then you type
“https://diegocant@svn.lafarga.cpl.cpu.edu/dades/annotation” and click 'finish'. Now you have a
Figure 4.10 “Add a new SVN Repository”
connection from Eclipse with the Repository. Right-click on the location, and select 'checkout'. The
reason why a 'checkout' is necessary is to copy the existing project files from the repository to your
Page 45 of 87
Chapter 4 Implementation
local project. It is only the first time when you configure your eclipse to the project, that it is necessary.
The further instructions are similar to 4.2.1.a.
Figure 4.11“Checkout from SVN” Figure 4.12“Result”
The next step is keeping your local project up-to-date with the repository, and the other way
around. When you right-click on the project, and select 'team'. The pop-up menu shows several
options, from which the most important for us are “commit”, “update”. “Update” takes the most recent
version of the repository and updates your local version. “Commit” updates the repository version
with your local version and SubClipse allows it to tag comments to your commits. The website were
you can find the source code is
https://lafarga.cpl.upc.edu/plugins/scmsvn/viewcvs.php/?root=annotation
Page 46 of 87
Chapter 4 Implementation
Figure 4.13“Commit window with Comment space”
Page 47 of 87
Chapter 4 Implementation
Figure 4.14 “Screenshot of SVN web interface”
Page 48 of 87
Chapter 5 Results
5 Results
In this chapter there are two sections. The first one describes in detail how you start the
annotation tool beginning in eclipse, and the annotation of an image. The second section gives a screen
shot of how it opens when you use a website. This will be not further discussed because of the
similarity with the first section.
5.1 Example of annotation, starting from Eclipse
a Run the Project in Eclipse
Figure 5.1 “How to run the program in Eclipse
You start the program by clicking with the left mouse-button on the annotator class. Then you
select 'run as' and 'Java Applet' as shown in the figure above. The applet starts running in
appletviewer, this is a test tool used during development.
b Select an Image from your hard drive
Page 49 of 87
Chapter 5 Results
Figure 5.2 “First part of the program”
The file browser pops up, the user browses to the image he desires and clicks the 'open' button.
c The Image Loads and Selection of a Rectangular Region
The figures on the next page show the image in AppletViewer. The second figure has the
selection of the highlighted rectangle .
Page 50 of 87
Chapter 5 Results
Figure 5.3 “Appletviewer with image loaded”
Figure 5.4 “Appletviewer with image loaded and region selected”
Page 51 of 87
Chapter 5 Results
d The 'send coordinates' button
Figure 5.5 “Put desired filename on a selected location”
When the 'send coordinates' button is clicked, the file browser opens again. The user types the
filename and selects a location. Finally the program writes two files, with the same name, at the same
location, but with a different extension. One file is a txt-file with normal text format. The other file is
the MPEG-7 file, as previously discussed. The following images give step by step what is described
above.
Figure 5.6 “The two files are written to this folder”
Page 52 of 87
Chapter 5 Results
Figure 5.7 “The content of the MPEG-7 file as seen in Mozilla Firefox”
Figure 5.8 “The content of the txt file as seen in Notepad”
Page 53 of 87
Chapter 5 Results
5.1.2 Example of Annotation, starting in a Web Browser
Figure 5.9 “The Annotation Tool loaded from a web browser”
Page 54 of 87
Chapter 6 Future Work
6 Future Work
The Annotation Tool can be improved in several ways. To begin with, the GUI can made
better. Moreover the functionality can be expanded to work with a BPT (Binary Partition Tree).
Semantic objects would be represented by or separate, or combined nodes of such an BPT, for example:
Figure 6.1 taken from “BPT Enhancement Based on Syntactic and Semantic Criteria”
by C.Ferran, X.Giró, F.Marqués and J.R.Casas
Page 55 of 87
Chapter 6 Future Work
The JAR-file should get signed by a certificate from the school, keep in mind that there is a
public and a private key needed. The public key is only needed to validate the JAR-file, the private key
to sign it.
Page 56 of 87
Chapter 7 Conclusion
7 Conclusion
During this project I have experienced to work with several technologies/programs which were
new for me: Subversion, Applet technology, MPEG-7, Eclipse, signing jar-files,... The knowledge I
have now gives me a better viewpoint on computer programming then I had before.
There are several goals which aren't achieved though. The first problems occurred with the
Filebrowser: the security issues it brought up took some time to find out what the problem actually was.
First for the version in eclipse (a permission-statement had to be added), later for the version on the web
browser (signing JAR-file). Finally these problems were solved, but the JAR-file is signed with a self-
generated certificate, which is not generated by the EUETIT.
It took some time to find out how to work with Subversion, but once the project was connected,
it showed its use. From experience I can tell that it is important to make a lot of commits with specific
and detailed comments on what has changed. It is not only important for your project partner to know
what you have changed, but also for yourself in case you forget something.
XML and MPEG-7 are very interesting subjects, though it can get complicated with the
Page 57 of 87
Chapter 7 Conclusion
different libraries that need to be added. The possibilities however are gigantic. In this program, the
functionality doesn't get a big podium to show its capabilities, but during reading articles and books I
came in contact with its use in retrieval frameworks,...
Page 58 of 87
Chapter 7 Conclusion
Bibliography
WIK: , Wikipedia, , www.wikipedia.be
XML2: , website XMLBeans, , http://xmlbeans.apache.org/
XML1: Elliotte Rusty Harold, W. Scott Means, XML in a Nutshell, 2nd Edition, 2002
MPOV: José M. Marinez, MPEG-7 Overview,
MP7W: , , , http://www.chiariglione.org/mpeg/
MP7HP: , The MPEG-7 homepage, , http://mpeg.telecomitalialab.com/
MPWP: , MPEG-7 Whitepaper, 2003
ftggr: , fototagger, , www.fototagger.com
MSCL: , MUSCLE, , http://muscle.prip.tuwien.ac.at/
VDTT: Nicholas Diakopoulos and Irfan Essa, Videotater: An Approach for Pen-BasedDigital Video
Segmentation and Tagging,
LBLM: , Homepage Labelme, , www.labelme.com
SUN: , SUN Microsystems, , http://Java.sun.com/
SVN: Ben Collins-Sussman,Brian W. FitzpatrickC. ,Michael Pilato, Version Control with Subversion,
MP7: Marco Bertini, MPEG-7,
UMMR: Werner Klieber, Using MPEG-7 for Multimedia Retrieval, 2003
XSMPDL7: Dr. HaraldKosch,Steve Dennis,Alejandro Jaimes, Jane Hunter
JAV1: Cay S.Horstmann and Gary Cornell, Core Java Fundamentals,
JAV2: Cay S. Horstmann, Gary Cornell, Core Java Advanced Features,
ECL: , Homepagina Eclipse, , http://www.eclipse.org/
Page 59 of 87
Chapter 8 Appendix
8 Appendix: Source Code
8.1 Annotator.Java
package src.edu.upc.terrassatsc;
import java.applet.Applet;
import java.awt.*;
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import javax.swing.JFileChooser;
//import mpegMpeg7Schema2001.Mpeg7Document;
import mpegMpeg7Schema2001.*;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
public class Annotator extends Applet implements MouseListener,
MouseMotionListener, ActionListener {
private static final long serialVersionUID = 5610359269819472163L;
Image image;
URL base;
Chapter 8 Appendix
MediaTracker mt;
private int temp;
private int firstX;
private int firstY;
private int currentX;
private int currentY;
private Object filePath;// saving of coordinates parameters
private Object fileName;
Button okButton1;
public void init() {
temp = 0;
setLayout(null);
addMouseMotionListener(this);
// Create a file chooser
final JFileChooser fc = new JFileChooser();
int returnVal = fc.showOpenDialog(Annotator.this);
final File file;
if (returnVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
System.out.println("Opening: " + file.getAbsolutePath() + ".");
/* Read image from file */
try {
image = getImage( file.toURI().toURL() );
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
System.out.println("Unable to open image file.");
e1.printStackTrace();
}
mt = new MediaTracker(this);
mt.addImage(image, 1);
try {
mt.waitForAll();
} catch (final InterruptedException e) {
}
int imageWidth = image.getWidth(null);
okButton1 = new Button("Send Coordinates");
System.out.println(imageWidth);
okButton1.setBounds(0,0,imageWidth,20);
add(okButton1, "Northwest");
okButton1.addActionListener(this);
} else {
System.out.println("Open command cancelled by user.");
Chapter 8 Appendix
}
}
private void toTextFile( )
{
// Write in the selected file in text mode
final TextFile textFile = new TextFile(false, filePath + "/" + fileName + ".txt");
textFile.println("first X: " + firstX + " " + "first Y: " + firstY
+ " " + "last X: " + currentX + " " + "last Y: "
+ currentY);
System.out.println( "TXT Coordinates written to " + filePath + "/" + fileName + ".txt");
}
private void toMpeg7File() throws XmlException, IOException
{
// Creates a new, completely empty instance
Mpeg7Document mpeg7doc = Mpeg7Document.Factory.newInstance();
// Add Mpeg7 element
Mpeg7Document.Mpeg7 mpeg7 = mpeg7doc.addNewMpeg7();
// Add Description element
CompleteDescriptionType completeDescription = mpeg7.addNewDescription();
// Change the schema type from CompleteDescription to ContentDescriptionType
ContentDescriptionType contentDescription = (ContentDescriptionType) completeDescription
.changeType(ContentDescriptionType.type);
// Change the schema type from ContentDescription to ContentEntityType
ContentEntityType contentEntity = (ContentEntityType) contentDescription
.changeType(ContentEntityType.type);
// Add MultimediaContent element
MultimediaContentType multimediaContent = contentEntity.addNewMultimediaContent();
// Change the schema type from MultimediaContent to ImageType
ImageType image = (ImageType) multimediaContent.changeType(ImageType.type);
// Add StillRegion element
StillRegionType stillRegion = image.addNewImage();
// Add SpatialLocator element
RegionLocatorType regionLocator = stillRegion.addNewSpatialLocator();
// Add Polygon/Coords element
IntegerMatrixType coords = regionLocator.addNewPolygon().addNewCoords();
// Creat a list and add the rectangle coordinates
List<Integer> boxVertices = new ArrayList<Integer>();
boxVertices.add(new Integer(firstX) );
boxVertices.add(new Integer(firstY) );
boxVertices.add(new Integer(currentX) );
boxVertices.add(new Integer(currentY) );
// Set the dimension of the list
List<Integer> dimension = new ArrayList<Integer>();
dimension.add(new Integer(4) );
Chapter 8 Appendix
coords.setDim( dimension );
// Set the list of coordinates
coords.setListValue(boxVertices);
// Create a XML object by parsing the MPEG-7 string
XmlObject xmlObject = XmlObject.Factory.parse( mpeg7doc.toString() );
// Create a file stream
OutputStream outputStream = new FileOutputStream( filePath + "/" + fileName + ".mp7");
// Dump the XML object into the file stream
xmlObject.save(outputStream);
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
*/
public void mouseClicked(final MouseEvent arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
*/
public void mouseEntered(final MouseEvent arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
*/
public void mouseExited(final MouseEvent arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
*/
public void mousePressed(final MouseEvent arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
Chapter 8 Appendix
*
* @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
*/
public void mouseReleased(final MouseEvent arg0) {
temp = 0;
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent)
*/
public void mouseDragged(final MouseEvent mEvent) {
processMovement(mEvent);
}
/*
* (non-Javadoc)
*
* @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent)
*/
public void mouseMoved(final MouseEvent arg0) {
// TODO Auto-generated method stub
}
/*
* (non-Javadoc)
*
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
public void actionPerformed(final ActionEvent evt) {
if (evt.getSource() == okButton1) {
// Select a filename to write the annotation to
final FileSelector fileSelector = new FileSelector();
fileSelector.actionPerformed();
filePath = fileSelector.getDirectory();
fileName = fileSelector.getFileName();
// Write to the selected file in text mode
toTextFile();
// Write to the selected file in MPEG-7 format
try {
toMpeg7File();
} catch (XmlException e) {
// TODO Auto-generated catch block
System.out.println( "XML Exception while writing MPEG-7 XML" );
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
System.out.println( "IO Exception while writing MPEG-7 XML" );
e.printStackTrace();
}
}
Chapter 8 Appendix
}
private void processMovement(final MouseEvent evt) {
final int CoordX = evt.getX();
final int CoordY = evt.getY();
currentX = CoordX;
currentY = CoordY - 20;
if (temp == 0) {
firstX = CoordX;
firstY = CoordY - 20;
temp = 1;
}
repaint();
}
public void paint(Graphics g)
{
// draw the image on the screen
final int green=255;
final int red=255 ;
final int blue=0;
final int transparency=50;
g.drawImage(image,0,20,this);
g.drawString("("+currentX+","+currentY+")",currentX+10,currentY+10);
g.drawString("("+firstX+","+firstY+")",firstX,firstY+10);
g.drawRect(firstX,firstY + 20,currentX-firstX, currentY-firstY);
Color color = new Color(red, green, blue,255 * transparency / 100);
g.setColor(color);
g.fillRect(firstX, firstY + 20, currentX - firstX + 1, currentY - firstY + 1);
}
}
8.2 FileSelector.Java
package src.edu.upc.terrassatsc;
import java.awt.BorderLayout;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
public class FileSelector extends JApplet {
private static final long serialVersionUID = 798921988041064078L;
JButton button1 = new JButton();
boolean successful = true;
JOptionPane jop = new JOptionPane();
Chapter 8 Appendix
public void init() {
button1.setText("Submit");
this.getContentPane().add(button1, BorderLayout.NORTH);
button1.setBounds(120, 200, 98, 30);
// button1.addActionListener(this);
}
public void actionPerformed() {
try {
JFileChooser fileDialog = new JFileChooser();
fileDialog.showOpenDialog(this);
temp1 = fileDialog.getCurrentDirectory();
// tempdirectory=(String) temp1;
// System.out.println(temp1);
temp2 = fileDialog.getSelectedFile().getName();
fileDialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
public Object getDirectory() {
return temp1;
}
public Object getFileName() {
return temp2;
}
private Object temp1;
private Object temp2;
}
8.3 TextFile.Java
package src.edu.upc.terrassatsc;
import java.io.*;
import java.text.DecimalFormat;
/**
* A simple I/O class to help students read from or write to a text file. The
* I/O classes that come with Java are very flexible, but are difficult for
* beginners to learn. This class is a substitute that performs most of the
* simple things you need to do in intro Java courses.
*
* None of the methods from this class throw exceptions. When errors occur, they
Chapter 8 Appendix
* print an error message and abort the program.
*
* For more details, see method descriptions below as well as example programs
* provided with this class.
*
* @author Margaret Lamb
* @version 1.3, August 2006
*/
/* Versions:
* 1.1: July 2005, initial version
* 1.2: September 2005: fixed minor problem with println
* 1.3: August 2006: internal changes so package works with Java 1.4,
* added padding and formatting functions
* 1.3a: September 2006: more user-friendly error message when readInt hits end of file
*/
public class TextFile {
// This object does all the real work. It's either an InputFileObject or an
// OutputFileObject. The only reason for the indirection is to make it
// possible to use regular constuctors instead of a static "factory" method
// to create TextFile objects.
private FileObject fileObj;
/**
* A TextFile object for reading user input from the keyboard ("standard
* input")
*/
public static final TextFile KEYBOARD = new TextFile(true);
/**
* A TextFile object for writing to the computer screen ("standard output").
* This provides the same functionality as System.out, but is included for
* completeness, and also contains formatted print and println methods for
* ints and doubles.
*/
public static final TextFile SCREEN = new TextFile(false);
/**
* Creates a new TextFile object for reading from or writing to a file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error message if the file can't be opened or if you attempt to read from
* an input file which does not exist.
*
* @param inputFile true if this is an input file for reading; false if it's an
* output file for writing
* @param fileName the name of the file -- may be an absolute name
* ("c:/Java/Assignment 1/inputfile.txt") or a simple name
* ("inputfile.txt"). Simple names will be found in the same
* folder as your program (.java) files.
*/
public TextFile(boolean inputFile, String fileName) {
if (inputFile)
fileObj = new InputFileObject(fileName);
else
fileObj = new OutputFileObject(fileName);
Chapter 8 Appendix
} // end constructor
// special constructor for creating an object for reading from the standard
// input or writing to the standard output
private TextFile(boolean inputFile) {
if (inputFile)
fileObj = new InputFileObject();
else
fileObj = new OutputFileObject();
} // end constructor
/**
* Reads a single character from the (input) file. Does not skip
* whitespace characters.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file, or if we have already reached the end of
* the file.
*
* @return the character read from the file
*/
public char readChar() {
return fileObj.readChar();
} // end readChar
/**
* Reads the next line from the (input) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file, or if we have already reached the end of
* the file.
*
* @return the line read from the file (minus the ending '\n')
*/
public String readLine() {
return fileObj.readLine();
} // end readLine
/**
* Reads the next "word" from the (input) file. A word is a sequence of
* characters other than the "whitespace" characters (space, tab and
* newline). It will skip any initial whitespace and then read characters
* until it sees either a whitespace character or the end of the file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file, or if we have already reached the end of
* the file.
*
* @return the word read from the file
*/
public String readWord() {
return fileObj.readWord();
} // end readWord
Chapter 8 Appendix
/**
* Reads an integer from the (input) file. It skips any whitespace
* characters, reads the next "word" and converts it to an integer.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file, if we have already reached the end of
* the file, or if the next word is not in legal integer format
*
* @return the integer read from the file
*/
public int readInt() {
return fileObj.readInt();
} // end readInt
/**
* Reads a double from the (input) file. It skips any whitespace
* characters, reads the next "word" and converts it to a double.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file, if we have already reached the end of
* the file, or if the next word is not in legal double format
*
* @return the integer read from the file
*/
public double readDouble() {
return fileObj.readDouble();
} // end readDouble
/**
* Skips "white space" in the (input) file. White space characters are
* blanks, tabs and newlines. This method throws away white space characters
* from the input until it reaches either a non-white character or the end
* of the file. It's not an error to call this method when you're already at
* the end of the file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file.
*/
public void skipWhiteSpace() {
fileObj.skipWhiteSpace();
} // end skipWhiteSpace
/**
* Checks whether we've reached the end of the (input) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an output file.
*
* @return true if we've reached the end of the file
*/
public boolean eof() {
return fileObj.eof();
} // end eof
Chapter 8 Appendix
/**
* Writes a single character to the (output) file, followed by an
* end-of-line character.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param c the character to write
*/
public void println(char c) {
fileObj.println(c);
} // end println
/**
* Writes a string to the (output file), followed by an end-of-line
* character.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param s the string to write
*/
public void println(String s) {
fileObj.println(s);
} // end println
/**
* Writes a string to the (output) file, using a specified minimum width,
* followed by an end-of-line character.
* If the string is shorter than the width, it is padded on the left with
* blanks.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param s the string to write
* @param width the minimum width
*/
public void println(String s, int width) {
fileObj.println(s, width);
} // end print
/**
* Writes an integer to the (output) file, followed by an end-of-line
* character.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param i the integer to write
*/
public void println(int i) {
Chapter 8 Appendix
fileObj.println(i);
} // end println
/**
* Writes an integer to the (output) file, using a specified minimum width,
* followed by an end-of-line character. If the integer has fewer than the
* specified number of digits, it is padded on the left with blanks. If the
* integer has more than the specified number of digits, the minimum width
* is disregarded and the full integer is printed.
* <p>
* <p>
* <b>Example:</b> <br>
*
* <tt>println(1234,5)</tt> will print <tt>" 12345"</tt> <br>
*
* <tt>println(1234,3)</tt> will print <tt>"1234"</tt>.
*
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param i the integer to write
* @param width the minimum number of output characters to write; the method
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void println(int i, int width) {
fileObj.println(i, width);
} // end println
/**
* Writes a double number to the (output) file in the default format,
* followed by an end-of-line character. Uses as many digits as required
* without leading or trailing zeros.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(123.45)</tt> prints <tt>"123.45"</tt>. <br>
*
* <tt>println(11.0/7.0)</tt> prints <tt>"1.5714285714285714"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this
is an input file.
*
* @param d
* the number to write.
*/
public void println(double d) {
fileObj.println(d);
} // end println
/**
* Writes a double number to the (output) file using a specified minimum
Chapter 8 Appendix
* width, followed by an end-of-line character. Always uses 6 digits after
* the decimal point, even if that includes trailing zeros. Decimal digits
* after 6 are rounded. Pads with spaces on the left, if necessary, to reach
* the minimum width.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(123.45,12)</tt> prints <tt>" 123.450000"</tt>. <br>
*
* <tt>println(11.0/7.0,9)</tt> prints <tt>" 1.571429"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param d the number to write
* @param width the minimum number of output characters to write; the method
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void println(double d, int width) {
fileObj.println(d, width);
} // end println
/**
* Writes a double number to the (output) file using a specified minimum
* width and precision, followed by an end-of-line character. Always uses
* exactly the specified number of digits after the decimal point, rounding
* the rest. (If the precision is negative, prints zero digits after the
* decimal point.) Pads with spaces on the left, if necessary, to reach the
* minimum width. If you want to specify the precision but not a minimum
* width, use a width of 1.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(123.45,9,3)</tt> prints <tt>" 123.450"</tt>. <br>
*
* <tt>println(11.0/7.0,3,1)</tt> prints <tt>" 1.6"</tt>. <br>
*
* <tt>println(11.0/7.0,1,2)</tt> prints <tt>"1.57"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param d the number to write
* @param width the minimum number of output characters to write; the method
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void println(double d, int width, int precision) {
fileObj.println(d, width, precision);
} // end println
/**
* Writes a boolean value to the (output) file (as "true" or "false"),
* followed by an end-of-line character.
Chapter 8 Appendix
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param b the boolean value to write
*/
public void println(boolean b) {
fileObj.println(b);
} // end println
/**
* Writes an object to the (output) file, followed by an end-of-line
* character. The printing format corresponds to the "toString" method of
* that object's type.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param obj
* the object to write
*/
public void println(Object obj) {
fileObj.println(obj);
} // end println
/**
* Writes an end-of-line character to the (output) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*/
public void println() {
fileObj.println();
} // end println
/**
* Writes a single character to the (output) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param c the character to write
*/
public void print(char c) {
fileObj.print(c);
} // end print
/**
* Writes a string to the (output) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
Chapter 8 Appendix
*
* @param s the string to write
*/
public void print(String s) {
fileObj.print(s);
} // end print
/**
* Writes a string to the (output) file, using a specified minimum width.
* If the string is shorter than the width, it is padded on the left with
* blanks.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param s the string to write
* @param width the minimum width
*/
public void print(String s, int width) {
fileObj.print(s, width);
} // end print
/**
* Writes an integer to the (output) file.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param i
* the integer to write
*/
public void print(int i) {
fileObj.print(i);
} // end print
/**
* Writes an integer to the (output) file, using a specified minimum width.
* If the integer has fewer than the specified number of digits, it is
* padded on the left with blanks. If the integer has more than the
* specified number of digits, the minimum width is disregarded and the full
* integer is printed.
* <p>
* <b>Example:</b> <br>
*
* <tt>println(1234,5)</tt> will print <tt>" 12345"</tt> <br>
*
* <tt>println(1234,3)</tt> will print <tt>"1234"</tt>.
*
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param i the integer to write
* @param width the minimum number of output characters to write; the method
Chapter 8 Appendix
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void print(int i, int width) {
fileObj.print(i, width);
} // end print
/**
* Writes a double number to the (output) file in the default format. Uses
* as many digits as required without leading or trailing zeros.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(123.45)</tt> prints <tt>"123.45"</tt>. <br>
*
* <tt>println(11.0/7.0)</tt> prints <tt>"1.5714285714285714"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param d the number to write.
*/
public void print(double d) {
fileObj.print(d);
} // end print
/**
* Writes a double number to the (output) file using a specified minimum
* width. Always uses 6 digits after the decimal point, even if that
* includes trailing zeros. Decimal digits after 6 are rounded. Pads with
* spaces on the left, if necessary, to reach the minimum width.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(123.45,12)</tt> prints <tt>" 123.450000"</tt>. <br>
*
* <tt>println(11.0/7.0,9)</tt> prints <tt>" 1.571429"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param d the number to write
* @param width the minimum number of output characters to write; the method
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void print(double d, int width) {
fileObj.print(d, width);
} // end print
/**
* Writes a double number to the (output) file using a specified minimum
* width and precision. Always uses exactly the specified number of digits
* after the decimal point, rounding the rest. (If the precision is
* negative, prints zero digits after the decimal point.) Pads with spaces
Chapter 8 Appendix
* on the left, if necessary, to reach the minimum width. If you want to
* specify the precision but not a minimum width, use a width of 1.
* <p>
* <b>Examples:</b><br>
*
* <tt>println(1.5714,5,1)</tt> prints <tt>" 1.6"</tt>. <br>
*
* <tt>println(1.5714,15,2)</tt> prints <tt>" 1.57"</tt>. <br>
*
* <tt>println(1.5714,1,6)</tt> prints <tt>"1.571400"</tt>.
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param d the number to write
* @param width the minimum number of output characters to write; the method
* will add spaces at the beginning if necessary to make this
* number of characters.
*/
public void print(double d, int width, int precision) {
fileObj.print(d, width, precision);
} // end print
/**
* Writes a boolean value to the (output) file (as "true" or "false").
* <p>
* <b>Errors:</b> <br>
* Will abort with an
* error if this is an input file.
*
* @param b the boolean value to write
*/
public void print(boolean b) {
fileObj.print(b);
} // end print
/**
* Writes an object to the (output) file. The printing format corresponds to
* the "toString" method of that object's type.
* <p>
* <b>Errors:</b> <br>
* Will abort with
an
* error if this is an input file.
*
* @param obj the object to write
*/
public void print(Object obj) {
fileObj.print(obj);
} // end print
/**
* Closes the file when you're done using it. It's important to remember to
* do this to free system resources associated with the file and to make
* sure any buffered characters really make it to the file. It's not
Chapter 8 Appendix
* necessary to close the special Keyboard or Screen files.
*/
public void close() {
fileObj.close();
} // end close
/**
* Aborts the program with an error message. Included here just because it's
* generally useful, both for I/O and other purposes.
*
* @param msg the message to print before ending the program execution
*/
public static void abort(String msg) {
System.out.println(msg);
System.exit(1);
} // end abort
/***************************************************************************
* Helper methods for formatting numbers. These are used by the print
* methods.
**************************************************************************/
/**
* Pads a string with spaces on the left to reach a target width.
* If the string is already longer than the width, leaves it alone --
* doesn't truncate.
* <p>
* <b>Examples:</b><br>
*
* <tt>padLeft("hello", 7)</tt> returns <tt>" hello"</tt>. <br>
*
* <tt>padLeft("hello", 4)</tt> returns <tt>"hello"</tt>.
* <p>
* @param s the string to pad
* @param width the target width (number of characters)
* @return the string with spaces inserted on the left as needed
*/
private static String padLeft(String str, int width) {
String result = str;
while (result.length() < width)
result = " " + result;
return result;
} // end padLeft
/**
* Formats an integer for output, padding it to a target width.
* Adds blank spaces to the left as needed to reach the width.
* If the integer contains more spaces than the width, no digits
* are truncated.
* <p>
* <b>Examples:</b><br>
*
* <tt>formatInt("12345", 7)</tt> returns <tt>" 12345"</tt>. <br>
*
* <tt>formatInt("12345", 4)</tt> returns <tt>"12345"</tt>.
* <p>
* @param value the integer to format
Chapter 8 Appendix
* @param width the target width
* @return the integer in string form, with blank spaces inserted on the
* left as needed to reach the target width
*/
private static String formatInt(int value, int width) {
return padLeft(Integer.toString(value), width);
} // end formatInt
/**
* Formats a double for output, with a specified precision and total width.
* Returns the value that the print method would print given the same
* double value, width and precision.
* <p>
* <b>Examples:</b><br>
*
* <tt>formatDouble(1.5714,5,1)</tt> returns <tt>" 1.6"</tt>. <br>
*
* <tt>formatDouble(1.5714,5,2)</tt> returns <tt>" 1.57"</tt>. <br>
*
* <tt>formatDouble(1.5714,1,6)</tt> returns <tt>"1.571400"</tt>.
* <p>
*
* @param value the double to format
* @param width the target width (total number of characters in the string)
* @param precision the target precision (digits after the decimal point)
* @return the double value as a string, formatted as specified
*/
private static String formatDouble(double value, int width, int precision) {
String formatString = "0.";
for (int i = 0; i < precision; i++)
formatString += "0";
DecimalFormat pattern = new DecimalFormat(formatString);
String formatted = pattern.format(value);
return padLeft(formatted, width);
} // end formatDouble
/**
* Formats a double for output, with a specified total width and the
* default precision (6 digits after the decimal point).
*
* @param value the double to format
* @param width the target width (total number of characters in the string)
* @return the double value as a string, formatted as specified
*/
private static String formatDouble(double value, int width) {
return formatDouble(value, width, 6);
} // end formatDouble
/***************************************************************************
* The inner class FileObject does all the real work. A FileObject is either
* an InputFileObject for reading or an OutputFileObject for writing.
**************************************************************************/
private abstract class FileObject {
// the name of the file
protected String fileName;
Chapter 8 Appendix
// All methods are abstract. InputFileObject implements the read methods
// and aborts if the write methods are called. OutputFileObject
// implements the write methods and aborts if the read methods are called. See the
// top-level TextFile methods for descriptions of the functionality,
// parameters, etc.
public abstract String readLine();
public abstract String readWord();
public abstract void skipWhiteSpace();
public abstract char readChar();
public abstract int readInt();
public abstract double readDouble();
public abstract void println(String s);
public abstract void println(String s, int width);
public abstract void println(char c);
public abstract void println(int i);
public abstract void println(int i, int midWidth);
public abstract void println(double d);
public abstract void println(double d, int width);
public abstract void println(double d, int width, int precision);
public abstract void println(boolean b);
public abstract void println(Object obj);
public abstract void println();
public abstract void print(String s);
public abstract void print(String s, int width);
public abstract void print(char c);
public abstract void print(int i);
public abstract void print(int i, int width);
public abstract void print(double d);
public abstract void print(double d, int width);
public abstract void print(double d, int width, int precision);
public abstract void print(boolean b);
public abstract void print(Object obj);
public abstract void close();
public abstract boolean eof();
} // end class FileObject
/***************************************************************************
* An InputFileObject implements an input file, using the BufferedReader
* class.
**************************************************************************/
private class InputFileObject extends FileObject {
// The reader that does the real work.
private BufferedReader reader;
// Read-ahead; these characters have not been returned yet.
// When we reach the end of the input file, buffer is set to null.
private StringBuffer buffer = new StringBuffer();
// Value returned by private function to denote end of file.
private static final int EOF_VALUE = -1;
// True if this file is the standard input (so that we won't
// try to close it!)
private boolean standardInput = false;
public InputFileObject(String fileName) {
this.fileName = fileName;
Chapter 8 Appendix
try {
reader = new BufferedReader(new FileReader(fileName));
}
catch (FileNotFoundException e) {
abort("Error: input file \"" + fileName + "\" does not exist");
}
} // end constructor
public InputFileObject() {
this.fileName = "standard input";
reader = new BufferedReader(new InputStreamReader(System.in));
standardInput = true;
} // end constructor
// Three specific abort methods with frequently-used error messages
private void errorAbort() {
abort("I/O error while reading from file \"" + fileName + "\"");
} // end errorAbort
private void eofAbort() {
abort("attempt to read past end of input file \"" + fileName + "\"");
} // end eofAbort
private void writeAbort() {
abort("error: attempt to write to input file \"" + fileName + "\"");
} // end writeAbort
// Reads the next character from the input file and returns it as an
// int. If we're at the end of the file, returns -1 instead.
private int readCharOrEOF() {
try {
if (buffer == null) { // already hit EOF
return EOF_VALUE;
}
else if (buffer.length() == 0) {
String newLine = reader.readLine();
if (newLine == null)
return EOF_VALUE;
else {
buffer.append(newLine);
buffer.append('\n');
} // end if
} // end if
// If we get here, the buffer is not null or length 0, so return
// the next character
char result = buffer.charAt(0);
buffer.deleteCharAt(0);
return result;
} // end try
catch (IOException e) {
errorAbort();
return ' '; // keep compiler happy
} // end catch
} // end readCharOrEOF
// Pushes a character back onto the input stream. Used when we
Chapter 8 Appendix
// read a character we're not ready to send to the user.
private void pushChar(char ch) {
if (buffer == null)
buffer = new StringBuffer(ch);
else
buffer.insert(0, ch);
} // end pushChar
// Returns true if ch is a "whitespace" character
private boolean isWhite(char ch) {
switch (ch) {
case ' ':
case '\t':
case '\n':
return true;
default:
return false;
} // end switch
} // end isWhite
/* ***********************************************************************
* PUBLIC METHODS
*
* See header comments in top-level TextFile methods for descriptions
* of functionality, parameters, etc.
* ***********************************************************************/
public boolean eof() {
int nextChar = readCharOrEOF();
if (nextChar == EOF_VALUE)
return true;
else {
pushChar((char) nextChar);
return false;
} // end if
} // end eof
public void skipWhiteSpace() {
char ch = ' ';
while (true) {
if (eof()) {
buffer = null;
return;
}
else if (!isWhite(ch)) {
pushChar(ch);
return;
}
else
// we just read a whitespace character, so keep going
ch = readChar();
} // end while
} // end skipWhiteSpace
public String readWord() {
// skip white space, then read and accumulate characters
Chapter 8 Appendix
// until non white space character or eof
StringBuffer word = new StringBuffer();
skipWhiteSpace();
if (eof())
eofAbort();
while (true) {
if (eof())
return word.toString();
char ch = readChar();
if (isWhite(ch)) {
pushChar(ch);
return word.toString();
} else {
word.append(ch);
} // end if
} // end while
} // end readWord
public String readLine() {
if (eof())
eofAbort();
// read and accumulate characters until end of line or end of file
StringBuffer newLine = new StringBuffer();
int newChar = readCharOrEOF();
while (newChar != '\n' && newChar != EOF_VALUE) {
newLine.append((char) newChar);
newChar = readCharOrEOF();
} // end while
return newLine.toString();
} // end readLine
public char readChar() {
int ch = readCharOrEOF();
if (ch == EOF_VALUE)
eofAbort();
return (char) ch;
} // end readChar
public int readInt() {
String intWord = readWord();
try {
return Integer.parseInt(intWord);
} // end try
catch (NumberFormatException e) {
abort("error: \"" + intWord + "\" is not a legal integer");
return 0; // keep compiler happy
} // end catch
} // end readInt
public double readDouble() {
String doubleWord = readWord();
try {
return Double.parseDouble(doubleWord);
} // end try
catch (NumberFormatException e) {
abort("error: \"" + doubleWord + "\" is not a legal double");
return 0; // keep compiler happy
Chapter 8 Appendix
} // end catch
} // end readDouble
public void close() {
if (standardInput)
return; // don't close the standard input
try {
reader.close();
}
catch (IOException e) {
abort("Error while attempting to close file \"" + fileName
+ "\"");
}
fileName = "closed file";
} // end close
// Calling an output method for an object of this class is an error.
public void println(String s) {
writeAbort();
} // end println
public void println(String s, int width) {
writeAbort();
} // end println
public void println(int i) {
writeAbort();
} // end println
public void println(int i, int midWidth) {
writeAbort();
}
public void println(double d) {
writeAbort();
} // end println
public void println(double d, int width) {
writeAbort();
} // end println
public void println(double d, int width, int precision) {
writeAbort();
} // end println
public void println(char c) {
writeAbort();
} // end println
public void println(boolean b) {
writeAbort();
} // end println
public void println(Object obj) {
writeAbort();
} // end println
public void println() {
writeAbort();
} // end println
public void print(String s) {
writeAbort();
} // end print
public void print(String s, int width) {
writeAbort();
} // end print
public void print(int i) {
Chapter 8 Appendix
writeAbort();
} // end print
public void print(int i, int width) {
writeAbort();
} // end print
public void print(double d) {
writeAbort();
} // end print
public void print(double d, int width) {
writeAbort();
} // end print
public void print(double d, int width, int precision) {
writeAbort();
} // end print
public void print(char c) {
writeAbort();
} // end print
public void print(boolean b) {
writeAbort();
} // end print
public void print(Object obj) {
writeAbort();
} // end print
} // end class InputFileObject
/***************************************************************************
* An OutputFileObject implements an output file, using the PrintStream
* class.
**************************************************************************/
private class OutputFileObject extends FileObject {
// the writer that does the real work
private PrintStream writer;
public OutputFileObject(String fileName) {
this.fileName = fileName;
try {
writer = new PrintStream(new FileOutputStream(fileName));
}
catch (FileNotFoundException e) {
abort("Error: can't open file \"" + fileName + "\" for writing");
}
} // end constructor
public OutputFileObject() {
this.fileName = "standard output";
writer = System.out;
} // end constructor
// abort with a common error message
private void readAbort() {
abort("Error: attempt to read from output file \"" + fileName
+ "\"");
} // end readAbort
/* ***********************************************************************
* PUBLIC METHODS
Chapter 8 Appendix
*
* See header comments in top-level TextFile methods for descriptions
* of functionality, parameters, etc.
* ***********************************************************************/
public void println(String s) {
print(s);
println();
} // end println
public void println(String s, int width) {
print(s, width);
println();
} // end println
public void println(int i) {
print(i);
println();
} // end println
public void println(int i, int width) {
print(i, width);
println();
} // end println
public void println(double d) {
print(d);
println();
} // end println
public void println(double d, int width) {
print(d, width);
println();
} // end println
public void println(double d, int width, int precision) {
print(d, width, precision);
println();
} // end println
public void println(char c) {
print(c);
println();
} // end println
public void println(boolean b) {
print(b);
println();
} // end println
public void println(Object obj) {
print(obj);
println();
} // end println
public void println() {
writer.println();
} // end println
Chapter 8 Appendix
public void print(String s) {
writer.print(s);
} // end print
public void print(String s, int width) {
print(padLeft(s,width));
} // end print
public void print(int i) {
print(Integer.toString(i));
} // end println
public void print(int i, int width) {
print(formatInt(i, width));
} // end print
public void print(double d) {
print(Double.toString(d));
} // end print
public void print(double d, int width) {
print(formatDouble(d, width));
} // end print
public void print(double d, int width, int precision) {
print(formatDouble(d, width, precision));
} // end print
public void print(char c) {
print(c + "");
} // end print
public void print(boolean b) {
if (b)
print("true");
else
print("false");
} // end print
public void print(Object obj) {
print(obj.toString());
} // end println
public void close() {
if (writer != System.out) {
writer.close();
fileName = "closed file";
} // end if
} // end close
/* ***********************************************************************
* Calling an input method for an object of this class is an error.
* **********************************************************************/
public String readLine() {
readAbort();
return null; // keep compiler happy
Chapter 8 Appendix
} // end readLine
public int readInt() {
readAbort();
return 0; // keep compiler happy
} // end readInt
public double readDouble() {
readAbort();
return 0; // keep compiler happy
} // end readInt
public boolean eof() {
readAbort();
return false; // keep compiler happy
} // end eof
public char readChar() {
readAbort();
return ' '; // keep compiler happy
} // end readChar
public String readWord() {
readAbort();
return null; // keep compiler happy
} // end readChar
public void skipWhiteSpace() {
readAbort();
} // end skipWhiteSpace
} // end class OutputFileObject
} // end class TextFile
Related docs
Get documents about "