This is get_orion.c in view mode; [Download] [Up]
/* * getOrion.c - Put RLE images on a High-Level Hardware Orion * * Author: Gianpaolo F M Tommasi * Computer Laboratory * University of Cambridge * Last Edit: 19 July 1987 * * Based on code by Spencer W Thomas, John W Peterson and Mark Blommenthal * Copyright (c) 1986, University of Utah * */ #include <stdio.h> #include <math.h> #include <graphics/grafix.h> #include <graphics/window.h> #include <graphics/control.h> #include <graphics/events.h> #include <sys/ioctl.h> #include <machine/graphics.h> #include "rle.h" #ifdef USE_STDLIB_H #include <stdlib.h> #endif #define RASTERSIZE_LIM 1280 #define MONOCHROME_MODE 1 #define EIGHT_BIT_COLOUR_MODE 2 #define MONOCHROME_ENTRIES 128 /* TRUE and FALSE defined in graphics/grafix.h */ typedef int boolean; /* logical vars and values */ /* RLE Scanline storage & row pointers */ unsigned char scanline[4][RASTERSIZE_LIM], *rows[4]; /* Scanline to be written to device points to scanline bitmap*/ unsigned char dest_pixels[RASTERSIZE_LIM]; /* Variables for translate_bits: bitmap for scan line and rectangle */ BitMap scanbitmap; Rect trandr; /* dither matrix */ int dm16[16][16]; /* tables for quantisation */ int errN[256], divN[256]; /* The gamma map and default gamma */ int gammamap[256]; float gam = 2.0; /* good default value */ /* Colour map flags */ boolean linear_flag = FALSE; boolean gamma_flag = FALSE; boolean all_colours_flag = FALSE; /* What mode to dither into. Either 8 bit color or monochrome */ int put_mode = EIGHT_BIT_COLOUR_MODE; /* Colour map to be written to device */ int n_colmap_colours; int colmap[256][3]; /* StarPoint variables */ WindowPtr rle_window; EventRecord myEvent; WindowPtr whichWindow; Point myPt; int thePart; boolean isActive = FALSE; int window_size_x, window_size_y; /* Debug flag */ boolean debug_flag = FALSE; /* reverse order of scan lines */ boolean reverse_flag = FALSE; /* make a special case of having 1 colour channel and 3 colour map channels */ boolean onec_threem_mode = FALSE; /**************************************************************************** * TAG( main ) * * Usage: * getOrion [-D] [-b] [-f] [-g gamma] [-l] [-r] [file] * * Inputs: * -D: Degub mode. * -b: Dither to monochrome picture * -f: Use all the 256 entries of the device colour look-up table * -g gam: Gamma map, use a gamma of gam (floating point number) * -l: Linear map (gamma of 1) * -r: Reverse the order of display of scanlines, i.e. start from * the top * file: Input Run Length Encoded file, stdin used if not * specified. * Outputs: * Puts image on the screen. * Assumptions: * Input file is in RLE format. * Algorithm: * [none] */ main(argc, argv) int argc; char *argv[]; { int i, temp; int bw_flag = 0; char *infname = NULL, *window_name; FILE *fopen(); Rect r; /* Get command line arguments */ if (scanargs(argc, argv, "getOrion D%- w%- f%- g%-gamma!f l%- r%- infile %s", &debug_flag, &bw_flag, &all_colours_flag, &gamma_flag, &gam, &linear_flag, &reverse_flag, &infname) == 0) exit(1); /* Open file for reading, if no filename was specified, read from stdin */ rle_dflt_hdr.rle_file = rle_open_f("get_orion", infname, "r"); temp = rle_get_setup(&rle_dflt_hdr); if (temp < 0) { fprintf(stderr, "getOrion: error reading setup information from %s\n", infname ? infname : "stdin"); fprintf(stderr, "with return code %d\n", temp); exit(1); } if (debug_flag) rle_debug(1); /* a linear map has no gamma correction */ if (linear_flag) gam = 1.0; /* Set up gamma correction table */ init_gamma_map(); /* we're only interested in R, G and B */ RLE_CLR_BIT(rle_dflt_hdr, RLE_ALPHA); for (i = 3; i < rle_dflt_hdr.ncolors; i++) RLE_CLR_BIT(rle_dflt_hdr, i); /* Set up rows to point to our copy of the scanline */ for (i = 0; i < 3; i++) rows[i] = scanline[i]; /* Pretend origin is at 0,0 */ rle_dflt_hdr.xmax -= rle_dflt_hdr.xmin; rle_dflt_hdr.xmin = 0; rle_dflt_hdr.ymax -= rle_dflt_hdr.ymin; rle_dflt_hdr.ymin = 0; /* shift the colour map, if present, down to 8 bits precision */ for (i = 0; i < rle_dflt_hdr.ncmap * (1 << rle_dflt_hdr.cmaplen); i++) rle_dflt_hdr.cmap[i] = rle_dflt_hdr.cmap[i] >> 8; if (bw_flag) { put_mode = MONOCHROME_MODE; init_monochrome_colour_map(); } else if ((rle_dflt_hdr.ncmap == 3) && rle_dflt_hdr.ncolors == 1) { /* one channel and 24-bit colour map supplied */ init_24_bit_colour_map(); onec_threem_mode = TRUE; } else /* use 216 standard colour map */ init_8_bit_colour_map(); /* Initialise the device and create window */ InitGraf(); window_size_x = rle_dflt_hdr.xmax + 1; window_size_y = rle_dflt_hdr.ymax + 1; SetRect (&r, 50, 50, window_size_x, window_size_y); if (infname == NULL) window_name = "piped"; else { window_name = infname; } rle_window = NewWindow(NIL, r, window_name, VISIBLE, noGrowDocProc, FRONT, GOAWAY, 0, 7); PenPat(black); UpdateWindow(rle_window, TRUE); write_colour_map(); /* make the scan line bit map */ scanbitmap = NewRBitMap(window_size_x, 1, 8); /* really need only one pla ne */ /* Get the scanlines */ for (i = rle_dflt_hdr.ymin; i <= rle_dflt_hdr.ymax; i++) { rle_getrow(&rle_dflt_hdr, rows); if (put_mode == MONOCHROME_MODE) put_line_mono(i); else put_line_8(i); } /* loop */ EventLoop(); } /************************************************* * TAG (init_gamma_map ) * * Compute a gamma correction map */ init_gamma_map() { int i; for (i = 0; i < 256; i++) { gammamap[i] = (int) (0.5 + 255 * pow(i / 255.0, 1.0/gam)); } } /********************************* * TAG( init_8_bit_colour_map ) * * Initialise the 8 bit colour map */ init_8_bit_colour_map() { double gamma; /* Set up the colour map entries. We will use 216 colours. */ n_colmap_colours = 216; /* calculate tables but don't gamma correct the colour map */ gamma = 1.0; dithermap(6, gamma, colmap, divN, errN, dm16); } /************************************************************ * TAG( init_monochrome_colour_map ) * * Initialize the monchrome colour map. This routine is called when the -b * flag is used. */ init_monochrome_colour_map() { int i, bwmap[256]; double gamma; /* Set up the colour map entries into a single greyscale ramp */ n_colmap_colours = MONOCHROME_ENTRIES; /* calculate tables but don't gamma correct the colour map */ gamma = 1.0; bwdithermap(n_colmap_colours, gamma, bwmap, divN, errN, dm16); for (i = 0; i < n_colmap_colours; i++) colmap[i][0] = colmap[i][1] = colmap[i][2] = bwmap[i]; } /*********************************************** * TAG (init_24_bit_colour_map) * * Sets the colour map to the one supplied in the RLE header * */ init_24_bit_colour_map() { int i, g_offset, b_offset; /* set up the colour map entries, will use the number supplied in the header */ n_colmap_colours = 1 << rle_dflt_hdr.cmaplen; g_offset = n_colmap_colours; b_offset = 2 * g_offset; /* set the device colour map to the one in the header */ for (i = 0; i < n_colmap_colours; i++) { colmap[i][0] = rle_dflt_hdr.cmap[i]; colmap[i][1] = rle_dflt_hdr.cmap[i + g_offset]; colmap[i][2] = rle_dflt_hdr.cmap[i + b_offset]; } } /* Dithering operation */ #define DMAP(v, x, y) (errN[v]>dm16[x][y] ? divN[v]+1 : divN[v]) /************************************************************ * TAG(put_line_8) * * Map a 24 bit scanline to 8 bits through the dither matrix */ put_line_8(yscan) int yscan; { unsigned char *r, *g, *b; int i, dither_col, dither_row; int xmax = rle_dflt_hdr.xmax; int g_offset, b_offset; unsigned char *dest_pixel_ptr; /* treat 1 colour and 3 colmap channels as special case */ if (onec_threem_mode) { bcopy(rows[0], dest_pixels, xmax+1); write_scanline(yscan); return; } dither_row = yscan % 16; dither_col = 0; dest_pixel_ptr = dest_pixels; r = rows[0]; /* check if we have less than three colour channels */ g = rows[(rle_dflt_hdr.ncolors >= 2 ? 1 : 0)]; b = rows[(rle_dflt_hdr.ncolors >= 3 ? 2 : 0)]; /* RLE file with colour map */ if (rle_dflt_hdr.ncmap) { /* offsets to the green and blue sections of the map */ g_offset = 1 << rle_dflt_hdr.cmaplen; b_offset = 2 * g_offset; for (i = 0; i <= xmax; i++, r++, g++, b++, dither_col = ((dither_col + 1) & 15), dest_pixel_ptr++) *dest_pixel_ptr = DMAP(rle_dflt_hdr.cmap[*r], dither_col, dither_row) + DMAP(rle_dflt_hdr.cmap[*g + g_offset], dither_col, dither_row) * 6 + DMAP(rle_dflt_hdr.cmap[*b + b_offset], dither_col, dither_row) * 36; } else for (i = 0; i <= xmax; i++, r++, g++, b++, dither_col = ((dither_col + 1) & 15), dest_pixel_ptr++) { *dest_pixel_ptr = DMAP(*r, dither_col, dither_row) + DMAP(*g, dither_col, dither_row) * 6 + DMAP(*b, dither_col, dither_row) * 36; } /* Write the scanline to the device */ write_scanline(yscan); } /***************************************************************** * TAG( put_line_mono ) * * Dither into monochrome */ put_line_mono(yscan) int yscan; { unsigned char *r, *g, *b; int i, dither_col, dither_row; unsigned char *dest_pixel_ptr; int xmax = rle_dflt_hdr.xmax; int bw_val; int g_offset, b_offset; dither_row = yscan % 16; dither_col = 0; dest_pixel_ptr = dest_pixels; r = rows[0]; /* check if we have less than three colour channels */ g = rows[(rle_dflt_hdr.ncolors >= 2 ? 1 : 0)]; b = rows[(rle_dflt_hdr.ncolors >= 3 ? 2 : 0)]; /* RLE file with colour map */ if (rle_dflt_hdr.ncmap) { /* offsets in table */ g_offset = 1 << rle_dflt_hdr.cmaplen; b_offset = 2 * g_offset; for (i = 0; i <= xmax; i++, r++, g++, b++, dither_col = ((dither_col + 1) & 15), dest_pixel_ptr++) { bw_val = (35 * rle_dflt_hdr.cmap[*r] + 55 * rle_dflt_hdr.cmap[*g + g_offset] + 10 * rle_dflt_hdr.cmap[*b + b_offset]) / 100; *dest_pixel_ptr = DMAP(bw_val, dither_col, dither_row); } } /* Gamma correction is the default */ else for (i = 0; i <= xmax; i++, r++, g++, b++, dither_col = ((dither_col + 1) & 15), dest_pixel_ptr++) { bw_val = (35*(*r) + 55*(*g) + 10*(*b)) / 100; *dest_pixel_ptr = DMAP(bw_val, dither_col, dither_row); } /* write the scanline */ write_scanline(yscan); } /* graphics device colour look-up table operations */ #define WriteCLT(cltp) (ioctl (_gdev, GTIOCSCLT, &(cltp))) #define ReadCLT(cltp) (ioctl (_gdev, GTIOCGCLT, &(cltp))) /*********************************************** * TAG ( write_colour_map ) * * Loads the graphics colour look up table */ write_colour_map() { int cltable[256], i; int *cltp = cltable; /* to avoid warning */ int terminate; /* Need to preserve colours 240-255 by default */ if (all_colours_flag) terminate = 256; else { /* read in current CLT */ ReadCLT(cltp); terminate = (n_colmap_colours < 240 ? n_colmap_colours : 240); } /* create the colour look up table, changing only required number of colours, and gamma correcting */ for (i = 0; i < terminate; i++) cltable[i] = (gammamap[colmap[i][0]] << 16) + (gammamap[colmap[i][1]] << 8) + gammamap[colmap[i][2]]; /* Write it to the device */ WriteCLT(cltp); } /******************************************************** * TAG ( write_scanline ) * * writes the scanline data, held in dest_pixels, to the device */ write_scanline(yscan) int yscan; { if (!reverse_flag) yscan = rle_dflt_hdr.ymax - yscan; /* the following may seem like a long-winded way of doing things, * but it's a lot quicker than setting points and lines with the usual * routines . */ /* set destination rectangle */ SetRect(&trandr, 0, yscan, window_size_x, 1); /* translate the scanline data to the corresponding strip in the window */ translate_bits(&((*rle_window).port.portBits), trandr); /* add strip to the update list of window and update */ AddUpdate(rle_window, trandr, 255); UpdateWindow(rle_window, TRUE); } /* translate_bits - takes a scanline (dest_pixels) and translates the bits * within the bytes so to be able to display it in BW mode. It extracts * a plane of bits made out of the bits from the same position within a * byte from the source scanline. Each plane is then rasterop-ed to the * corresponding plane in the window bit map. The version is not general * since it has been tuned to the current requirement, a more general * version can be found in the StarPoint Library. * Inputs: db is the destination BitMap, * dr is a rectangle specifying where in the window to put the scanlin e */ translate_bits(db, dr) BitMapPtr db; Rect dr; { Ptr sa = scanbitmap.baseAddr; unsigned sw = scanbitmap.rowBits; Ptr da = db->baseAddr; int dy = top(dr); unsigned dw = db->rowBits; unsigned dh = db->colBits; unsigned dps = db->planeSize; int cw = width (db->bounds); int ch = height (db->bounds); unsigned w = window_size_x; int *scanad; unsigned char *srcad; register int dest; int bitpos, bytes_in_source; int plane = 7; /* all planes are of interest */ while(plane+1) { scanad = scanbitmap.baseAddr; /* baseAddr is always word-aligned */ srcad = dest_pixels; bitpos = dest = 0; bytes_in_source = window_size_x; while(bytes_in_source){ /* *srcad++ >> plane is a logical shift */ dest = dest | (((*srcad++ >> plane) & 0x01) << bitpos); if (bitpos++ == 31) { *scanad++ = dest; dest = bitpos = 0; } bytes_in_source--; } *scanad = dest; /* might be some residue */ /* raster op the translated scanline to the plane in window */ rasterop(sa, sw, 1, 0, 0, da, dw, dh, 1, 23, cw, ch, 0, dy, w, 1, srcCopy); plane--; da += dps; } } /******************************************************************** * TAG( EventLoop ) * * Deals with StarPoint. */ EventLoop () { while (TRUE) { GetNextEvent (everyEvent, &myEvent); switch (myEvent.what) { case mouseDown: whichWindow = (WindowPtr) myEvent.refCon; switch (FindWindow (myEvent.where, whichWindow)) { case inGoAway: if (TrackGoAway (whichWindow, myEvent.where)) { MyClose (); } break; case inDrag: DragWindow (whichWindow, myEvent.where, stdBoundsRect); break; case inContent: if (whichWindow != FrontWindow ()) { BringToFront (whichWindow); } else { myPt = myEvent.where; GlobalToLocal (&myPt); } break; } break; /* End of mouseDown */ case activate: MyActivate (); break; } } /* while (TRUE) */ } MyClose () { exit (0); } MyActivate () { WindowPtr theWindow; Bool theState; theWindow = (WindowPtr) myEvent.message; theState = (myEvent.modifiers & activateFlag) != 0; if (theState) { if (!isActive) { HiliteWindow (theWindow, TRUE); SetPort (theWindow); isActive = TRUE; } } else { HiliteWindow (theWindow, FALSE); isActive = FALSE; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.