Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Image Processing


May 1991/Image Processing

Image Processing

Part 2: Displaying Images And Printing Numbers

Dwayne Phillips


Dwayne Phillips works as a computer and electronics engineer with the United States Department of Defense. He has a Ph.D. in electrical and computer engineering at Louisiana State University. His interests include computer vision, artificial intelligence, software engineering, and programming languages.

Image processing is a visual task. You therefore must have a method of displaying images in various forms in order to process them. The first article of this series (CUJ, March 1991) discussed image input and the Tag Image File Format. This article presents techniques to print the numbers in an image, display the numbers in an image on a CRT, and display the image in color and grayscales on EGA and VGA monitors.

The C Image Processing System (CIPS) ties together these image-display subroutines. (I will include image processing operators in later articles.) The CIPS platform can call all the subroutines. CIPS was compiled and linked using Microsoft C 6.0. Certain display manipulation calls are unique to Microsoft, but you can substitute equivalents from Turbo C or other C implementations.

A key feature of CIPS is that it does not require a special image processing board, math coprocessor, 80286, or top of the line display. CIPS is a software system that runs on a basic PC, though a hard disk is highly recommended. While CIPS works for VGA, EGA, CGA, and monochrome displays, the system looks best with a VGA monitor. (You'll have to wait until next month to display images on CGA and monochrome).

Listing 1 shows the function main for CIPS. It declares two image arrays, each of 100x100 shorts. (See the March 1991 article for the cips.h header and the definition of ROWS, COLS, and other constants.) The image would look sharper if the image arrays were 500x500. Due to limitations of DOS, Intel's 80x86 segmented architecture, and other reasons, such large arrays are impractical. CIPS passs these two image arrays to various operators. Two arrays are necessary because most operations require one array for input and one for output.

The heart of Listing 1 is a simple user interface that gets parameters from the user and calls the available functions. Figure 1 shows the CIPS main menu (displayed by show_menu). All other menus are as simple as the main menu and are self-explanatory.

The Main Menu

Choice one in the main menu displays an image header. CIPS calls the read_tiff_header function (presented in the March 1991 article) and displays the header information.

Choice two displays the image numbers on the screen as text. Recall that images are two-dimensional arrays of numbers. When the operators that process these arrays do not return the expected results, you can stop and look at the numbers. CIPS first reads an image using read_tiff_image, then calls the function show_image (Listing 1) to display the numbers. show_image prints 20 rows of 18 columns each on the CRT.

Functions that operate on an image do not interact directly with the user. Instead, the system employs various user-interface functions. This structure allows you to write stand-alone image-processing programs in which you set the parameters in code, call the desired functions, and come back in several hours when the functions finish. The advantages of this system will become more apparent in future articles when certain functions will require large amounts of time to complete.

The parameters in all CIPS functions have the same form. Each function operates on an image file. The function get_image_name gets this file name. Four parameters important to all images — il (initial line), ie (initial element), ll (last line), and le (last element) — describe the four corners of the 100x100 image array. The images themselves are usually 500x500 or 600x600. CIPS, however, can handle only 100x100 portions at a time. The function get_parameters in Listing 2 asks the user to specify these parameters.

Choice three from the main menu sends the image numbers to a line printer. This choice prints a larger part of the image than the portion displayed from choice two. CIPS reads the image as in choice two and calls the function print_image (Listing 3) , which opens the printer file and calls perform_printing to do the printing. Figure 2 shows an example printed output.

The main limitation of printing the image numbers is the width of the paper. Using the default 10 characters per inch, you can fit only 17 columns of data on a page. Most printers have some form of condensed printing. My Hewlett-Packard DeskJet has several modes and fonts. You can send the printer commands from the code and experiment with fitting columns of data on a page. In one of the DeskJet modes, I can print 50 columns. The comments in Listing 3 explain how and where to insert commands to your printer.

Choice four displays the actual image. This month I discuss EGA and VGA displays. The next installment of this series will discuss display using halftoning, which works for CGA and monochrome monitors. EGA displays up to 640x350 pixels with 16 colors. VGA displays up to 640x480 pixels with 16 colors. VGA will also display 320x200 pixels with 256 colors. Example images I'll use have either 16 or 256 shades of gray. The function display_menu_for_display_image asks the user the type of image, the type of display adapter, and the desired method of display (see Listing 4) . CIPS then calls display_image.

Displaying The Image

Two values obtained here, invert and color_transform, need more explanation. The invert variable causes the display to be normal or inverted in color (like a photo negative). Sometimes the scanning process will produce a negative of the original image. Using invert allows you to display the negative as a positive.

The color_transform variable determines how to display an image with 256 shades of gray on a display that will show only 16. In this article we will map the 256 shades down to 16 in a simple and straightforward manner by dividing the original value by 16. In a future installment on histograms, CIPS wil use the color_transform variable.

The function display_image (Listing 4) first sets the horizontal, vertical, and display_mode variables. horizontal and vertical limit the size of the displayed image. They depend on the type of monitor, its mode, and the size of the image file. display_mode depends on the type of monitor and mode chosen by the user. display_image then sets the display to graphics mode.

display_image reads in 100x100 portions of the image and calls the function display_image_portion to display them. display_image_portion first looks at the invert parameter. If the user specified invert=1, the code goes through the image array and reverses the numbers by subtracting each value from the maximum display value. Next, the function loops through the image array and sets the pixels on the display. The four if statements in the loops set the color transform by dividing the number of colors in the image by the number of colors in the display.

There is one catch to displaying the images in color. The original images were scanned into gray scales, not color. Scanning color photographs into files with a color scanner (and then displaying them in color) is a completely different subject. When you display a gray scale image using colors, the result appears a bit odd. The function display_16_shades_of_gray displays 16 shades of gray, rather than 16 colors. Figure 3 shows the values as defined in the file graph.h, a Microsoft C 6.0 file with equivalents in other C compilers. A long (4-byte) word defines the 16 color values.

The three least-significant bytes of the long are the blue, green, and red values. Each of the values can only be six bits, and so ranges from 0 to 63 (00 to 3f hex). Notice in Figure 3 that_BLUE = 0x2a0000 (the blue value is 42 and the red and green are zero), _GREEN = 0x002a00 (green is on and blue and red are off), and_RED = 0x00002a (red is on and blue and green are off). To remap the 16 colors to be any shade, tint, or hue, you use the _remappalette function (a Microsoft function that also exists in Turbo C).

I want the 16 colors to be 16 shades of gray. Notice that _BLACK, _WHITE, _GRAY, and _BRIGHTWHITE each has equal values of blue, green, and red. When the three color guns have equal values, the result is a shade of gray. Therefore, the function display_16_shades_of_gray remaps the 16 color values to 16 gray shades by setting blue, green, and red to equal values ranging from 0 to 63 in steps of four.

Example Images

Photograph 1 shows a boy and Photograph 2 shows a house as displayed by CIPS. CIPS displayed these photographs in 16 shades of gray on a VGA monitor. An EGA monitor displays them exactly the same. I took the original photographs in black-and-white and scanned them with a Hewlett-Packard ScanJet Plus. CIPS displayed them and I took the photographs you see here using black-and-white film. (See the sidebar on shooting images on a CRT.) CIPS took about one minute to display these on my 10 Mhz 80286 machine. Your speed will vary according to your processor and disk drive speed. You can obtain these and other images on disk through The C Users Journal.

[Ed. Note: The CIPS source files printed in the March issue are not reproduced here because of their length. cip.h,tiff.c, and rtiff.c are available on the March code disk.]


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.