(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* *) (* by Steve Glassman *) (* Last modified on Mon Jan 4 13:55:33 PST 1993 by mhb *) (* modified on Mon Nov 2 12:45:44 PST 1992 by steveg *) <*PRAGMA LL*> (* An "Image.T" is a screen-independent specification of an {\it image}. An image is a pixmap that includes specifications for both color and resolution. It is rendered consistently across screen types in terms of its colors and size. *) INTERFACE Image; IMPORT Pixmap, Rd, ScrnPixmap, Thread, TrestleComm, VBT, Word, Wr; TYPE T = Pixmap.T; EXCEPTION Error; (* An "Image.Raw" is an array of pixels, with both resolution and color information. (It is like a "Pixmap.Raw", with the addition of resolution and color information.) An "Image.T" is built from one or more "Image.Raw" pixmaps. There are three types of "Image.Raw" pixmaps: The "RawBitmap" represents bitmaps (1-bit deep pixmaps); the "RawPixmap" represents pixmaps that do not have a color table; and the "RawPixmapCMap" represents pixmaps that use a color table. *) TYPE Pixel = Word.T; Mode = {Stable, Normal, Accurate}; RGB = RECORD r, g, b: REAL END; TYPE Raw = OBJECT width, height: INTEGER; xres, yres: REAL := 75.0; (* in pixels per inch *) METHODS get (h, v: INTEGER): Pixel; set (h, v: INTEGER; pixel: Pixel); END; RawBitmap = Raw BRANDED OBJECT END; RawPixmap = Raw OBJECT needsGamma := TRUE; colorMode := Mode.Normal; END; RawPixmapCMap = RawPixmap OBJECT colors: REF ARRAY OF RGB; END; (* If "pm" is a "Raw" pixmap, then "pm" contains "pm.height" rows, and each row contains "pm.width" elements. These fields are read-only after they are initialized. The pixels are accessed with (0,0) in the northwest corner and "(width-1,height-1)" in the southeast corner. The "pm.xres" and "pm.yres" fields specify the resolution at which "pm" was designed. The "get" and "set" methods retrieve and store individual elements of the pixmap. Each of the three subtypes of "Raw" interprets a ``pixel'' as follows: \begin{itemize} \item If "pm" is a "RawBitmap" pixmap, then it is guaranteed that the method "pm.get" will return a 0 or 1. In the call "pm.set(h,v,pixel)", only the least significant bit of "pixel" is used. \item If "pm" is a "RawPixmap", the pixels in "pm" encode an RGB value each of whose components is 8 bits. A "(r,g,b)" triple is stored as | r * 256 * 256 + g * 256 + b and each of "r", "g", and "b" is between 0 and 255. The field "pm.needsGamma" indicates whether to let Trestle gamma-correct the colors. The "pm.colorMode" field determines how each RGB value in the pixmap should be displayed on color-mapped display. \item If "pm" is a "RawPixmapCMap", the pixels in "pm" are used as in index into the color table stored in the field "pm.colors". \end{itemize} The colors used to display a colored pixmap "p" depends on a number of factors. The "p.colorMode" field is used to match colors in the pixmap with colors in the color table, as described in the "ScrnPixmap" interface. The matching depends on other applications running, on other pixmaps being displayed, and on the depth of the screen. The current implementation does not perform any dithering, except on monochrome screens. On monochrome screen, a very crude ``thresholding'' is performed: if the brightness of the color is more than 50\% of the maximum brightness, the screen's foreground color is used. Otherwise, the screen's background color is used. *) (* \subsubsection{Retrieving, storing, and creating ``raw'' pixmaps} An "Image.Raw" can be built from a reader containing an image in Jeff Poskanzer's ``portable anymap file'' (``pnm'') format, and a ``pnm'' description of an "Image.Raw" can be stored into a writer. There are many tools available in the public domain for manipulating images in ``pnm'' format and for converting between that format and other formats (e.g., GIF, X11, Macintosh PICT, HP PaintJet, and so on). There are three types of ``pnm'' files: \begin{itemize} \item ``pbm'' -- portable bitmap file \item ``pgm'' -- portable graymap file \item ``ppm'' -- portable pixmap file \end{itemize} Each of these format has two variants: ``raw'' and ``ascii''. In the ``ascii'' version, pixel values are stored as ASCII decimal numbers. In the ``raw'' version, pixel values must be less than 256 and are stored as plain bytes. *) PROCEDURE FromRd (rd: Rd.T): Raw RAISES {Thread.Alerted, Rd.Failure, Error}; <* LL = arbitrary *> (* Returns an "Image.Raw" from the reader "rd" containing an image in ``pnm'' format. Pixels in ``ppm'' files are normalized to 8 bits per channel and intensity values of ``pgm'' files are normalized to 8 bits. *) PROCEDURE ToWr (raw: Raw; wr: Wr.T) RAISES {Thread.Alerted, Wr.Failure}; <* LL = arbitrary *> (* Store an ascii description of "raw" into the writer "wr" using ``pnm'' format. *) (* Procedures "FromRd" and "ToWr" are not guaranteed to be idempotent because pixel values are normaized by "FromRd" to be 8 bits. Also, the ``pnm'' format produced by "ToWr" is either ascii ``pbm'' for subtypes of "RawBitmap" or ascii ``ppm'' for subtypes of "RawPixmap", whereas procedure "FromRd" can accept these formats as well as the ``raw'' variants and grayscale formats (``pgm''). The more serious limitation of using ``pnm'' format is that ``pnm'' does include any information about the pixmap resolution or color matching. "FromRd" will use the default reslution of a "Raw" and the default color parameters of a "RawPixmap"; "ToWr" simply ignores the resolution and color parameters. Finally, the following procedure is used to create an "Image.Raw" from a screen-dependent pixmap: *) PROCEDURE FromScrnPixmap ( spm: ScrnPixmap.T; st: VBT.ScreenType): Raw RAISES {TrestleComm.Failure}; <* LL.sup <= VBT.mu *> (* Returns a screen-independent "Raw" which describes the pixmap "spm" when displayed on "st". Any field of "Raw" that cannot be computed from "spm" and "st" is given its default value. For example, the "needsGamma" and the "colorMode" fields of pixmaps that are deeper than 1-bit. *) (* \subsubsection{Building an image from ``raw'' pixmaps} The remaining procedures in this interface create an "Image.T" from one or more "Image.Raw" pixmaps: *) PROCEDURE Unscaled (raw: Raw): T; <* LL.sup <= VBT.mu *> (* Returns a pixmap that will display as "raw". The pixels in "raw" will not be scaled regardless of the screen's resolution. *) (* So, for example, consider a pixmap "p" whose dimensions are 150 wide by 50 high. On a 75dpi screen (a typical 1993 vintage monitor), pixmap "p" would appear 2 inches wide and 2/3 inches high. On a high-resolution monitor of 300 dpi, pixmap "p" would appear .5 inches wid and 1/6 inches high. The "p.xres" and "p.yres" fields are ignored. If you wanted "p" to always appear as 2 inches by 2/3 inches, regardless of the pixel density of the monitor, you'd use "Scaled" instead: *) PROCEDURE Scaled (raw: Raw): T; <* LL.sup <= VBT.mu *> (* Return a pixmap that will display as "raw", scaled for the screen's resolution. The horizontal and vertical dimensions are scaled independently. *) (* The current implementation scales pixmaps by non-negative integer amounts: horizontally by "ROUND(dpiX/p.xres)" and vertcially by "ROUND(dpi.x/p.yres)", where "dpiX" and "dpiY" are the horizontal and vertical resolution of the screen, respectively, expressed in dots-per-inch. In the example above, suppose that "p.xres" and "p.yres" were both 75. On a 300 dpi screen, "p" would appear 2 inches wide and 2/3 inches high. Each pixel in "p" would appear as a block of 4x4 screen pixels. If the screen were 250 dpi horizontally and 175 dpi vertically, then "p" would appear 1-1/2 inches wide and 1-1/3 inches high. Each pixel in "p" would appear as a block of 3x2 screen pixels. *) END Image.