Michael Sweeney, School of Computer Science, University College - University of NSW, Australian Defence Force Academy, Canberra ACT Australia; and C3 Research Centre, Fern Hill Park, Defence Science and Technology Organisation, Department of Defence, Canberra ACT Australia. mike.sweeney@dsto.defence.gov.au
A significant number of web sites are designed to offer custom services such as content indexing, geospatial mapping, and calendar functions. Many existing command line applications could be made available as web services if an efficient method of web integration could be developed. By exploiting the flexibility of scripting languages such as Perl, Python, and TCL, existing programs can be reused in the web environment with minimal work.
This paper describes the design issues encountered when wrapping a command line application for web use. Problems such as URL argument ordering, performance, security, and error handling are identified and discussed.
An example web image processing service is presented. The image processor is sent a set of processing operations and filenames embedded in a HTTP POST URL (from a web form, HTML image reference, hyperlink, or web-aware application) and the synthesised image is returned in HTTP JPEG format. It is based on the freely available xloadimage command line application and uses a CGI based Python script to integrate with the web. The prototype has been successfully used to perform dynamic cropping and scaling functions on medium sized map images to support a simple GIS. The script is dissected and the benefits and limitations of the prototype design is presented.
Web Services, Image processing, Python, CGI, HTTP.
A significant number of web sites are designed to offer custom services such as content indexing, geospatial mapping, and calendar functions. Client browsers interact with the service by activating hyperlinks or completing forms which serve as input to the web service. The service executes the required actions and sends back a result in the form of a web page or graphics image. Web services are typically constructed with custom programs, databases, and specialist commercial packages.
An example of such a web service is the CubeView - Web Mapping Testbed demo [HREF7] that is provided by the Canadian CubeWerx Spatial Data Warehousing [HREF8]. This web based application takes a number of arguments expressed within a URL and returns a custom map segment that has been assembled to order. This web service is not implemented as a simple script-wrapped executable; however it demonstrates the web interface and the practicality of the concept.
Many existing command line applications could be made available as web services if an efficient method of web integration could be developed. A typical command line application executes a transform or transaction operation described with a set of command line parameters and an input stream. The output consists of an optional text or graphic dataset, and a possible error message.
Modern scripting languages support powerful string manipulation with high operating system integration and are often used to receive web service requests, generate dynamic web pages, "glue" together systems using large compiled programs, and perform ad-hoc utility functions (Ousterhout 1998). By exploiting the flexibility and integration features of scripting languages such as Perl, Python, and TCL, existing programs can be reused in the web environment with minimal work.
To evaluate the effectiveness of using command line applications as web services, a common image transformation program called xloadimage was chosen to be wrapped with a script and made available on a web server. The web server receives requests for services using the HTTP protocol (Fielding 1999) and returns a MIME-compliant dataset such as a HTML document or JPEG image. The service will be configured to use the Common Gateway Interface (NCSA 1995) to receive the GET request from the web server and transmit the output image back to the client.
Web based application environments such as the Browser-based User-interface Service (BUS) (Sweeney 2000) can use web services to dynamically build web applications. Typically, a page will be created with an HTML image tag (Raggett et al. 1999) using a reference to the web service defined in a URL. The following example clips a 250 x 200 pixel rectangle from a large map image and returns a highly compressed JPEG image to the browser as part of a page:
<IMG SRC="http://myserver.com/hiat/cgi/imgproc.cgi?
a:clip=1240,635,250,200&f:jpegQ=20&q:file=../map/australia/nsw.gif">
The xloadimage program is open source software and copyrighted 1989 by Jim Frost of Centerline Software. It is available for most Unix platforms and included in the Redhat Linux 5.2 release. The command line specifies the operations to be performed and the images to operate on. An example is:
xloadimage -clip 50,50,120,240 -zoom 160 -brighten 70 test.gif
This command will load the image "test.gif", clip a region 120 pixels wide and 240 pixels high starting at the pixel coordinates (50,50) , then enlarge the region to 160% and reduce the brightness to 70%. The default action is to display the image in a window; however there is an option to dump the resulting image to a JPEG file, for example:
xloadimage -clip 50,50,120,240 -zoom 160 -brighten 70 test.gif
-dump jpeg,quality=50 newtest.jpg
The dump option will write the image to the specified file in JPEG format using the quality value of 50 (which provides moderate compression and minimal visual artifacts).
The input to a web service is a URL. This is a combination of the protocol, host name, path to the resource, and an argument list in name-value pair format (Berners-Lee et al. 1998). The above command line example would be encoded into the following URL:
http://myserver.com/hiat/cgi/imgproc.cgi?
a:clip=50,50,120,240&b:zoom=160&m:brighten=70&q:file=../map/web/test.gif
The HTTP GET and POST protocols are not guaranteed to keep name-value pair order so pipelined operations specified in the URL may be executed on the server in random order - an undesirable property (scale then crop is different to crop then scale). To allow the client to specify order for the processing operations, a two character prefix of "letter+colon" is to be added to each operation name. The service will sort (using ASCII order) the operations by prefix, and then will remove the prefixes. Gaps in letter sequences will be permitted; however operations that use the same letter will be executed in undefined order. The output modifiers jpegQ and jpegS are independent of order but they still require an ordering prefix (which is ignored). Omitting a prefix for any operation will cause a fatal error.
The xloadimage program can output images in a number of formats but the most compatible for use as web graphics is JPEG. The compression level (termed quality) and smoothing value can be specified in the program command line. These options will be exposed via the URL parameters.
Image transformation and merging is specified with a number of ordered operations. As the xloadimage program can also display images on the screen, not all command line options will be useful to a web service. The image operations available via the URL interface are listed in Table 1.
| Operation Name | Operation Arguments | Operation Function |
|---|---|---|
| zoom | percentage (decimal) | Decrease or increase image size. |
| xzoom | as zoom | Changes horizontal size. |
| yzoom | as zoom | Changes vertical size. |
| clip | x,y,w,h | Clips a sub-image at x,y with w,h width and height. |
| rotate | 90,180,270 | Rotates an image. |
| brighten | percentage (decimal) | Decrease or increase image brightness. |
| gamma | ratio to 1.0 | Value 0 to 0.99 decrease and >1.0 increase brightness. |
| at | x,y | Place current image in the previous at x,y. (use after merge) |
| colors | 2-65535 | Reduce colour map for smaller file size. |
| smooth | "1" if on | Reduce pixelation at high zoom level. (slow) |
| gray | "1" if on | Convert colour map to gray scale. |
| merge | "1" if on | Merge next image onto previous one. |
| normalize | "1" if on | Normalise colour map for even brightness. |
| file | path and filename | File path and name for processing. |
| jpegq | 1-100 | Quality factor for compression (smaller=high compression) |
| jpegs | 0-100 | Smoothing factor for output jpeg |
Table 1. Operation List
To ease the task of writing the URL, the script will be configured to remove leading and trailing white space from values, and transform option names into lower case (as required by the program). If an operation name is provided that is not in Table 1, or values supplied that are outside the given range, an error will result. The error text will be sent to the script stderr stream and appear in the web server log. The resulting image returned will be a standard "error JPEG image" copied from the file system where the script is located.
The input file formats that can be processed by xloadimage (and hence the web service) are:
The Python [HREF6] language was chosen for it's clear syntax, object-oriented features, powerful programming constructs, and extendable architecture (Lutz 1996). The extensive library support available makes adapting scripts to new protocols or functions possible with a minimum of work.
1 #!/usr/bin/python
2
3 try:
4 import cgi, os, string, sys
5 print 'content-type: image/jpeg\n'
6 sys.stdout.flush()
7
8 os.environ[ 'DISPLAY' ] = 'localhost:0'
9
10 opneedarglist = string.split(
'xzoom yzoom zoom gamma brighten rotate at clip colors' )
11 opsinglelist = string.split( 'smooth gray merge normalize' )
12 opall = opneedarglist + opsinglelist + ['file']
13
14 arglist = [ 'imgproc.py', '-quiet' ]
15
16 quality, smoothing = 80, 0
17
18 f = cgi.FieldStorage()
19 oplist = f.keys()
20 oplist.sort()
21 for k in oplist:
22 v = f[k]
23 if type(v) == type([]): v = v[0].value
24 else: v = v.value
25 v = string.replace( v, ' ', '' )
26 op = string.lower( k[2:] )
27 if op == 'jpegq': quality = int(v)
28 elif op == 'jpegs': smoothing = int(v)
29 else:
30 if op not in opall:
raise 'op not supported: '+op+' '+v
31 if op != 'file':
arglist.append( '-' + op )
32 if op not in opsinglelist:
arglist.append( v )
33 cmdarg = arglist + ['-dump', 'jpeg,quality=%u,smooth=%u' \
% (quality,smoothing), '/dev/stdout']
34 os.execvp( '/usr/bin/X11/xloadimage', cmdarg )
35
36 except:
37 sys.stderr.write( 'ERROR: %s (%s)\n%s\n' % sys.exc_info() )
38 os.execvp( 'cat', [ 'imgproc.py', 'errorpic.jpg' ] )
Figure 1. The Python script wrapper for the xloadimage web service
The script wrapper that implements the web service is shown in Figure 1. The main part of the program is contained within a "try" section which will cause the associated "except" exception handler section to be executed if an error occurs. The exception handler will send a simple diagnostic error message to the stderr stream and copy a local JPEG image file containing an error message or symbol to stdout.
The statements on lines 5 and 6 send a HTTP header to the client immediately so that the TCP connection is kept open while possibly lengthy image transformations are being executed. The xloadimage program (which will inherit the script process and environment) requires a display environment to be set (performed in line 8) even though the display will not be used. A list of operations that need an argument is initialised on line 10, and the list of operations that appear without argument is initialised on line 11. Line 12 creates a list of all legal operation names (except for jpegQ and jpegS which are treated specially as they are used in a different part of the command line).
The argument list is initialised on line 14 with the script name and an option (-quiet) to ensure nothing is sent to stdout except for image data. The two JPEG encoder variables are set to defaults on line 16. In lines 18 to 20, the URL name-value pairs are extracted and sorted by leading sort letter, then for each name in the URL, an argument is added to the argument list within the loop. Finally, the JPEG dump arguments are added (on line 33) and the command name and argument list is sent to the operating system for execution (on line 34). Note that the filename is specified to be "/dev/stdout" so the program will send the image to the stdout stream and not a file.
Within the main processing loop, each name-value pair is analysed and processed. The value is extracted in lines 22 to 24 and the result is cleaned of any space characters (which are not permitted in command line arguments but are often introduced with HTML forms) on line 25. The leading two characters (the letter and colon) are stripped off the name and the resulting keyword is converted to lower case. If the name is a JPEG encoding variable, the values are modified (on lines 27 and 28), else name is tested for legality (line 30), and added as an argument (line 31) with a possible associated value (line 32). Note that if the option was a file, only the value (the filename) is added to the argument list.
The new service behaved as expected and generated JPEG images to the web browser using URL based commands.

Figure 2. Original Image (91kB)
http://myserver.com/hiat/map/web/kuwaitma.gif
In Figure 2, the original test image is shown. It is a scanned map from the USGS [HREF1] web site in GIF format. The image is 450 by 324 pixels, is 91kB is size when compressed with GIF, and approximately 580kB when extracted to 32 bit RGB format.

Figure 3. Image colors reduced to 4 and brightness enhanced (65kB)
http://myserver.com/hiat/cgi/imgproc.cgi?a:colors=4&b:gamma=1.6&c:file=../map/web/kuwaitma.gif

Figure 4. Image clipped and zoomed to 185% then compressed to quality 10 (13kB)
http://myserver.com/hiat/cgi/imgproc.cgi?a:clip=100,100,250,150&b:zoom=185&
c:file=../map/web/kuwaitma.gif&d:jpegQ=10

Figure 5. Zoomed clipped image merged with other positioned reduced image (62kB)
http://myserver.com/hiat/cgi/imgproc.cgi?a:clip=50,0,220,150&b:zoom=200&c:file=../map/web/kuwaitma.gif&
d:merge=1&e:zoom=66&f:at=116,8&g:file=../map/web/kuwaitci.jpg
The images in Figures 3, 4, and 5 show the results of various image transformation operations performed by the new web service. The URL command strings were typed into a browser however the service was also tested with HTML form based commands, image references within a HTML document, and with web client software.

Figure 6. Openmap example
An OpenMap [HREF2] application was configured with a layer that called the image processing web service to generate cropped and scaled map images on demand. In Figure 6, we see two georeferenced images overlaying a vector based coast outline within the application. The two images were dynamically generated in response to the user pan and zoom operations.
The processing performance was evaluated for two large images. A form was used to create the image processing request, and the image was loaded into the OS cache before each measurement by a null image processing command. The service was timed on an AMD K2-400 PC with 256MB RAM, SCSI disks with PCI controller card, Linux 2.036 OS, Apache web server using CGI, xloadimage 4.1, netscape communicator 4.7 on the local host, and python 1.5.2 language release.
| Source | us_map_30secpixel_250652560v2.jpg | Iraq_South_H6B_91.jpg | |
|---|---|---|---|
| Content | 6663x3556 pixel RGB image | 1145x2085 pixel RGB image | |
| Size | 94.7 MB unpacked | 9.5 MB unpacked | |
| File | jpeg (7.3MB) | niff (71.1MB) | jpeg (828kB) |
| Zoom to 7% | 15 | 7 | 3 |
| Clip 512x512 | 15 | 7 | 3 |
| Clip 512x512& Zoom 165% | 16 | 7 | 3 |
Table 2. Processing Performance (seconds)
The processing times can be seen in Table 2. The web service performance was similar to raw xloadimage command line performance which indicates the overheads of the scripting language and CGI protocol are not significant. The niff (native format) is larger but useful for extra speed (showing a 50% improvement). It is interesting that combinations of operations do not add significantly to the processing time. The main cost seems to be in the first load, and clip or zoom operation. Subsequent operations are on a smaller dataset and execute rapidly.
There are a number of limitations that are due to the constraints of the protocols. A natural extension to this service would be the ability to carry out operations on remote images. Although the script would be capable of loading an image from a web server using the HTTP protocol, there is currently no way to express an embedded URL within another URL. Because both strings use the same character sequences to delimit name-value pairs, there is no way for the CGI script to know whether a name-value pair belongs to the inner or outer URL.
Receivers of images from the web service expect a JPEG image to be delivered when a URL is sent. If an error occurs and a text error message is returned, the client process will often be unable to handle it. For this reason error recovery is difficult. Currently the error is passed to the web server log, and an obvious error message image is displayed.
As the executable string is assembled from strings that the client supplies in the form of a URL, there exists a security hole where a malicious user could include piped commands or "backticked" commands within an argument. Currently the service does not protect against this attack and must be modified before use on the open internet. One solution is to search for forbidden characters such as the pipe or backtick and reject such URLs.
The xloadimage loads the entire image into memory before executing operations on it. This works well for small images however many large images requiring concurrent processing will stress the server and affect response times. This limitation restricts the uses of the service and needs to be factored in to approach taken with script-based designs. Applications that require the processing of large datasets or high request service rates need high performance custom software or commercial solutions.
The combination of scripting languages and web technology offers simple methods of reusing command line based programs within the web environment. The example script of about 40 lines enabled a command line image processing program to be sucessfully used from the web. Although there are limitations in the scalability, error handling, and security of these web services, their ease of development makes them useful in many small applications within an intranet, and with more development, on the internet at large.
Berners-Lee, et al. (1998) RFC 2396: URI Generic Syntax. Online at ftp://ftp.isi.edu/in-notes/rfc2396.txt [HREF5]
Fielding, R., et al. (June 1999) RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1. Online at ftp://ftp.isi.edu/in-notes/rfc2616.txt [HREF9]
Lutz, M. (1996) Programming Python. O'Reilly & Associates, Inc. Sebastopol, CA, USA.
National Center for Supercomputing Applications(NCSA) (1995) The Common Gateway Interface. University of Illinois at Urbana - Champaign, IL, USA. Online at http://hoohoo.ncsa.uiuc.edu/cgi/overview.html [HREF3]
Ousterhout, J.K. (1998) Scripting: Higher-Level Programming for the 21st Century. Computer, March 1998. p23-30.
Raggett, D. et al (Eds) (1999) HTML 4.01 Specification. Online at http://www.w3.org/TR/html401/ [HREF4]
Sweeney, M. (2000) BUS: a Browser Based User Interface Service for Web Based Applications. Proceedings of First Australasian User Interface Conference AUIC 2000, Australian Computer Science Communications, Volume 22, Number 5. IEEE Computer Society, Los Alamitos, California, USA.
Michael J. Sweeney, © 2000. The author assigns to Southern Cross University and other educational and non-profit institutions a non-exclusive licence to use this document for personal use and in courses of instruction provided that the article is used in full and this copyright statement is reproduced. The author also grants a non-exclusive licence to Southern Cross University to publish this document in full on the World Wide Web and on CD-ROM and in printed form with the conference papers and for the document to be published on mirrors on the World Wide Web.
[ Proceedings ]