home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-12-09 | 49.7 KB | 1,903 lines |
- Path: wuarchive!cs.utexas.edu!sun-barr!newstop!exodus!appserv!halibut.cis.upenn.edu
- From: bradley@halibut.cis.upenn.edu (John Bradley)
- Newsgroups: comp.sources.x
- Subject: v10i083: xv - display and manipulate images, Part05/10
- Message-ID: <321@appserv.Eng.Sun.COM>
- Date: 27 Nov 90 20:08:23 GMT
- References: <csx-10i079:xv@uunet.UU.NET>
- Sender: news@exodus.Eng.Sun.COM
- Lines: 1886
- Approved: argv@sun.com
-
- Submitted-by: bradley@halibut.cis.upenn.edu (John Bradley)
- Posting-number: Volume 10, Issue 83
- Archive-name: xv/part05
-
- #!/bin/sh
- # to extract, remove the header and type "sh filename"
- if `test ! -s ./xvinfo.c`
- then
- echo "writting ./xvinfo.c"
- cat > ./xvinfo.c << '\BARFOO\'
- /*
- * xvinfo.c - 'Info' box handling functions
- *
- * callable functions:
- *
- * CreateInfo(geom) - creates the infoW window. Doesn't map it.
- * InfoBox(vis) - random processing based on value of 'vis'
- * maps/unmaps window, etc.
- * RedrawInfo(x,y,w,h) - called by 'expose' events
- * SetInfoMode(mode) - changes amount of info Info window shows
- * SetISTR(st, fmt, args) - sprintf's into ISTR #st. Redraws it in window
- * char *GetISTR(st) - returns pointer to ISTR #st, or NULL if st bogus
- */
-
- /*
- * Copyright 1989, 1990 by the University of Pennsylvania
- *
- * Permission to use, copy, and distribute for non-commercial purposes,
- * is hereby granted without fee, providing that the above copyright
- * notice appear in all copies and that both the copyright notice and this
- * permission notice appear in supporting documentation.
- *
- * The software may be modified for your own purposes, but modified versions
- * may not be distributed.
- *
- * This software is provided "as is" without any express or implied warranty.
- */
-
-
- #define NEEDSVARARGS
-
- #include "xv.h"
- #include "bitmaps.h"
-
- /* max length of an Info String */
- #define ISTRLEN 80
-
- /* baseline of top line of text */
- #define TOPBASE (36 + penn_height/2 + 4 + 8 + ASCENT)
- #define STLEFT 100 /* left edge of strings */
-
- static Pixmap graspPix, pennPix;
- static char istrs[NISTR][ISTRLEN];
-
- #ifdef __STDC__
- static void DrawStrings(void);
- static void DrawFieldName(int);
- static void RedrawString(int);
- #else
- static void DrawStrings(), DrawFieldName(), RedrawString();
- #endif
-
-
-
- /***************************************************/
- void CreateInfo(geom)
- char *geom;
- {
- infoW = CreateWindow("xv info", geom, INFOWIDE, INFOHIGH, infofg, infobg);
- if (!infoW) FatalError("can't create info window!");
-
- pennPix = XCreatePixmapFromBitmapData(theDisp, infoW, penn_bits, penn_width,
- penn_height, infofg, infobg, dispDEEP);
- graspPix = XCreatePixmapFromBitmapData(theDisp,infoW,grasp_bits,grasp_width,
- grasp_height, infofg, infobg, dispDEEP);
- }
-
-
- /***************************************************/
- void InfoBox(vis)
- int vis;
- {
- if (vis) XMapRaised(theDisp, infoW);
- else XUnmapWindow(theDisp, infoW);
-
- infoUp = vis;
- }
-
-
- /***************************************************/
- void RedrawInfo(x,y,w,h)
- int x,y,w,h;
- {
- int i;
-
- XSetForeground(theDisp, theGC, infofg);
- XSetBackground(theDisp, theGC, infobg);
-
- /* draw the two icons */
- XCopyArea(theDisp, pennPix, infoW, theGC, 0, 0, penn_width, penn_height,
- 36 - penn_width/2, 36 - penn_height/2);
- XCopyArea(theDisp, graspPix, infoW, theGC, 0, 0, grasp_width, grasp_height,
- INFOWIDE - 36 - grasp_width/2, 36 - grasp_height/2);
-
- /* draw the credits */
- sprintf(str,"XV - %s",REVDATE);
- CenterString(infoW, str, INFOWIDE/2, 36-LINEHIGH);
- CenterString(infoW, "by John Bradley (bradley@cis.upenn.edu)"
- , INFOWIDE/2, 36);
- CenterString(infoW, "(c) 1990, University of Pennsylvania",
- INFOWIDE/2, 36+LINEHIGH);
-
- /* draw the dividing lines */
- i = 36 + penn_height/2 + 4;
- XDrawLine(theDisp, infoW, theGC, 0, i, INFOWIDE, i);
- XDrawLine(theDisp, infoW, theGC, 0, i+2, INFOWIDE, i+2);
-
- XDrawLine(theDisp, infoW, theGC, 0, INFOHIGH-20, INFOWIDE, INFOHIGH-20);
- XDrawLine(theDisp, infoW, theGC, 0, INFOHIGH-22, INFOWIDE, INFOHIGH-22);
-
- XDrawLine(theDisp, infoW, theGC, 0, INFOHIGH-40, INFOWIDE, INFOHIGH-40);
- XDrawLine(theDisp, infoW, theGC, 0, INFOHIGH-42, INFOWIDE, INFOHIGH-42);
-
- DrawStrings();
- }
-
-
- /***************************************************/
- static void DrawStrings()
- {
- int i;
- for (i=0; i<6; i++) DrawFieldName(i); /* draw the field titles */
- for (i=0; i<NISTR; i++) RedrawString(i); /* draw the field values */
- XFlush(theDisp);
- }
-
-
- /***************************************************/
- static void DrawFieldName(fnum)
- int fnum;
- {
- static char *fname[6] = { "Filename:", "Format:", "Resolution:",
- "Cropping:", "Expansion:", "Colors:" };
-
- XSetForeground(theDisp, theGC, infofg);
- XSetBackground(theDisp, theGC, infobg);
-
- if (infoMode == INF_NONE || infoMode == INF_STR) return;
- if (infoMode == INF_PART && fnum>=3) return;
-
- XDrawString(theDisp, infoW, theGC, 10, TOPBASE + fnum*LINEHIGH,
- fname[fnum], strlen(fname[fnum]));
- }
-
-
- /***************************************************/
- static void RedrawString(st)
- int st;
- {
- /* erase area of string, and draw it with new contents */
-
- XSetForeground(theDisp, theGC, infofg);
- XSetBackground(theDisp, theGC, infobg);
-
- if (infoMode == INF_NONE) return;
- if (infoMode == INF_STR && st > ISTR_WARNING) return;
- if (infoMode == INF_PART && st > ISTR_RES) return;
-
-
- if (st == ISTR_INFO) {
- XClearArea(theDisp, infoW, 0, INFOHIGH-19, INFOWIDE, 17, False);
- CenterString(infoW, istrs[st], INFOWIDE/2, INFOHIGH-10);
- }
- else if (st == ISTR_WARNING) {
- XClearArea(theDisp, infoW, 0, INFOHIGH-39, INFOWIDE, 17, False);
- CenterString(infoW, istrs[st], INFOWIDE/2, INFOHIGH-30);
- }
- else {
- XClearArea(theDisp,infoW,STLEFT,TOPBASE - ASCENT
- + (st-ISTR_FILENAME)*LINEHIGH, INFOWIDE-STLEFT, LINEHIGH,False);
- XDrawString(theDisp, infoW, theGC, STLEFT,TOPBASE
- + (st-ISTR_FILENAME)*LINEHIGH, istrs[st], strlen(istrs[st]));
- }
- }
-
-
-
- /***************************************************/
- void SetInfoMode(mode)
- int mode;
- {
- int y1, y2;
-
- infoMode = mode;
- if (infoUp) { /* only do this if window is mapped */
- y1 = TOPBASE - ASCENT;
- y2 = INFOHIGH-43;
-
- XClearArea(theDisp, infoW, 0, y1, INFOWIDE, y2-y1, False);
- XClearArea(theDisp, infoW, 0, INFOHIGH-39, INFOWIDE, 17, False);
- XClearArea(theDisp, infoW, 0, INFOHIGH-19, INFOWIDE, 17, False);
-
- DrawStrings();
- }
- }
-
-
- /***************************************************/
- /*VARARGS0*/
- void SetISTR(va_alist)
- va_dcl
- {
- va_list args;
- char *fmt;
- int stnum;
-
- /* InfoStr( ISTR, format, arg1, arg2, ...) */
-
- va_start(args);
-
- stnum = va_arg(args, int);
- if (stnum<0 || stnum>=NISTR) return;
-
- fmt = va_arg(args, char *);
- vsprintf(istrs[stnum], fmt, args);
- va_end(args);
-
- if (infoUp) {
- RedrawString(stnum);
- XFlush(theDisp);
- }
-
- if (ctrlUp && stnum == ISTR_INFO) {
- DrawCtrlStr();
- XFlush(theDisp);
- }
- }
-
-
- /***************************************************/
- char *GetISTR(stnum)
- int stnum;
- {
- /* returns pointer to ISTR string */
- if (stnum < 0 || stnum>=NISTR) return(NULL);
- return (istrs[stnum]);
- }
-
-
- \BARFOO\
- else
- echo "will not over write ./xvinfo.c"
- fi
- if `test ! -s ./xvmisc.c`
- then
- echo "writting ./xvmisc.c"
- cat > ./xvmisc.c << '\BARFOO\'
- /*
- * xvmisc.c - random routines that most of the work involved in putting
- * a picture on an X display.
- *
- * Resize(w,h) - generates epic, new Ximage,
- * SortColormap() - sorts the desired colormap into a 'most important color
- * to allocate first' order
- * AllocColors() - Takes the desired colormap and sees what it can do about
- * getting it.
- * DoCrop() - crops the picture
- * UnCrop() - uncrops the picture (natch)
- * Rotate() - rotates 'pic' 90-degrees clockwise
- * FloydDitherize8 - Takes epic, and produces a b/w dithered version of it,
- * stored in 8-bit per pixel format
- * FloydDitherize1 - Does the same, but the output is an XYBitmap (1 bit per
- * pixel, packed 8 pixels to a byte.
- * CreateXImage - Given epic, generate an ximage of it. Handles displays
- * of different depths.
- * CenterString - civilized string drawing routine. uses font 'mfinfo'
- * ULineString - draws underlined string. uses font 'mfinfo'
- * StringWidth - civilized XTextWidth width interface, uses font 'mfinfo'
- * FakeButtonPress - when a keyboard equiv is hit, fakes mouse click in button
- * Timer - sleeps for a given # of milliseconds
- */
-
- /*
- * Copyright 1989, 1990 by the University of Pennsylvania
- *
- * Permission to use, copy, and distribute for non-commercial purposes,
- * is hereby granted without fee, providing that the above copyright
- * notice appear in all copies and that both the copyright notice and this
- * permission notice appear in supporting documentation.
- *
- * The software may be modified for your own purposes, but modified versions
- * may not be distributed.
- *
- * This software is provided "as is" without any express or implied warranty.
- */
-
-
- #define NEEDSTIME
- #include "xv.h"
- #include "bitmaps.h"
-
- #ifdef __STDC__
- static void DoCrop1(int, int, int, int);
- static void RotatePic(byte *, unsigned int *, unsigned int *, int);
- static void FloydDitherize8(byte *);
- static void FloydDitherize1(XImage *);
- static void FreeMostResources(void);
- #else
- static void DoCrop1(), RotatePic(), FloydDitherize8(), FloydDitherize1();
- static void FreeMostResources();
- #endif
-
-
- /***************************************************/
- Window CreateWindow(name,geom,w,h,fg,bg)
- char *name, *geom;
- unsigned int w,h;
- unsigned long fg, bg;
- {
- Window win;
- XSetWindowAttributes xswa;
- unsigned int xswamask;
- XWMHints xwmh;
- XSizeHints hints;
- int i,x,y;
-
- /* note that only x,y are gotten from geom spec. w,h are fixed */
- x = y = 1;
- i = XParseGeometry(geom,&x,&y,&w,&h);
-
- if (i&XValue || i&YValue) hints.flags = USPosition;
- else hints.flags = PPosition;
-
- hints.flags |= USSize;
-
- if (i&XValue && i&XNegative) x = dispWIDE - w - abs(x);
- if (i&YValue && i&YNegative) y = dispHIGH - h - abs(y);
-
- hints.x = x; hints.y = y;
- hints.width = w; hints.height = h;
- hints.min_width = w; hints.min_height = h;
- hints.max_width = w; hints.max_height = h;
- hints.flags |= PMaxSize | PMinSize;
-
- xswa.background_pixel = bg;
- xswa.border_pixel = fg;
- xswamask = CWBackPixel | CWBorderPixel;
-
- win = XCreateWindow(theDisp, rootW, x, y, w, h,
- bwidth, CopyFromParent, CopyFromParent,
- CopyFromParent, xswamask, &xswa);
- if (!win) return(win); /* leave immediately if couldn't create */
-
- XSetStandardProperties(theDisp, win, name, name, None, NULL, 0, &hints);
-
- xwmh.input = True;
- xwmh.flags = InputHint;
- if (iconPix) { xwmh.icon_pixmap = iconPix; xwmh.flags |= IconPixmapHint; }
- XSetWMHints(theDisp, win, &xwmh);
-
- return(win);
- }
-
-
-
- /***********************************/
- void Resize(w,h)
- int w,h;
- {
- int cy,ex,ey,*cxarr, *cxarrp;
- byte *clptr,*elptr,*epptr;
- static char *rstr = "Resizing Image. Please wait...";
-
- clptr = NULL; cxarrp = NULL; cy = 0; /* shut up compiler */
- /* force w,h into valid ranges */
- RANGE(w,1,dispWIDE); RANGE(h,1,dispHIGH);
-
- SetISTR(ISTR_EXPAND, "%.3g x %.3g (%d x %d)",
- ((float) w) / cWIDE, ((float) h) / cHIGH, w, h);
-
- /* if same size, and Ximage created, do nothing */
- if (w==eWIDE && h==eHIGH && theImage!=NULL) return;
-
- if (DEBUG) fprintf(stderr,"%s: Resize(%d,%d) eSIZE=%d,%d cSIZE=%d,%d\n",
- cmd,w,h,eWIDE,eHIGH,cWIDE,cHIGH);
-
- BTSetActive(&but[BCROP],0);
- SetCropString();
-
- if (w==cWIDE && h==cHIGH) { /* 1:1 expansion. point epic at cpic */
- if (epic != cpic && epic!=NULL) free(epic);
- epic = cpic; eWIDE = cWIDE; eHIGH = cHIGH;
- }
-
- else { /* have to actually SCALE THE PIC. Drats! */
- StartFish();
- WaitCursor();
-
- /* if it's a big image, this could take a while. mention it */
- if (w*h>(500*500) && !useroot) {
- XSetForeground(theDisp, theGC, fg);
- XSetBackground(theDisp, theGC, bg);
- XClearWindow(theDisp,mainW);
- XFlush(theDisp);
- XDrawImageString(theDisp,mainW,theGC,CENTERX(mfinfo,w/2,rstr),
- CENTERY(mfinfo,h/2),rstr, strlen(rstr));
- XFlush(theDisp);
- }
-
- /* first, kill the old epic, if one exists */
- if (epic!=NULL && epic!=cpic) {
- free(epic); epic = NULL;
- }
-
- /* create a new epic of the appropriate size */
- eWIDE = w; eHIGH = h;
- epic = (byte *) malloc(w*h);
- if (epic==NULL) {
- sprintf(str,"unable to malloc a %dx%d image\n",w,h);
- FatalError(str);
- }
-
- /* the scaling routine. not really all that scary after all... */
-
- /* OPTIMIZATON IDEA. Malloc an eWIDE array of ints which will hold the
- values of the equation px = (pWIDE * ex) / eWIDE. Faster than doing
- a mul and a div for every point in picture */
-
- cxarr = (int *) malloc(eWIDE * sizeof(int));
- if (!cxarr) FatalError("unable to allocate cxarr");
- for (ex=0; ex<eWIDE; ex++) cxarr[ex] = (cWIDE * ex) / eWIDE;
-
- elptr = epptr = epic;
- for (ey=0; ey<eHIGH; ey++, elptr+=eWIDE) {
- if ((ey&127) == 0) WaitCursor();
- cy = (cHIGH * ey) / eHIGH;
- epptr = elptr;
- clptr = cpic + (cy * cWIDE);
- for (ex=0, cxarrp = cxarr; ex<eWIDE; ex++, epptr++)
- *epptr = clptr[*cxarrp++];
- }
- free(cxarr);
- }
-
- /* now make something displayable out of epic */
- CreateXImage();
- StopFish();
- }
-
-
-
-
- /************************************************/
- /* structure and routine used in SortColormap() */
- /************************************************/
-
- typedef struct thing
- { byte r,g,b;
- int oldindex;
- int use; } CMAPENT;
-
-
- static int CMAPcompare(a,b)
- CMAPENT *a,*b;
- {
- return (b->use - a->use);
- }
-
-
- /***********************************/
- void SortColormap()
- {
- byte *p;
- int i, j, k, mdist, entry, mn, d, hist[256], trans[256];
- static CMAPENT c[256], c1[256], *cp, *cj, *ck;
-
-
- /* no point doing this if we're on a 1-bit display */
- if (ncols == 0) { numcols = 256; return; }
-
- /* initialize histogram and compute it */
- for (i=0; i<256; i++) hist[i]=0;
- for (i=pWIDE*pHIGH, p=pic; i; i--, p++) hist[*p]++;
-
- if (DEBUG>1) {
- fprintf(stderr,"%s: Desired colormap\n",cmd);
- for (i=0; i<256; i++)
- if (hist[i]) fprintf(stderr,"(%3d %02x,%02x,%02x) ",
- i,r[i],g[i],b[i]);
- fprintf(stderr,"\n\n");
- }
-
-
- /* put the actually-used colors into the 'c' array in the order they occur */
- /* also, while we're at it, calculate numcols */
- for (i=numcols=0; i<256; i++) {
- if (hist[i]) {
- cp = &c[numcols++];
- cp->r = r[i]; cp->g = g[i]; cp->b = b[i];
- cp->use = hist[i]; cp->oldindex = i;
- }
- }
-
-
- /* find most-used color, put that in c1[0] */
- entry = -1; mdist = -1;
- for (i=0; i<numcols; i++) {
- if (c[i].use > mdist) { mdist = c[i].use; entry=i; }
- }
- memcpy(&c1[0], &c[entry], sizeof(CMAPENT));
- c[entry].use = 0; /* and mark it dealt with */
-
-
- /* sort rest of colormap, in order of decreasing 'distance' from already
- allocated elements.
-
- FURTHER MODIFICATION of algorithm. The algorithm's performance
- utterly goes to hell as numcols increases. (Probably on the order
- of O^3 performance). Since I don't see a clever way of rewriting
- the algorithm for O^2 performance (which'd be acceptable), I'm going
- to make a trade-off. I'll only run the algorithm for the first 32 colors
- (or so). It can do that Real Fast. Then I'll just stick the rest of
- the unsorted colors (if any), and tack them on the end, in order of
- amount of use. This should give similar picture quality, with
- much higher performance. */
-
- for (i=1; i<numcols && i<32; i++) {
- /* find the i'th most different color */
- entry = -1; mdist = -1;
- for (j=0, cj=c; j<numcols; j++,cj++) {
- if (cj->use) { /* this color has not been marked already */
- mn = 10000;
- for (k=0, ck=c1; k<i; k++,ck++) {
- d = abs(cj->r - ck->r) + abs(cj->g - ck->g) + abs(cj->b - ck->b);
- if (mn>d) mn=d;
- }
- /* mn = minimum distance from c[j] to already used colors */
- /* we want to select the unused color that has the greatest mn */
- if (mn > mdist) { mdist = mn; entry = j; }
- }
- }
-
- /* c[entry] is the next color to put in the map. do so */
- memcpy(&c1[i], &c[entry], sizeof(CMAPENT));
- c[entry].use = 0;
- }
-
- /* tack rest of colors onto colormap in decreasing order of use */
- qsort((char *) c,numcols,sizeof(CMAPENT),CMAPcompare);
- memcpy(&c1[i], c, (numcols - i) * sizeof(CMAPENT));
-
-
- /* build translation table */
- for (i=0; i<numcols; i++) trans[ c1[i].oldindex ] = i;
-
- /* modify 'pic' to reflect the new colormap */
- for (i=pWIDE*pHIGH, p=pic; i; i--, p++) *p = trans[*p];
-
- /* and copy the new colormap into *the* colormap */
- for (i=0; i<numcols; i++) {
- r[i] = c1[i].r; g[i] = c1[i].g; b[i] = c1[i].b;
- }
-
- if (DEBUG>1) {
- fprintf(stderr,"%s: result of sorting colormap\n",cmd);
- for (i=0; i<numcols; i++)
- fprintf(stderr,"(%3d %02x,%02x,%02x) ",i,r[i],g[i],b[i]);
- fprintf(stderr,"\n\n");
-
- fprintf(stderr,"%s: translate table\n",cmd);
- for (i=0; i<numcols; i++)
- fprintf(stderr,"%3d->%3d ",i,trans[i]);
- fprintf(stderr,"\n\n");
- }
-
- }
-
-
-
- #define NOPIX 0xffffffff
-
- /***********************************/
- void AllocColors()
- {
- int i, j, unique, p2alloc, p3alloc;
- Colormap cmap;
- XColor defs[256];
- XColor ctab[256];
- int dc;
-
-
- nfcols = unique = p2alloc = p3alloc = 0;
- rwthistime = 0;
-
-
- if (ncols == 0) {
- SetISTR(ISTR_COLOR,"no colors allocated. Using black & white.");
- SetISTR(ISTR_COLOR2,"");
- return;
- }
-
-
- /* FIRST PASS COLOR ALLOCATION:
- for each color in the 'desired colormap', try to get it via
- XAllocColor(). If for any reason it fails, mark that pixel
- 'unallocated' and worry about it later. Repeat. */
-
- /* attempt to allocate first ncols entries in colormap
- note: On displays with less than 8 bits per RGB gun, it's quite
- possible that different colors in the original picture will be
- mapped to the same color on the screen. X does this for you
- silently. However, this is not-desirable for this application,
- because when I say 'allocate me 32 colors' I want it to allocate
- 32 different colors, not 32 instances of the same 4 shades... */
-
- for (i=0; i<numcols; i++) cols[i] = NOPIX;
-
- cmap = theCmap;
- for (i=0; i<numcols && unique<ncols; i++) {
- defs[i].red = r[i]<<8;
- defs[i].green = g[i]<<8;
- defs[i].blue = b[i]<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
-
- if (XAllocColor(theDisp, cmap, &defs[i])) {
- unsigned long pixel, *fcptr;
-
- pixel = cols[i] = defs[i].pixel;
-
- /* see if the newly allocated color is new and different */
- for (j=0, fcptr=freecols; j<nfcols && *fcptr!=pixel; j++,fcptr++);
- if (j==nfcols) unique++;
-
- fc2pcol[nfcols] = i;
- freecols[nfcols++] = pixel;
- }
-
- else {
- /* the allocation failed. If we want 'perfect' color, and we haven't
- already created our own colormap, we'll want to do so */
- if (perfect && !LocalCmap) {
- LocalCmap = XCopyColormapAndFree(theDisp,theCmap);
- XSetWindowColormap(theDisp,mainW, LocalCmap);
- cmap = LocalCmap;
- i--; /* redo the allocation request */
- }
-
- else
- /* either we don't care about perfect color, or we do care, have
- allocated our own colormap, and have STILL run out of colors
- (possible, even on an 8 bit display), just mark pixel as
- unallocated. We'll deal with it later */
- cols[i] = NOPIX;
- }
- } /* FIRST PASS */
-
-
-
- if (nfcols==numcols) {
- if (numcols != unique)
- SetISTR(ISTR_COLOR,"Got all %d desired colors. (%d unique)", numcols,
- unique);
- else
- SetISTR(ISTR_COLOR,"Got all %d desired colors.", numcols);
-
- SetISTR(ISTR_COLOR2,"");
- return;
- }
-
-
-
- /* SECOND PASS COLOR ALLOCATION:
- Allocating 'exact' colors failed. Now try to allocate 'closest'
- colors.
-
- Read entire X colormap (or first 256 entries) in from display.
- for each unallocated pixel, find the closest color that actually
- is in the X colormap. Try to allocate that color (read only).
- If that fails, the THIRD PASS will deal with it */
-
- SetISTR(ISTR_COLOR,"Got %d out of %d colors. (%d unique)",
- nfcols,numcols,unique);
-
-
- /* read entire colormap (or first 256 entries) into 'ctab' */
- dc = (ncells<256) ? ncells : 256;
- for (i=0; i<dc; i++) ctab[i].pixel = (unsigned long) i;
-
- XQueryColors(theDisp, cmap, ctab, dc);
-
- for (i=0; i<numcols && unique<ncols; i++)
- if (cols[i]==NOPIX) { /* an unallocated pixel */
- int d, mdist, close;
- unsigned long ri,gi,bi;
-
- mdist = 100000; close = -1;
- ri = r[i]; gi = g[i]; bi = b[i];
-
- for (j=0; j<dc; j++) {
- d = abs(ri - (ctab[j].red>>8)) +
- abs(gi - (ctab[j].green>>8)) +
- abs(bi - (ctab[j].blue>>8));
- if (d<mdist) { mdist=d; close=j; }
- }
-
- if (close<0) FatalError("This Can't Happen! (How reassuring.)");
- if (XAllocColor(theDisp, cmap, &ctab[close])) {
- memcpy(&defs[i], &ctab[close], sizeof(XColor));
- cols[i] = ctab[close].pixel;
- fc2pcol[nfcols] = i;
- freecols[nfcols++] = cols[i];
- p2alloc++;
- unique++;
- }
- }
-
-
-
- /* THIRD PASS COLOR ALLOCATION:
- We've alloc'ed all the colors we can. Now, we have to map any
- remaining unalloced pixels into either A) the colors that we DID get
- (noglob), or B) the colors found in the X colormap */
-
- for (i=0; i<numcols; i++) {
- if (cols[i] == NOPIX) { /* an unallocated pixel */
- int d, k, mdist, close;
- unsigned long ri,gi,bi;
-
- mdist = 100000; close = -1;
- ri = r[i]; gi = g[i]; bi = b[i];
-
- if (!noglob) { /* search the entire X colormap */
- for (j=0; j<dc; j++) {
- d = abs(ri - (ctab[j].red>>8)) +
- abs(gi - (ctab[j].green>>8)) +
- abs(bi - (ctab[j].blue>>8));
- if (d<mdist) { mdist=d; close=j; }
- }
- if (close<0) FatalError("This Can't Happen! (How reassuring.)");
- memcpy(&defs[i], &ctab[close], sizeof(XColor));
- cols[i] = defs[i].pixel;
- p3alloc++;
- }
-
- else { /* only search the alloc'd colors */
- for (j=0; j<nfcols; j++) {
- k = fc2pcol[j];
- d = abs(ri - (defs[k].red>>8)) +
- abs(gi - (defs[k].green>>8)) +
- abs(bi - (defs[k].blue>>8));
- if (d<mdist) { mdist=d; close=k; }
- }
- if (close<0) FatalError("This Can't Happen! (How reassuring.)");
- memcpy(&defs[i], &defs[close], sizeof(XColor));
- cols[i] = defs[i].pixel;
- }
- }
- } /* THIRD PASS */
-
-
- if (p2alloc && p3alloc)
- SetISTR(ISTR_COLOR2,"Got %d 'close' color%s. 'Borrowed' %d color%s.",
- p2alloc, (p2alloc>1) ? "s" : "",
- p3alloc, (p3alloc>1) ? "s" : "");
-
- else if (p2alloc && !p3alloc)
- SetISTR(ISTR_COLOR2,"Got %d 'close' color%s.",
- p2alloc, (p2alloc>1) ? "s" : "");
-
- else if (!p2alloc && p3alloc)
- SetISTR(ISTR_COLOR2,"'Borrowed' %d color%s.",
- p3alloc, (p3alloc>1) ? "s" : "");
- }
-
-
-
- /***********************************/
- void AllocRWColors()
- {
- int i,j;
- Colormap cmap;
- XColor defs[256];
-
- nfcols = 0; rwthistime = 1;
-
- if (ncols == 0) {
- SetISTR(ISTR_COLOR,"no colors allocated. Using black & white.");
- SetISTR(ISTR_COLOR2,"");
- rwthistime = 0;
- return;
- }
-
-
- cmap = theCmap;
-
- for (i=0; i<numcols; i++) cols[i] = NOPIX;
-
- for (i=0; i<numcols && i<ncols; i++) {
- unsigned long pmr[1], pix[1];
- if (XAllocColorCells(theDisp, cmap, False, pmr, 0, pix, 1)) {
- defs[i].pixel = cols[i] = pix[0];
- defs[i].red = r[i]<<8;
- defs[i].green = g[i]<<8;
- defs[i].blue = b[i]<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
-
- fc2pcol[nfcols] = i;
- freecols[nfcols++] = pix[0];
- }
-
- else {
- if (perfect && !LocalCmap) {
- LocalCmap = XCopyColormapAndFree(theDisp,theCmap);
- XSetWindowColormap(theDisp,mainW, LocalCmap);
- cmap = LocalCmap;
- i--; /* redo the allocation request */
- }
-
- else cols[i] = NOPIX;
- }
- } /* for (i=0; ... */
-
-
-
- if (nfcols==numcols) {
- SetISTR(ISTR_COLOR,"Got all %d desired colors.", numcols);
- SetISTR(ISTR_COLOR2,"");
- }
-
- else {
- /* Failed to allocate all colors in picture. Map remaining desired
- colors into closest allocated desired colors */
-
- if (nfcols==0) {
- SetISTR(ISTR_COLOR,"No r/w cells available. Using r/o color.");
- AllocColors();
- return;
- }
-
- SetISTR(ISTR_COLOR,"Got %d out of %d colors.", nfcols,numcols);
-
- for (i=0; i<numcols; i++)
- if (cols[i]==NOPIX) { /* an unallocated pixel */
- int k, d, mdist, close;
- unsigned long ri,gi,bi;
-
- mdist = 100000; close = -1;
- ri = r[i]; gi = g[i]; bi = b[i];
-
- for (j=0; j<nfcols; j++) {
- k = fc2pcol[j];
- d = abs(ri - (defs[k].red>>8)) + abs(gi - (defs[k].green>>8)) +
- abs(bi - (defs[k].blue>>8));
- if (d<mdist) { mdist=d; close=k; }
- }
-
- if (close<0) FatalError("This Can't Happen! (How reassuring.)");
- cols[i] = defs[close].pixel;
- }
- }
-
- /* load up the allocated colorcells */
- for (i=0; i<nfcols; i++) {
- j = fc2pcol[i];
- defs[i].pixel = freecols[i];
- defs[i].red = r[j]<<8;
- defs[i].green = g[j]<<8;
- defs[i].blue = b[j]<<8;
- defs[i].flags = DoRed | DoGreen | DoBlue;
- /* fprintf(stderr,"StoreColors: %3d = %3d,%3d,%3d\n",
- defs[i].pixel,r[j],g[j],b[j]); */
- }
- XStoreColors(theDisp, cmap, defs, nfcols);
- XStoreColor(theDisp, cmap, &defs[0]); /* bug in XStoreColors call */
- }
-
-
-
- /***********************************/
- void DoMonoAndRV()
- {
- int i;
-
- /* operate on original colors, before any gamma correction */
- for (i=0; i<numcols; i++) {
- r[i] = rorg[i]; g[i] = gorg[i]; b[i] = borg[i];
- }
-
- if (mono || ncols==0) /* if monochrome, mono-ify the desired colormap */
- for (i=0; i<numcols; i++)
- r[i] = g[i] = b[i] = MONO(r[i],g[i],b[i]);
-
- if (revvideo) /* reverse the desired colormaps */
- for (i=0; i<numcols; i++) {
- r[i] = 255-r[i]; g[i] = 255-g[i]; b[i] = 255-b[i];
- }
- }
-
-
- /***********************************/
- void DoCrop()
- {
- int i, x, y, x2, y2, w, h;
-
- if (!but[BCROP].active) return;
-
- /* turn off the cropping rectangle */
- InvCropRect(); BTSetActive(&but[BCROP],0);
-
- /* sort crx1,crx2,cry1,cry2 so that crx1,cry1 are top left corner */
- if (crx1>crx2) { i = crx1; crx1 = crx2; crx2 = i; }
- if (cry1>cry2) { i = cry1; cry1 = cry2; cry2 = i; }
-
- /* see if cropping to same size, in which case do nothing */
- if (crx2-crx1 == eWIDE && cry2-cry1 == eHIGH) return;
-
- /* figure out what the crop rectangles coordinates are in pic coordinates */
- x = cXOFF + (crx1 * cWIDE) / eWIDE;
- y = cYOFF + (cry1 * cHIGH) / eHIGH;
- x2 = cXOFF + (crx2 * cWIDE) / eWIDE;
- y2 = cYOFF + (cry2 * cHIGH) / eHIGH;
- w = (x2 - x) + 1;
- h = (y2 - y) + 1;
-
- if (w<1) w = 1;
- if (x+w > pWIDE) w = pWIDE - x;
- if (h<1) h = 1;
- if (y+h > pHIGH) h = pHIGH - y;
-
- DoCrop1(x,y,w,h);
- }
-
-
- static void DoCrop1(x,y,w,h)
- int x,y,w,h;
- {
- int i,j;
- byte *cp, *pp;
- double expw, exph;
-
- /* dispose of old cpic and epic */
- if (epic && epic != cpic) free(epic);
- if (cpic && cpic != pic) free(cpic);
- epic = cpic = NULL;
-
- expw = (double) eWIDE / (double) cWIDE;
- exph = (double) eHIGH / (double) cHIGH;
-
- crx1 = (int) ((x - cXOFF) * expw);
- cry1 = (int) ((y - cYOFF) * exph);
-
- cXOFF = x; cYOFF = y; cWIDE = w; cHIGH = h;
- if (DEBUG) fprintf(stderr,"%s: cropping to %dx%d rectangle at %d,%d\n",
- cmd, cWIDE, cHIGH, cXOFF, cYOFF);
-
- /* kill old Ximage so that Resize will be forced to generate a new one */
- if (theImage != NULL) XDestroyImage(theImage);
- theImage = NULL;
-
- /* at this point, we want to generate cpic, which will contain a
- cWIDE*cHIGH subsection of 'pic', top-left at cXOFF,cYOFF */
-
- cpic = (byte *) malloc(cWIDE * cHIGH);
- if (cpic == NULL) {
- fprintf(stderr,"%s: unable to allocate memory for cropped image\n", cmd);
- WUnCrop();
- cpic = pic; cXOFF = cYOFF = 0; cWIDE = pWIDE; cHIGH = pHIGH;
- SetCropString();
- return;
- }
-
- /* copy relevant pixels from pic to cpic */
- cp = cpic;
- for (i=0; i<cHIGH; i++) {
- pp = pic + (i+cYOFF) * pWIDE + cXOFF;
- for (j=0; j<cWIDE; j++)
- *cp++ = *pp++;
- }
-
- SetCropString();
- BTSetActive(&but[BUNCROP],1);
-
- /* shrink window */
-
- WCrop((int) (cWIDE * expw), (int) (cHIGH * exph));
- }
-
-
-
- /***********************************/
- void UnCrop()
- {
- int w,h;
-
- if (cpic == pic) return; /* not cropped */
-
- BTSetActive(&but[BUNCROP],0);
-
- /* dispose of old cpic and epic */
- if (epic && epic != cpic) free(epic);
- if (cpic && cpic != pic) free(cpic);
- epic = cpic = NULL;
-
- /* kill old Ximage so that Resize will be forced to generate a new one */
- if (theImage != NULL) XDestroyImage(theImage);
- theImage = NULL;
-
- w = (pWIDE * eWIDE) / cWIDE;
- h = (pHIGH * eHIGH) / cHIGH;
- RANGE(w,1,dispWIDE); RANGE(h,1,dispHIGH);
-
- WUnCrop();
- cpic = pic; cXOFF = cYOFF = 0; cWIDE = pWIDE; cHIGH = pHIGH;
- SetCropString();
- }
-
-
- /***********************************/
- void AutoCrop()
- {
- byte *cp, *cp1;
- int i, ctop, cbot, cleft, cright;
- byte bgcol;
-
- ctop = cbot = cleft = cright = 0;
-
- /* crop the top */
- cp = cpic;
- bgcol = cp[0];
-
- while (ctop+1 < cHIGH) {
- /* see if we can delete this line */
- for (i=0, cp1=cp; i<cWIDE && *cp1==bgcol; i++, cp1++);
- if (i==cWIDE) { cp += cWIDE; ctop++; }
- else break;
- }
-
-
- /* crop the bottom */
- cp = cpic + (cHIGH-1) * cWIDE;
- bgcol = cp[0];
-
- while (ctop + cbot + 1 < cHIGH) {
- /* see if we can delete this line */
- for (i=0, cp1=cp; i<cWIDE && *cp1==bgcol; i++,cp1++);
- if (i==cWIDE) { cp -= cWIDE; cbot++; }
- else break;
- }
-
-
- /* crop the left side */
- cp = cpic;
- bgcol = cp[0];
-
- while (cleft + 1 < cWIDE) {
- /* see if we can delete this line */
- for (i=0, cp1=cp; i<cHIGH && *cp1==bgcol; i++, cp1 += cWIDE);
- if (i==cHIGH) { cp++; cleft++; }
- else break;
- }
-
-
- /* crop the right side */
- cp = cpic + cWIDE-1;
- bgcol = cp[0];
-
- while (cleft + cright + 1 < cWIDE) {
- /* see if we can delete this line */
- for (i=0, cp1=cp; i<cHIGH && *cp1==bgcol; i++, cp1 += cWIDE);
- if (i==cHIGH) { cp--; cright++; }
- else break;
- }
-
-
- /* do the actual cropping */
- if (cleft || ctop || cbot || cright)
- DoCrop1(cXOFF+cleft, cYOFF+ctop, cWIDE-(cleft+cright), cHIGH-(ctop+cbot));
- }
-
-
- /***********************************/
- void Rotate(dir)
- int dir;
- {
- int i;
-
- /* dir=0: clockwise, else counter-clockwise */
-
- RotatePic(pic, &pWIDE, &pHIGH, dir);
-
- /* rotate clipped version and modify 'clip' coords */
- if (cpic != pic && cpic != NULL) {
- if (!dir) {
- i = pWIDE - (cYOFF + cHIGH); /* have to rotate offsets */
- cYOFF = cXOFF;
- cXOFF = i;
- }
- else {
- i = pHIGH - (cXOFF + cWIDE);
- cXOFF = cYOFF;
- cYOFF = i;
- }
- RotatePic(cpic, &cWIDE, &cHIGH,dir);
- }
- else { cWIDE = pWIDE; cHIGH = pHIGH; }
-
- /* rotate expanded version */
- if (epic != cpic && epic != NULL) {
- RotatePic(epic, &eWIDE, &eHIGH,dir);
- }
- else { eWIDE = cWIDE; eHIGH = cHIGH; }
-
- CreateXImage();
- WRotate();
- }
-
-
- /************************/
- static void RotatePic(pic, wp, hp, dir)
- byte *pic;
- unsigned int *wp, *hp;
- int dir;
- {
- /* rotates a w*h array of bytes 90 deg clockwise (dir=0)
- or counter-clockwise (dir != 0). swaps w and h */
-
- byte *pic1, *pix1, *pix;
- int i,j;
- unsigned int w,h;
-
- w = *wp; h = *hp;
- pix1 = pic1 = (byte *) malloc(w*h);
- if (!pic1) FatalError("Not enough memory to rotate!");
-
- /* do the rotation */
- if (dir==0) {
- for (i=0; i<w; i++) /* CW */
- for (j=h-1, pix=pic+(h-1)*w + i; j>=0; j--, pix1++, pix-=w)
- *pix1 = *pix;
- }
- else {
- for (i=w-1; i>=0; i--) /* CCW */
- for (j=0, pix=pic+i; j<h; j++, pix1++, pix+=w)
- *pix1 = *pix;
- }
-
-
- /* copy the rotated buffer into the original buffer */
- memcpy(pic, pic1, w*h);
-
- free(pic1);
-
- /* swap w and h */
- *wp = h; *hp = w;
- }
-
-
-
- /************************/
- static void FloydDitherize8(image)
- byte *image;
- {
- /* takes epic, and builds a black&white dithered version of it.
- stores result in 8bit Pixmap format in 'image' */
-
- int i;
- byte *p;
-
- FSDither(epic, eWIDE, eHIGH, image);
-
- /* set to 'black' and 'white' instead of '0' and '1' */
- if (black != 0 || white != 1) {
- for (i=eWIDE*eHIGH, p=image; i>0; i--, p++) {
- if (*p) *p = white; else *p = black;
- }
- }
- }
-
-
-
- /************************/
- static void FloydDitherize1(ximage)
- XImage *ximage;
- {
- /* same as FloydDitherize8, but output is a 1-bit per pixel XYBitmap,
- packed 8 pixels per byte */
-
- register short *dp;
- register byte pix8, bit;
- short *dithpic;
- int i, j, err, bperln, order;
- byte *pp, *image, w, b, w8, b8;
-
-
- image = (byte *) theImage->data;
- bperln = theImage->bytes_per_line;
- order = theImage->bitmap_bit_order;
-
- if (DEBUG) fprintf(stderr,"Ditherizing1...");
-
- dithpic = (short *) malloc(eWIDE * eHIGH * sizeof(short));
- if (dithpic == NULL) FatalError("not enough memory to ditherize");
-
- w = white&0x1; b=black&0x1;
- w8 = w<<7; b8 = b<<7; /* b/w bit in high bit */
-
- /* copy r[epic] into dithpic so that we can run the algorithm */
- pp = epic; dp = dithpic;
- for (i=eHIGH * eWIDE; i>0; i--) *dp++ = fsgamcr[r[*pp++]];
-
- dp = dithpic;
- pp = image;
-
- for (i=0; i<eHIGH; i++) {
- pp = image + i*bperln;
-
- if (order==LSBFirst) {
- bit = pix8 = 0;
- for (j=0; j<eWIDE; j++,dp++) {
- if (*dp<128) { err = *dp; pix8 |= b8; }
- else { err = *dp-255; pix8 |= w8; }
-
- if (bit==7) {
- *pp++ = pix8; bit=pix8=0;
- }
- else { pix8 >>= 1; bit++; }
-
- if (j<eWIDE-1) dp[1] += ((err*7)/16);
-
- if (i<eHIGH-1) {
- dp[eWIDE] += ((err*5)/16);
- if (j>0) dp[eWIDE-1] += ((err*3)/16);
- if (j<eWIDE-1) dp[eWIDE+1] += (err/16);
- }
- }
- if (bit) *pp++ = pix8>>(7-bit); /* write partial byte at end of line */
- }
-
- else { /* order==MSBFirst */
- bit = pix8 = 0;
- for (j=0; j<eWIDE; j++,dp++) {
- if (*dp<128) { err = *dp; pix8 |= b; }
- else { err = *dp-255; pix8 |= w; }
-
- if (bit==7) {
- *pp++ = pix8; bit=pix8=0;
- }
- else { pix8 <<= 1; bit++; }
-
- if (j<eWIDE-1) dp[1] += ((err*7)/16);
-
- if (i<eHIGH-1) {
- dp[eWIDE] += ((err*5)/16);
- if (j>0) dp[eWIDE-1] += ((err*3)/16);
- if (j<eWIDE-1) dp[eWIDE+1] += (err/16);
- }
- }
- if (bit) *pp++ = pix8<<(7-bit); /* write partial byte at end of line */
- }
- }
-
- if (DEBUG) fprintf(stderr,"done\n");
-
- free(dithpic);
- }
-
-
-
- /************************/
- void FSDither(inpic, w, h, outpic)
- byte *inpic, *outpic;
- int w,h;
- {
- /* takes inpic, and builds a black&white dithered version of it.
- stores result as 1 byte per pixel format in 'image'
- black = 0; white = 1;
- temporarily mallocs a w*h array of SHORTS.
- (need to be signed, also to avoid overflow problems.) */
-
- /* floyd-steinberg dithering.
- *
- * ---- x 7/16
- * 3/16 5/16 1/16
- *
- */
-
- short *dp, *dithpic;
- int i, j, err, w1, h1;
- byte *pp, rgb[256];
-
- if (DEBUG) fprintf(stderr,"Ditherizing...");
-
- /* first thing to do is build rgb[], which will hold the B/W intensity
- of the colors in the r,g,b arrays */
- for (i=0; i<256; i++)
- rgb[i] = MONO(r[i], g[i], b[i]);
-
-
- dithpic = (short *) malloc(w*h * sizeof(short));
- if (dithpic == NULL) FatalError("not enough memory to ditherize");
-
- w1 = w-1; h1 = h-1;
-
- /* copy rgb[inpic] into dithpic so that we can run the algorithm */
- pp = inpic; dp = dithpic;
- for (i=w*h; i>0; i--) *dp++ = fsgamcr[rgb[*pp++]];
-
- dp = dithpic; pp = outpic;
- for (i=0; i<h; i++) {
- if ((i&15) == 0) WaitCursor();
- for (j=0; j<w; j++,dp++,pp++) {
- if (*dp<128) { err = *dp; *pp = 0; }
- else { err = *dp-255; *pp = 1; }
-
- if (j<w1) dp[1] += ((err*7)/16);
-
- if (i<h1) {
- dp[w] += ((err*5)/16);
- if (j>0) dp[w1] += ((err*3)/16);
- if (j<w1) dp[w+1] += (err/16);
- }
- }
- }
-
- if (DEBUG) fprintf(stderr,"done\n");
-
- free(dithpic);
- }
-
-
-
-
-
-
- /***********************************/
- void CreateXImage()
- {
- int i;
-
-
- /*
- * this has to do the tricky bit of converting the data in 'epic'
- * into something usable for X.
- *
- * Algorithm notes:
- * if dispDEEP is 8, nothing has to be done other than create an
- * Ximage (ZPixmap, depth=8) and point it at the 'epic' data.
- *
- * if dispDEEP is 1, format'll be an XYBitmap, special case code
- *
- * if dispDEEP is 4, format'll be a ZPixmap, 4 or 8 bits per pixel
- *
- * if dispDEEP is 6, format'll be a ZPixmap, 8 bits per pixel
- *
- * if dispDEEP is 24 or 32, format'll be a ZPixmap. 32 bits per pixel
- *
- * any other value of dispDEEP will use a XYPixmap of the appropriate
- * depth, and some slug-like general-case code DOESN'T YET!!
- */
-
- if (DEBUG)
- fprintf(stderr,"%s: creating a %dx%d Ximage, %d bits deep\n",
- cmd, eWIDE, eHIGH, dispDEEP);
-
- /* destroy old image and imagedata, if there is one */
- if (theImage) XDestroyImage(theImage);
- theImage = NULL;
-
- if (!epic) {
- /* fprintf(stderr,"CreateXImage called while epic was null\n"); */
- Resize(eWIDE,eHIGH);
- return;
- }
-
- switch (dispDEEP)
- {
-
- case 8:
- {
- byte *imagedata, *ip, *pp;
-
- imagedata = (byte *) malloc(eWIDE*eHIGH);
- if (!imagedata) FatalError("couldn't malloc imagedata");
-
- if (ncols==0) FloydDitherize8(imagedata);
- else {
- for (i=eWIDE*eHIGH, pp=epic, ip=imagedata; i>0; i--,pp++,ip++) {
- if ((i&0x1ffff) == 0) WaitCursor();
- *ip = (byte) cols[*pp];
- }
- }
-
- theImage = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
- (char *) imagedata, eWIDE, eHIGH, 8, 0);
- if (!theImage) FatalError("couldn't create theImage!");
- }
- break;
-
- /*********************************/
-
- case 1:
- {
- byte *imagedata;
-
- theImage = XCreateImage(theDisp, theVisual, dispDEEP, XYPixmap, 0, NULL,
- eWIDE, eHIGH, 8, 0);
- if (!theImage) FatalError("couldn't create theImage!");
- imagedata = (byte *) malloc(theImage->bytes_per_line * eHIGH);
- if (!imagedata) FatalError("couldn't malloc imagedata");
- theImage->data = (char *) imagedata;
- FloydDitherize1(theImage);
- }
- break;
-
- /*********************************/
-
- case 4: {
- byte *imagedata, *ip, *pp;
- byte *lip;
- int bperline, half, j;
-
- theImage = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
- eWIDE, eHIGH, 8, 0);
- if (!theImage) FatalError("couldn't create theImage!");
-
- bperline = theImage->bytes_per_line;
- imagedata = (byte *) malloc(bperline * eHIGH);
- if (!imagedata) FatalError("couldn't malloc imagedata");
- theImage->data = (char *) imagedata;
-
- if (ncols==0) { /* ditherize */
- byte *dith;
- dith = (byte *) malloc(eWIDE * eHIGH);
- if (!dith) FatalError("can't create dithered image");
- FloydDitherize8(dith);
-
- if (theImage->bits_per_pixel == 4) {
- for (i=0, pp=dith, lip=imagedata; i<eHIGH; i++, lip+=bperline)
- for (j=0, ip=lip, half=0; j<eWIDE; j++,pp++,half++) {
- if (half&1) { *ip = *ip + ((*pp&0x0f)<<4); ip++; }
- else *ip = *pp&0x0f;
- }
- }
- else if (theImage->bits_per_pixel == 8)
- memcpy(imagedata, dith, eWIDE*eHIGH);
-
- else FatalError("This display is too bizarre. Can't create XImage.");
-
- free(dith);
- }
-
- else { /* don't ditherize */
- if (theImage->bits_per_pixel == 4) {
- for (i=0, pp=epic, lip=imagedata; i<eHIGH; i++, lip+=bperline) {
- if ((i&127) == 0) WaitCursor();
- for (j=0, ip=lip, half=0; j<eWIDE; j++,pp++,half++) {
- if (half&1) { *ip = *ip + ((cols[*pp]&0x0f)<<4); ip++; }
- else *ip = cols[*pp]&0x0f;
- }
- }
- }
- else if (theImage->bits_per_pixel == 8) {
- for (i=eWIDE*eHIGH, pp=epic, ip=imagedata; i>0; i--,pp++,ip++) {
- if ((i&0x1ffff) == 0) WaitCursor();
- *ip = (byte) cols[*pp];
- }
- }
- else FatalError("This display's too bizarre. Can't create XImage.");
- }
-
- }
- break;
-
- /*********************************/
-
- case 6: {
- byte *imagedata, *ip, *pp;
- int bperline;
-
- theImage = XCreateImage(theDisp, theVisual, dispDEEP, ZPixmap, 0, NULL,
- eWIDE, eHIGH, 8, 0);
- if (!theImage) FatalError("couldn't create theImage!");
-
- if (theImage->bits_per_pixel != 8)
- FatalError("This display's too bizarre. Can't create XImage.");
-
- bperline = theImage->bytes_per_line;
- imagedata = (byte *) malloc(bperline * eHIGH);
- if (!imagedata) FatalError("couldn't malloc imagedata");
- theImage->data = (char *) imagedata;
-
- if (ncols==0) FloydDitherize8(imagedata);
- else {
- for (i=eWIDE*eHIGH, pp=epic, ip=imagedata; i>0; i--,pp++,ip++) {
- if ((i&0x1ffff) == 0) WaitCursor();
- *ip = (byte) cols[*pp];
- }
- }
-
- }
- break;
-
- /*********************************/
-
- case 24:
- case 32:
- {
- byte *imagedata, *ip, *pp;
- imagedata = (byte *) malloc(4*eWIDE*eHIGH);
- if (!imagedata) FatalError("couldn't malloc imagedata");
-
- theImage = XCreateImage(theDisp,theVisual,dispDEEP,ZPixmap,0,
- (char *) imagedata, eWIDE, eHIGH, 32, 0);
- if (!theImage) FatalError("couldn't create theImage!");
-
- if (theImage->byte_order == MSBFirst)
- for (i=eWIDE*eHIGH, pp=epic, ip=imagedata; i>0; i--,pp++) {
- if ((i&0x1ffff) == 0) WaitCursor();
- *ip++ = 0;
- *ip++ = (cols[*pp]>>16) & 0xff;
- *ip++ = (cols[*pp]>>8) & 0xff;
- *ip++ = cols[*pp] & 0xff;
- }
- else
- for (i=eWIDE*eHIGH, pp=epic, ip=imagedata; i>0; i--,pp++) {
- if ((i&0x1ffff) == 0) WaitCursor();
- *ip++ = cols[*pp] & 0xff;
- *ip++ = (cols[*pp]>>8) & 0xff;
- *ip++ = (cols[*pp]>>16) & 0xff;
- *ip++ = 0;
- }
- }
- break;
-
- /*********************************/
-
- default:
- sprintf(str,"no code to handle this display type (%d bits deep)",
- dispDEEP);
- FatalError(str);
- break;
- }
- }
-
-
-
-
- /**************************************************/
- void CenterString(win,str,x,y)
- Window win;
- char *str;
- int x,y;
- {
- XDrawString(theDisp, win, theGC, CENTERX(mfinfo, x, str),
- CENTERY(mfinfo, y), str, strlen(str));
- }
-
-
- /**************************************************/
- void ULineString(win,str,x,y)
- Window win;
- char *str;
- int x,y;
- {
- XDrawString(theDisp, win, theGC, x, y, str, strlen(str));
- XDrawLine(theDisp, win, theGC, x, y+DESCENT-1,
- x+StringWidth(str), y+DESCENT-1);
- }
-
-
- /**************************************************/
- int StringWidth(str)
- char *str;
- {
- return(XTextWidth(mfinfo, str, strlen(str)));
- }
-
-
- /***********************************/
- void FakeButtonPress(bp)
- BUTT *bp;
- {
- /* called when a button keyboard equivalent has been pressed.
- 'fakes' a ButtonPress event in the button, which A) makes the button
- blink, and B) falls through to ButtonPress command dispatch code */
-
- XButtonEvent ev;
-
- ev.type = ButtonPress;
- ev.send_event = True;
- ev.display = theDisp;
- ev.window = bp->win;
- ev.root = rootW;
- ev.subwindow = NULL;
- ev.x = bp->x;
- ev.y = bp->y;
- ev.state = 0;
- ev.button = Button1;
- XSendEvent(theDisp, bp->win, False, NoEventMask, (XEvent *) &ev);
- }
-
- /**************************************************/
- void SetCropString()
- {
- /* sets the crop string in the info box to be correct. should
- be called whenever 'but[BCROP].active', cXOFF,cYOFF,cWIDE,cHIGH
- are changed */
-
- /* if but[BCROP].active, there's a cropping rectangle drawn on the picture.
- the string should reflect that. */
-
- if (but[BCROP].active) {
- /* figure out current cropping rectangle in 'pic' coordinates */
- int x,y,x1,y1,w,h;
- int cx,cy,dx,dy;
-
- if (crx1<crx2) cx=crx1; else cx=crx2;
- if (cry1<cry2) cy=cry1; else cy=cry2;
- dx = abs(crx1-crx2); dy = abs(cry1-cry2);
-
- x = cXOFF + (cx * cWIDE) / eWIDE;
- y = cYOFF + (cy * cHIGH) / eHIGH;
- x1 = cXOFF + ((cx+dx) * cWIDE) / eWIDE;
- y1 = cYOFF + ((cy+dy) * cHIGH) / eHIGH;
- w = (x1 - x) + 1;
- h = (y1 - y) + 1;
-
- if (w<1) w = 1;
- if (x+w > pWIDE) w = pWIDE - x;
- if (h<1) h = 1;
- if (y+h > pHIGH) h = pHIGH - y;
-
- SetISTR(ISTR_CROP, "%dx%d rectangle starting at %d,%d", w, h, x, y);
- }
-
- else { /* cropping rectangle is turned off */
- if (cpic != pic)
- SetISTR(ISTR_CROP, "%dx%d rectangle starting at %d,%d",
- cWIDE, cHIGH, cXOFF, cYOFF);
- else
- SetISTR(ISTR_CROP, "none");
- }
- }
-
-
- /***********************************/
- void Warning()
- {
- char *st;
- int i;
-
- if (infoUp || ctrlUp) { /* give 'em time to read message */
- if (!fishrunning) sleep(5);
- else {
- for (i=0; i<25; i++) PAUSE_SIG;
- }
- }
- else {
- st = GetISTR(ISTR_INFO);
- fprintf(stderr,"%s: %s\n", cmd, st);
- }
- }
-
-
- /***********************************/
- void FatalError (identifier)
- char *identifier;
- {
- fprintf(stderr, "%s: %s\n",cmd, identifier);
- Quit(-1);
- }
-
-
- /***********************************/
- void Quit(i)
- int i;
- {
- FreeMostResources();
- exit(i);
- }
-
-
- /***********************************/
- static void FreeMostResources()
- {
- /* called when the program exits. frees everything explictly created
- EXCEPT allocated colors. This is used when 'useroot' is in operation,
- as we have to keep the alloc'd colors around, but we don't want anything
- else to stay */
-
- if (!theDisp) return; /* called before connection opened */
-
- if (dirW) XDestroyWindow(theDisp, dirW);
- if (infoW) XDestroyWindow(theDisp, infoW);
- if (ctrlW) XDestroyWindow(theDisp, ctrlW);
- if (gamW) XDestroyWindow(theDisp, gamW);
-
- XFlush(theDisp);
- }
-
- static Cursor flcurs, fl1curs, fmcurs, fr1curs, frcurs;
-
- /***********************************/
- void LoadFishCursors()
- {
- #define fc_w 16
- #define fc_h 16
-
- Pixmap flpix,flmpix,fmpix,fmmpix,frpix,frmpix;
- Pixmap fl1pix, fl1mpix, fr1pix, fr1mpix;
- XColor fg, bg;
-
- flcurs = fl1curs = fmcurs = fr1curs = frcurs = NULL;
-
- flpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_left_bits,
- fc_w, fc_h, 1, 0, 1);
- flmpix= XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_leftm_bits,
- fc_w, fc_h, 1, 0, 1);
-
- fl1pix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_left1_bits,
- fc_w, fc_h, 1, 0, 1);
- fl1mpix= XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_left1m_bits,
- fc_w, fc_h, 1, 0, 1);
-
- fmpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_mid_bits,
- fc_w, fc_h, 1, 0, 1);
- fmmpix= XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_midm_bits,
- fc_w, fc_h, 1, 0, 1);
-
- fr1pix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_right1_bits,
- fc_w, fc_h, 1, 0, 1);
- fr1mpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_right1m_bits,
- fc_w, fc_h, 1, 0, 1);
-
- frpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_right_bits,
- fc_w, fc_h, 1, 0, 1);
- frmpix = XCreatePixmapFromBitmapData(theDisp, ctrlW, fc_rightm_bits,
- fc_w, fc_h, 1, 0, 1);
-
- if (!flpix || !flmpix || !fmpix || !fmmpix || !frpix || !frmpix
- || !fl1pix || !fl1mpix || !fr1pix || !fr1mpix) return;
-
- fg.red = fg.green = fg.blue = 0;
- bg.red = bg.green = bg.blue = 0xffff;
-
- flcurs = XCreatePixmapCursor(theDisp, flpix, flmpix, &fg, &bg, 8,8);
- fl1curs= XCreatePixmapCursor(theDisp, fl1pix,fl1mpix,&fg, &bg, 8,8);
- fmcurs = XCreatePixmapCursor(theDisp, fmpix, fmmpix, &fg, &bg, 8,8);
- fr1curs= XCreatePixmapCursor(theDisp, fr1pix,fr1mpix,&fg, &bg, 8,8);
- frcurs = XCreatePixmapCursor(theDisp, frpix, frmpix, &fg, &bg, 8,8);
-
- if (!flcurs || !fmcurs || !frcurs || !fl1curs || !fr1curs)
- { flcurs = fmcurs = frcurs = NULL; }
- }
-
- static int fishno=0;
-
-
- /***********************************/
- void WaitCursor()
- {
- SetCursors(fishno);
- fishno = (fishno+1) % 8;
- }
-
-
- /***********************************/
- void SetCursors(n)
- int n;
- {
- Cursor c;
-
- c = cross;
- /* if n < 0 sets normal cursor in all windows
- n = 0..6 cycles through fish cursors */
-
- if (n<0) {
- if (!useroot && mainW) XDefineCursor(theDisp, mainW, cross);
- XDefineCursor(theDisp, infoW, arrow);
- XDefineCursor(theDisp, ctrlW, arrow);
- XDefineCursor(theDisp, dirW, arrow);
- XDefineCursor(theDisp, gamW, arrow);
- fishno = 0;
- }
-
- else if (flcurs) { /* was able to load the cursors */
- switch (n%8) {
- case 0: c = flcurs; break;
- case 1: c = fl1curs; break;
- case 2: c = fmcurs; break;
- case 3: c = fr1curs; break;
- case 4: c = frcurs; break;
- case 5: c = fr1curs; break;
- case 6: c = fmcurs; break;
- case 7: c = fl1curs; break;
- }
-
- if (!useroot && mainW) XDefineCursor(theDisp, mainW, c);
- XDefineCursor(theDisp, infoW, c);
- XDefineCursor(theDisp, ctrlW, c);
- XDefineCursor(theDisp, dirW, c);
- XDefineCursor(theDisp, gamW, c);
- }
-
- XFlush(theDisp);
- }
-
-
-
-
- /***************************************************/
-
- static int timerdone;
-
- /*******/
- static void onalarm()
- /*******/
- {
- timerdone=1;
- }
-
-
- /*******/
- void Timer(n) /* waits for 'n' milliseconds */
- int n;
- /*******/
- {
- long usec;
- struct itimerval it;
-
- if (!n) return;
- if (fishrunning) { PAUSE_SIG; return; }
-
- #ifdef sco
- if (!n) return;
- nap(n);
- return;
- #endif /* sco */
-
- #ifdef USLEEP
- usleep(n);
- return;
- #endif
-
- #ifdef NOTIMER
- return;
- #endif
-
- usec = (long) n * 1000;
-
- memset(&it, 0, sizeof(it));
- if (usec>=1000000L) { /* more than 1 second */
- it.it_value.tv_sec = usec / 1000000L;
- usec %= 1000000L;
- }
-
- it.it_value.tv_usec = usec;
- timerdone=0;
- signal(SIGALRM,onalarm);
- setitimer(ITIMER_REAL, &it, (struct itimerval *)0);
- while (1) {
- HOLD_SIG; /* note: have to block, so that ALRM */
- if (timerdone) break; /* doesn't occur between 'if (timerdone)' */
- else PAUSE_SIG; /* and calling PAUSE_SIG */
- }
-
- RELEASE_SIG; /* turn ALRM blocking off */
- signal(SIGALRM,SIG_DFL);
- }
-
-
-
-
-
-
- \BARFOO\
- else
- echo "will not over write ./xvmisc.c"
- fi
- echo "Finished archive 5 of 10"
- exit
-
- dan
- ----------------------------------------------------
- O'Reilly && Associates argv@sun.com / argv@ora.com
- Opinions expressed reflect those of the author only.
- --
- dan
- ----------------------------------------------------
- O'Reilly && Associates argv@sun.com / argv@ora.com
- Opinions expressed reflect those of the author only.
-