OhioLINK was excited and privileged to participate in the second annual Google Summer of Code — a program to inspire young developers and provide students in Computer Science and related fields the opportunity to do work related to their academic pursuits during the summer, and to support existing open source projects and organizations. This is the first of three posts summarizing the efforts of three students; this one details the work of Juan Pablo Garcia Ortiz, a Ph.D. candidate at the University of Almeria in Spain, to build a JPEG2000 JPIP Streaming Server and Client Browser Viewer Applet. This is an edited version of his final report.
JPIP Streaming Server
The JPIP Streaming Sever was not the primary focus of Juan Pablo’s efforts, but it was required in order to achieve the primary objective. It is a very simple implementation, supporting only HTTP channels with JPP streams. The server is multi-threaded and supports channel reconnection. Only a reduced set of JPIP parameters are supported — the ones necessary for the implementation of the Java JPIP client. (In Juan Pablo’s opinion, the simple image browser client he was developing did not require additional functionality at the server end.)
The multi-threaded mechanism is implemented with the Linux ‘pthread’ library and uses one thread for each client socket. The source code is written in C++, using the STL library to simplify the code, making it more legible, and orienting it to the object oriented programming philisophy. The different modules of the program are:
- report.cpp (report.h): For the class ‘report’, used to generate the applications logs.
- sock.cpp (sock.h): For the class ‘sock’, used to simplify the sockets work in Linux.
- j2k.cpp (j2k.h): Contains the class ‘j2k_image_file’, used to abstract the work with J2K images. It also contains the necessary code to initialize the Kakadu message handling system.
- jpip.cpp (jpip.h): Contains several classes to support a basic version of the JPIP protocol, over the Kakadu library.
- jpip_server.cpp: The main module.
It is recommended to start from a freshly unpacked (but not yet build) version of the Kakadu library source code (version 5.1). To build this JPIP, follow these steps:
- At the top level of the Kakadu source directory, checkout the ‘jpip_server’ directory from the OhioLINK Subversion respository. The Subversion URI is https://drc-dev.ohiolink.edu/svn/jpip_server/
- Change the current directory into ‘jpip_server’ and call the script ‘ ‘. The script will create the Kakadu directory structure, apply some necessary patches, and build the Kakadu libraries. Please note that this script was written for Kakadu version 5.1 and the patches may not be required in subsequent versions.
- Run ‘make’ (inside the jpip_server directory)
The accepted parameters by the server can be seen executing ‘jpip_server -u’. The images served by the server must be, by default, in the same directory. The command line option ‘-ipath’ allows you to define a base path for all the requested images. This server can be tested with the ‘kdu_show’ application of the Kakadu package. (kdu_show is a Windows application, but can be executed in Linux with WINE without problems.)
JPIP Browser Applet
The second application is a JPIP Java viewer, implemented as an applet. It requires the Kakadu JNI library; the portions of the Kakadu JNI library for Windows and Linux required to implement the JPIP applet are included in the source code repository. To build the JPIP Java viewer, follow these steps:
- Checkout of the ‘J2KViewer’ directory from the OhioLINK Subversion respository. The Subversion URI is https://drc-dev.ohiolink.edu/svn/J2KViewer/.
- From within the J2KViewer directory, run ‘make’.
The build process creates a JAR file containing the viewer applet. It’s correct use would be to sign it with a official signature and include it into the appropriate Web page as an applet. The applet accepts the following parameters:
- “Image“: required, specifies the JPEG2000 image to view. If it’s a local image (not typical), this would be a path name (for example ‘
/home/jportiz/image.jp2‘). If it’s a remote image (the typical usage) through the JPIP server, it would be a JPIP URI (for example, ‘
jpip://server:9000/image.jp2‘). Do not include any JPIP parameters in this URI.
- “MiniViewWidth“: optional, specifies the width, in pixels, of the mini-view.
- “MiniViewHeight“: optional, specifies the height, in pixels, of the mini-view. The final mini-view size will be the maximum multiple by 2 size of the image that can be included within the specified mini-view size. By default, the mini-view size is 250×250.
To be able to test easily the applet, you can run ‘
make test‘ to create a ‘test.html’ file and a ‘test’ script. This script launches the applet viewer with the ‘test.html’ page. It is necessary to modify the ‘Image’ parameter of this HTML page to set the appropriate image location.
To test the applet within a web browser, you can run ‘
make test-signed‘ to create a signed JAR file, then open ‘test-signed.html’ with a Java compatible browser. Before opening the HTML page, it is necessary to modify the ‘Image’ parameter within the page to set the appropriate image location.
The viewer has a simple UI. It has a toolbar with two buttons, one to select the interaction mode (zoom or pan) and another one to show the mini-view window. There is a status bar where is showed the real image
size and the current scale, and in the right side, the current number of bytes read. In the center panel is the image — initially scaled by 2 fo fit it in the applet size. This behaviour can be modified easily in the code.
The mini-view window can be moved to any part of the main window. If it’s closed, it can be showed again with the associated button of the toolbar. The mini-view contains a red rectangle outlining the actual view of the main window. This red rectangle can be moved by dragging it and the corresponding view in the main window will be updated.
The applet requires that the Kakadu JNI library is stored in the user home directory (‘C:\Document And Settings\User’ in Windows and ‘/home/user’ in Linux). The applet detects if this library exists and if it is not found the applet allows it to be download automatically from the OhioLINK repository and stored it in the user home directory.
This is a brief description of the implemented classes:
- ChunkedInputStream: An InputStream derived class to decode HTTP chunked messages.
- HTTPMessage: The base class of all the HTTP message classes.
- HTTPRequest: Identifies a HTTP request.
- HTTPResponse: Identifies a HTTP response.
- HTTPSocket: Derives from Socket and allows HTTP messages to be sent and received in an easy way. In only supports send HTTP requests and receive HTTP responses (a client socket).
- ImagePanel: A GUI panel that can be included in any image browser. This panel has the necessary methods to load images and control its visualization. It supports the display of a mini-view of the image. All of the image navigation is controlled directly within this panel.
- ImageWindow: An interface to implement all the parent windows that include an ImagePanel obejct.
- J2KCache: A wrapper class for the Kdu_cache Kakadu class. This encapsulation allows another J2K engine to be used while avoiding the need to modify the design and code of the applet.
- J2KEngine: Contains all the necessary code to initialize the J2K engine. In our case, the Kakadu J2K engine.
- J2KException: A Exception derived class to identify the exceptions generated by the J2K code.
- J2KImage: This class contains all the necessary code to work with J2K images, local files as well as remote URIs. If the image is local, the Kakadu library functions are used to open it. If the image is remote, a J2KReader object is used to retreive the content.
- J2KImageView: Defines an image view, renderable on the screen. This image view is defined by its coordenates, size and resolution level.
- J2KReader: An implementation of a basic JPIP client to read the necessary data of a specific image view.
- J2KRender: Implements the rendering thread of the image browser. This thread is always generating the current image view. It stops when this view is rendered and the image content is completed (if the image is remote, this means that all of the required image codestream blocks have been received).
- J2KViewer: The main class of the application.
- JpipConstants: Defines several global constants related to the JPIP protocol.
- JpipDataInputStream: An InputStream-derived class to extract JPIP data segments from an input.
- JpipDataSegment: Contains the information of a JPIP data segment, which can be either an EOR message or a data-bin segment.
- Mutex: A simple mutex implementation in Java, used to avoid threads conflicts when accessing to the image data.
- StringInputStream: An InputStream-derived class to extract strings from inputs without buffering. Useful to decode HTTP headers and chunks lengths.
The viewer follows the JPIP philosophy in the code structure, especially with remote images. That is, when it is displaying a remote image, there are three threads running in parallel: one for the main GUI, a second for the JPIP comunication that is making the requests and filling the cache with the received data, and a third to render the cache content on the user’s display.
The Java JPIP viewer has been tested in Windows and in Linux. In Windows it has been used the Sun JVM/JRE 1.5 without problems. However, in Linux, this JVM/JRE version seems quite unstable, requiring the previous version, 1.4.2. In Linux the Blackdown JVM 1.4.2 as well as the Sun JVM 1.4.2 have been tested with succesful results.
Future Development Goals
The most important feature to include, in Juan Pablo’s opinion as well as my own, is to make the client applet independent of the Kakadu library; that is, to use an open source J2K engine. Juan Pablo is currently collaborating a bit with the HiRISE project in order to implement a pure Java JPIP code. It needs to use an efficient pure Java J2K engine. They are currently modifing the JJ2000 code in order to improve it and adapt it within the JPIP client. When this goal was reached, it should be included into the current J2KViewer implementation.
Another feature that was part of the original design but was not completed due to time pressures was to integrate the JPIP server and client into the FEDORA digital object repository system. There is also room for a lot of more features: support of the HTTP-TCPtransport protocol, allow for the display of the image metadata, more GUI utilities like the ability to save the image as a local file for image processing, increase the set of supported JPIP parameters, etc.
Gratitude and Acknowledgements
OhioLINK offers its congratulations to Juan Pablo for successfully completing the Google Summer of Code project and we look forward to working with him to continue the development effort. We anticipate integrating his work into the Ohio Digital Resource Commons Project in the coming year. We also offer our gratitude to Google for not only their financial support of the Summer of Code program but also for the efforts of Chris, Greg, Leslie and countless other Google staff members in supporting the logistics of this world-wide effort. I would also like to thank Ron Murray and others at the Preservation Reformatting Division of the Library of Congress for helping think through the requirements and their general support for the effort to bring JPEG2000 to the world of archives and libraries.
- Editorial comment: although not released with an open source license, the Kakadu JPEG2000 code library is available at a very reasonable cost. Juan Pablo’s efforts initially started with one of the open source JPEG2000 libraries, but it was quickly determined that the Kakadu library was required to meet the demands of the project proposal. [↩]