Path: utzoo!attcan!uunet!mcvax!enea!kth!draken!liuida!ingwa From: ingwa@teorix.liu.se (Inge Wallin) Newsgroups: comp.graphics Subject: bugfix for showpic and performance enhancement Message-ID: <963@teorix.liu.se> Date: 4 Oct 88 23:16:20 GMT Organization: CIS Dept, Univ of Linkoping, Sweden Lines: 611 Unfortunately, a bug crept into showpic. In the Floyd-Steinberg function floydfunc(), height and width were switched in the loop control. This didn't matter as long as one only used the program to view quadratic images, but would have resulted in very strange behaviours, and maybe even a core dump, if you had tried to look at rectangular ones. While I was at it, I made the program some 40% faster by skipping the calls to pr_put. I also fixed some grammar errors in the README and manual. Unfortunately the diffs were bigger than the entire posting of version 1.0, so I decided to send it all out again. ---------------------------clip here---------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh Makefile <<'END_OF_Makefile' X# X# Makefile for showpic X# X X#CFLAGS = -g XCFLAGS = -O X XLIBS = -lsuntool -lsunwindow -lpixrect X XOBJS = showpic.o X Xshowpic: $(OBJS) X $(CC) -o showpic $(CFLAGS) $(OBJS) $(LIBS) X Xshowpic.o: showpic.c showpic.icon X X Xshar: X shar Makefile README showpic.1 showpic.c showpic.icon >showpic.shar X X Xclean: X rm -f *.o core END_OF_Makefile if test 310 -ne `wc -c README <<'END_OF_README' X******************************************************************* X showpic 1.1 -- show ray traced images X X by Inge Wallin ingwa@majestix.liu.se X Jonas Yngvesson jonas-y@joakim.liu.se X X Linkoping Institute of Technology X Sweden X******************************************************************* X XThis is the README file for the showpic program. Showpic takes as input Xan image file, generated by Mark VandeWettering's ray tracer, and Xdisplays it on a SUN workstation. Unlike other programs which Xhave been posted lately, showpic shows the image in a standard Xsunview window. X XThe program is extremely simple and was developed because of the Xlack of SUNs with colour screens at this university. (Actually, Xthere are a few of those also, but they are mainly out of our reach.) XThus, there is no support for colour or gray scales in it. X XInstead, we have put in two half-toning algorithms, ordered dithering Xand the Floyd-Steinberg method. There is also a choise of a number of Xdither matrixes (currently 3) for those of you who don't like the Xstandard one. See the manual for further details! X XThe gray scale conversion used was provided on comp.graphics about a Xyear ago by Edward Falk. X XUnfortunately, no one of us have any great artistical talents, so the Xicon is not very beautiful. If anybody should feel like making a nicer Xone, we would be grateful if we could have a copy of it. X XDifferences between 1.1 and 1.0: X* A bug fixed. (switch of width and height in floydfunc()) X* Faster program. Use own bit fiddling instead of pr_put. X* Possibility of looking at files which are not finished. This X was made while waiting for a major ray tracing to finish. X* Some grammar errors in this file and the manual were corrected. X (Very possibly some others have been introduced.) X XAs before, please send any enhancements, bug reports and fixes to us. X XLinkoping 4 Oct 1988 X X enjoy! /Inge & Jonas END_OF_README if test 2002 -ne `wc -c showpic.1 <<'END_OF_showpic.1' X.\" Copyright 1988, Inge Wallin, Jonas Yngvesson X.\" This program and documentation may be distributed freely for X.\" non-commercial use only. X.TH SHOWPIC 1 "October 4, 1988" 1 X.UC 4 X.SH NAME Xshowpic \- show ray traced images on a SUN X.SH SYNOPSIS X\fBshowpic\fR [\fB\-u\fR] X[\fB\-f\fR] X[\fB\-d\fR[\fIn\fR]] X\fB\-\fR | \fIfilename\fR X.SH DESCRIPTION XShowpic shows an image, generated by Mark VandeWettering's ray tracer, Xin a sunview window. The program does not return, except when the \fB\-u\fR Xoption is given. X.PP XThe program look for \fIEOF\fR, so it is possible to look at images which Xare not finished. X.SH OPTIONS X.IP \fB\-u\fR XShow program usage and exit. X.IP \fB\-f\fR XUse the Floyd\-Steinberg algorithm for halftoning. This is the default. X.IP \fB\-d\fIn\fR XUse ordered dithering for halftoning. \fIn\fR is the number of the Xdither matrix you want to use. Currently there are 3 matrixes Xavailable so \fIn\fR has to be in the range 1 to 3. If no \fIn\fR Xis given, the program chooses a standard dither (number 1). X.PP XThe options \fB\-f\fR and \fB\-d\fR are exclusive and if both are Xpresent, the program uses the last one. X.PP XIf showpic sees a \fIfilename\fR as its last argument, it tries to show Xthat file. If a hyphen is given as the last argument, the image Xis read from stdin. This is useful, for instance, if you want to Xview compressed images, and use \fBzcat\fR(1) to uncompress them. X.SH AUTHORS XInge Wallin X.br XJonas Yngvesson X.SH BUGS XNo checks are made to see if the image is bigger than the screen. X.PP XIf you use the standard input feature, there is no way to stop the Xprogram with CTRL\-C. The reason for this is not entirely clear. X.PP XThe program should be expanded to handle gray scales and colour Xscreens. END_OF_showpic.1 if test 1741 -ne `wc -c showpic.c <<'END_OF_showpic.c' X/* X * showpic.c - show ray traced images on a SUN X * X * Copyright 1988 Inge Wallin and Jonas Yngvesson. X * X * Use it as you like, but don't try to sell it or use it for X * other commercial purposes. X */ X X#include X#include X#include X#include X X#define VERSION "1.1" X X#ifndef TRUE /* is sometimes defined by sunview */ X#define TRUE 1 X#define FALSE 0 X#endif X X#define INFILE 0 /* input from file */ X#define STDIN 1 /* input from stdin */ X X/* typedef unsigned short u_short; */ /* already exists!!!??! */ X Xextern char *malloc(); X XFrame frame; XCanvas picture_canvas; XPixrect *picture_pr; X Xu_short *picture; X X Xtypedef struct dither { X int size; X int shift; X int *table; X} Dither; X X Xint dithmat1[8][8] = { X { 0, 32, 8, 40, 2, 34, 10, 42 }, X { 48, 16, 56, 24, 50, 18, 58, 26 }, X { 12, 44, 4, 36, 14, 46, 6, 38 }, X { 60, 28, 52, 20, 62, 30, 54, 22 }, X { 3, 35, 11, 43, 1, 33, 9, 41 }, X { 51, 19, 59, 27, 49, 17, 57, 25 }, X { 15, 47, 7, 39, 13, 45, 5, 37 }, X { 63, 31, 55, 23, 61, 29, 53, 21 }}; X Xint dithmat2[8][8] = { X { 52, 44, 36, 124, 132, 140, 148, 156 }, X { 60, 4, 28, 116, 220, 228, 236, 164 }, X { 68, 12, 20, 108, 212, 252, 244, 172 }, X { 76, 84, 92, 100, 204, 196, 188, 180 }, X { 132, 140, 148, 156, 52, 44, 36, 124 }, X { 220, 228, 236, 164, 60, 4, 28, 116 }, X { 212, 252, 244, 172, 68, 12, 20, 108 }, X { 204, 196, 188, 180, 76, 84, 92, 100 }}; X Xint dithmat3[4][4] = { X { 0, 8, 3, 11 }, X { 12, 4, 14, 7 }, X { 2, 10, 1, 9 }, X { 13, 6, 15, 5 }}; X XDither dithers[] = { X {8, 2, (int *) dithmat1}, X {8, 0, (int *) dithmat2}, X {4, 4, (int *) dithmat3}, X}; Xint numdithers = sizeof(dithers) / sizeof(Dither); X X Xint redtab[256]; /* lookup tables for gray scale conversion */ Xint greentab[256]; Xint bluetab[256]; X Xchar *programname; X X Xvoid usage(exitstatus) Xint exitstatus; X{ X fprintf(stderr, "Usage: %s [-u] [-d[n]] [-f] - | filename\n", programname); X fprintf(stderr, "n between 1 and %d\n", numdithers); X exit(exitstatus); X} X X X Xvoid error(message) Xchar *message; X{ X fprintf(stderr, "%s: %s\n", programname, message); X exit(1); X} X X X X/* The icon */ Xshort icon_image[] = { X#include "showpic.icon" X}; XDEFINE_ICON_FROM_IMAGE(showpic_icon, icon_image); X X Xvoid create_windows(infilename, width, height) Xchar *infilename; Xint width; Xint height; X{ X char header[80]; X X sprintf(header, "showpic %s - %s", VERSION, infilename); X frame = window_create(NULL, FRAME, X FRAME_LABEL, header, X FRAME_ICON, &showpic_icon, X 0); X X picture_canvas = window_create(frame, CANVAS, X WIN_HEIGHT, height, X WIN_WIDTH, width, X CANVAS_AUTO_SHRINK, FALSE, X CANVAS_AUTO_EXPAND, FALSE, X 0); X X window_fit(frame); X X} X X X Xvoid ditherfunc(infile, dithernum, width, height) XFILE *infile; Xint dithernum; Xint width, height; X{ X int y, x; X int red, green, blue; X int gray; X int *dithermat; X int dithersize; X int dithershifts; X u_short mask; X int offset; X X dithermat = dithers[dithernum].table; X dithersize = dithers[dithernum].size; X dithershifts = 8 + dithers[dithernum].shift; X X offset = 0; X for (y = 0; y < height; y++) { X mask = 0x8000; X for (x = 0; x < width; x++) { X red = getc(infile); X if (red == EOF) { X x = width; X y = height; X } else { X green = getc(infile); X blue = getc(infile); X gray = (redtab[red] + greentab[green] + bluetab[blue]) >> X dithershifts; X if ( gray < *(dithermat + (y % dithersize) * dithersize + X (x % dithersize)) ) { X *(picture + offset) |= mask; X } X X if ((mask >>= 1) == 0) { X mask = 0x8000; X offset++; X } X } X } X X if (mask != 0x8000) { X mask = 0x8000; X offset++; X } X } X} X X X Xvoid floydfunc(infile, width, height) XFILE *infile; Xint width; Xint height; X{ X int y, x; X int red, green, blue; X int gray; X int err; X char *buffer1; X char *buffer2; X char *temp; X u_short mask; X int offset; X X int alphatab[256]; X int betatab[256]; X int gammatab[256]; X int deltatab[256]; X X buffer1 = malloc(width + 2); X buffer2 = malloc(width + 2); X if ((buffer1 == NULL) || (buffer2 == NULL)) { X error("Couldn't allocate buffers for error distribution."); X } X X /* Distribute the error as follows: */ X /* current pixel = A[y,x] */ X /* A[y, x+1] += err*7/16 */ X /* A[y+1, x-1] += err*3/16 */ X /* A[y+1, x ] += err*5/16 */ X /* A[y+1, x+1] += err*1/16 */ X for (y = 0; y < 256; y++) { X alphatab[y] = ((y - 128) * 7) / 16; X betatab[y] = ((y - 128) * 3) / 16; X gammatab[y] = ((y - 128) * 5) / 16; X deltatab[y] = ((y - 128) * 1) / 16; X } X X offset = 0; X for (y = 0; y < height; y++) { X err = 0; X for (x = 0; x < width + 2; x++) X *(buffer2 + x) = 0; X X mask = 0x8000; X for (x = 0; x < width; x++) { X red = getc(infile); X if (red == EOF) { X x = width; X y = height; X } else { X green = getc(infile); X blue = getc(infile); X gray = ((redtab[red] + greentab[green] + bluetab[blue]) >> 8) + X *(buffer1 + x + 1); X X if (gray < 128) { X *(picture + offset) |= mask; X err = gray; X } else { X err = gray - 256; X } X X if ((mask >>= 1) == 0) { X mask = 0x8000; X offset++; X } X X *(buffer1 + x + 2) += alphatab[err + 128]; X *(buffer2 + x ) += betatab[err + 128]; X *(buffer2 + x + 1) += gammatab[err + 128]; X *(buffer2 + x + 2) += deltatab[err + 128]; X } X } X temp = buffer1; X buffer1 = buffer2; X buffer2 = temp; X X if (mask != 0x8000) { X mask = 0x8000; X offset++; X } X } X} X X X Xvoid main(argc, argv) Xint argc; Xchar *argv[]; X{ X int i, j; X int width, height; X int ditherflag = FALSE; X int dithernum = 0; X int floydflag = TRUE; X int inputflag = INFILE; X char *infilename; X FILE *infile; X X programname = argv[0]; X for (i = 1; (i < argc) && (*argv[i] == '-'); i++) { X switch (*(argv[i] + 1)) { X X /* usage */ X case 'u': X usage(0); X break; /* not reached */ X X /* dithering */ X case 'd': X if (*(argv[i] + 2) != '\0') { X if ((*(argv[i] + 2) < '1') || X (*(argv[i] + 2) > numdithers + '0')) X usage(1); X else X dithernum = *(argv[i] + 2) - '1'; X } X ditherflag = TRUE; X floydflag = FALSE; X break; X X /* Floyd-Steinberg */ X case 'f': X ditherflag = FALSE; X floydflag = TRUE; X break; X X /* input from stdin */ X case '\0': X inputflag = STDIN; X break; X X default: X usage(1); X } X } X X if ((ditherflag + floydflag != 1) || /* better safe than sorry */ X ((i == argc) && (inputflag == INFILE))) X usage(1); X X if (inputflag == INFILE) { X infilename = argv[i]; X if ((infile = fopen(infilename, "r")) == NULL) { X error( "Couldn't open infile."); X } X } else { X infilename = "standard input"; X infile = stdin; X } X X if (fscanf(infile, "%d %d\n", &width, &height) != 2) { X error("Couldn't read image size."); X } X X picture = (u_short *) malloc(height * (width / 16 + 1) * sizeof(u_short)); X if (picture == NULL) X error("Couldn't allocate buffer for the picture"); X X /* uses the equation gray = 0.30*red + 0.59*green + 0.11*blue */ X for (i = 0; i < 256; i++) { X redtab[i] = 77 * i; X greentab[i] = 151 * i; X bluetab[i] = 28 * i; X } X X if (ditherflag) { X ditherfunc(infile, dithernum, width, height); X } else if (floydflag) { X floydfunc(infile, width, height); X } X fclose(infile); X X create_windows(infilename, width, height); X picture_pr = mem_point(width, height, 1, picture); X pw_write(canvas_pixwin(picture_canvas), 0, 0, width, height, X PIX_SRC, picture_pr, 0, 0); X X window_main_loop(frame); X exit(0); X} X X X END_OF_showpic.c if test 7915 -ne `wc -c showpic.icon <<'END_OF_showpic.icon' X/* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF, X 0xC000,0x0000,0x0000,0x0003,0xC000,0x0000,0x0000,0x0003, X 0xC000,0x0000,0x0000,0x0003,0xC000,0x0000,0x0000,0x0003, X 0xC000,0x0000,0x0000,0x0003,0xC000,0x5000,0x0000,0x0003, X 0xC000,0xA800,0x0000,0x0003,0xC001,0x5600,0x0000,0x0003, X 0xC000,0xA800,0x0000,0x0003,0xC001,0x5500,0x0000,0x0003, X 0xC000,0xA880,0x0000,0x0003,0xC002,0x5200,0x0020,0x0003, X 0xC000,0x4400,0x0068,0x0003,0xC001,0x1115,0x0054,0x0003, X 0xC000,0x88AA,0x88AA,0x0003,0xC000,0x2055,0x4154,0x0003, X 0xC000,0x04C6,0xA44C,0x0003,0xC000,0x0151,0x5110,0x0003, X 0xC000,0x0AA8,0xA888,0x0003,0xC000,0x0652,0x5620,0x0003, X 0xC000,0x00AC,0x2840,0x0003,0xC000,0x1551,0x5510,0x0003, X 0xC00A,0x0888,0xAA80,0x0003,0xC035,0x2622,0x5420,0x0003, X 0xC04A,0x4A44,0xAA40,0x0003,0xC115,0x1511,0x5510,0x0003, X 0xC08A,0x8A8A,0xA888,0x0003,0xC022,0x2555,0x5620,0x0003, X 0xC044,0x46AA,0xAC40,0x4003,0xC010,0x1155,0x5111,0x5003, X 0xC008,0x88AA,0xA88A,0xA803,0xC000,0x2255,0x6221,0x4003, X 0xC000,0x444A,0x4446,0xA403,0xC000,0x1111,0x1111,0x5003, X 0xC002,0x8888,0x8888,0x8803,0xC005,0x4222,0x1202,0x2003, X 0xC04A,0xA444,0xAA44,0x4003,0xC085,0x5111,0x5501,0x1003, X 0xC00A,0xA888,0xAA80,0x8003,0xC041,0x4223,0x5520,0x0003, X 0xC204,0x8444,0xAA40,0x0003,0xC861,0x1011,0x5500,0x0003, X 0xCE40,0x8C00,0xAA80,0x0003,0xDA02,0x2442,0x1220,0x0003, X 0xE540,0x4004,0x4440,0x0003,0xC110,0x1151,0x1100,0x0003, X 0xC800,0x0000,0x0000,0x0003,0xE218,0x0000,0x0000,0x0003, X 0xC640,0x0400,0x0000,0x1003,0xD310,0x0400,0x0000,0x0003, X 0xC889,0xC587,0x112C,0x7073,0xE222,0x2648,0x9132,0x108B, X 0xC442,0x0448,0x9522,0x1083,0xE051,0xC448,0x9522,0x1083, X 0xC908,0x2448,0x9522,0x1083,0xE102,0x2448,0x9532,0x108B, X 0xC401,0xC447,0x0A2C,0x1073,0xC010,0x0000,0x0020,0x0003, X 0xD000,0x0000,0x0020,0x0003,0xF620,0x0000,0x0020,0x0003, X 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF END_OF_showpic.icon if test 1933 -ne `wc -c