📄 xgrabsc.c
字号:
/*======================================================================== * * Name - xgrabsc.c * * Version: 1.12 * * ccsid: @(#)xgrabsc.c 1.12 - 7/26/91 15:15:31 * from: ccs/s.xgrabsc.c * date: 7/26/91 15:16:10 * * Copyright (c) 1990 Bruce Schuchardt. * Read the file cpyright.h for full copyright information. * * * Description: * * xgrabsc - grab screen images and store in files * *======================================================================== */#include "cpyright.h"#include "patchlevel.h"#include "ps_color.h"#include <stdio.h>#include <X11/Xos.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/cursorfont.h>#include <X11/Xatom.h>#include <X11/XWDFile.h>#ifndef CARD32#include <X11/Xmd.h>#endif#define MAX_CELLS 256#define TRUE 1#define FALSE 0typedef enum { NO_DITHER=0, FS_DITHER, MATRIX_DITHER, MATRIX_HALFTONE} ditherType;typedef unsigned char byte;typedef unsigned long dw;typedef unsigned int word;typedef struct { XImage *ximage; word numcells; word red[MAX_CELLS], green[MAX_CELLS], blue[MAX_CELLS]; byte used[MAX_CELLS];} imageInfo;#ifdef MEMCPYchar *memcpy();char *memset();#endif#ifdef BCOPY#ifdef MEMCPY#undef MEMCPY#endif#define memcpy(x,y,c) bcopy(y,x,c)#define memset(x,c) bzero(x,c) /* well, I only use it for zeroing out stuff */#endifDisplay *hDisplay;int hScreen;Window hRoot;int displayCells;char *programName;char *imageName;char *version = XGRABSC_VERSION;int patchLevel = XGRABSC_PATCHLEVEL;int verbose;word nr[MAX_CELLS], ng[MAX_CELLS], nb[MAX_CELLS];char hexdigits[] = "0123456789abcdef";/* * Alter colors by setting or clearing bits in rgb values. * This effectively reduces the depth of the image, causing the * number of colors used to be reduced. Equivalent colors are * merged in the image, and the used flags of remapped colors are * cleared. * * The number of eliminated colormap entries is returned. The colormap * is not compressed. */alterPlanes(image, modeIsAnd, bits) imageInfo *image; int modeIsAnd; /* if TRUE, combine mask with AND; if FALSE, use OR */ unsigned int bits;{ int nc, cidx, ridx, h, w; long p; XImage *ximage = image->ximage; long map[MAX_CELLS]; int remapCount; word mask; if (ximage->depth <= 1) return 0; mask = 0xFFFF ^ ((1 << (bits+8)) - 1); if (!modeIsAnd) mask = ~mask & 0xFFFF; if (verbose) { fprintf(stderr, "%s: %s color with mask %x...", programName, modeIsAnd? "ANDing" : "ORing", mask); fflush(stderr); } nc = image->numcells; if (modeIsAnd) for (cidx=0; cidx<nc; cidx++) { nr[cidx] = image->red[cidx] & mask; ng[cidx] = image->green[cidx] & mask; nb[cidx] = image->blue[cidx] & mask; } else for (cidx=0; cidx<nc; cidx++) { nr[cidx] = image->red[cidx] | mask; ng[cidx] = image->green[cidx] | mask; nb[cidx] = image->blue[cidx] | mask; } /* now eliminate redundant colors */ for (cidx=0; cidx<nc; cidx++) map[cidx] = cidx; remapCount = 0; for (cidx=0; cidx<nc; cidx++) if (image->used[cidx]) for (ridx=cidx+1; ridx<nc; ridx++) if (image->used[ridx] && nr[cidx]==nr[ridx] && ng[cidx]==ng[ridx] && nb[cidx]==nb[ridx]) { /* the colors match - remap this pixel to the one we're scanning with */ map[ridx] = cidx; image->used[ridx] = FALSE; remapCount++; } memcpy(image->red, nr, nc*sizeof(word)); memcpy(image->green, ng, nc*sizeof(word)); memcpy(image->blue, nb, nc*sizeof(word)); /* remap redundant pixels in the image */ if (remapCount) for (h=0; h<ximage->height; h++) for (w=0; w<ximage->width; w++) { p = XGetPixel(ximage, w, h); if (p != map[p]) XPutPixel(ximage, w, h, map[p]); } if (verbose) fprintf(stderr, " %d colors remapped\n", remapCount, nc); return remapCount;}/* Brighten or darken colors in the image by the given amount ('percent'). * The amount is an integer that, if less than 100 will darken the image * and if greater than 100 will brighten the image. After modifying * colors equivalent colors are merged (as in alterPlanes). The number * of eliminated colors is returned. */brightenColors(image, percent) imageInfo *image; int percent;{ int nc, cidx, ridx, h, w; long p; XImage *ximage = image->ximage; float adjustment; long map[MAX_CELLS]; int remapCount; dw new; if (ximage->depth <= 1) return 0; if (verbose) { fprintf(stderr, "%s: adjusting intensity by %d...", programName, percent); fflush(stderr); } adjustment = (float)percent / 100.0; nc = image->numcells; for (cidx=0; cidx<nc; cidx++) { new = image->red[cidx] * adjustment; if (new > (dw)0xFFFF) new = (dw)0xFFFF; nr[cidx] = new; new = image->green[cidx] * adjustment; if (new > (dw)0xFFFF) new = (dw)0xFFFF; ng[cidx] = new; new = image->blue[cidx] * adjustment; if (new > (dw)0xFFFF) new = (dw)0xFFFF; nb[cidx] = new; } /* now eliminate redundant colors */ for (cidx=0; cidx<nc; cidx++) map[cidx] = cidx; remapCount = 0; for (cidx=0; cidx<nc; cidx++) if (image->used[cidx]) for (ridx=cidx+1; ridx<nc; ridx++) if (image->used[ridx] && nr[cidx]==nr[ridx] && ng[cidx]==ng[ridx] && nb[cidx]==nb[ridx]) { map[ridx] = cidx; image->used[ridx] = FALSE; remapCount++; } memcpy(image->red, nr, nc*sizeof(word)); memcpy(image->green, ng, nc*sizeof(word)); memcpy(image->blue, nb, nc*sizeof(word)); /* remap redundant pixels in the image */ if (remapCount) for (h=0; h<ximage->height; h++) for (w=0; w<ximage->width; w++) { p = XGetPixel(ximage, w, h); if (p != map[p]) XPutPixel(ximage, w, h, map[p]); } if (verbose) fprintf(stderr, " %d colors remapped\n", remapCount, nc); return remapCount;}/* * Compress the colors used in an XImage so that all pixel values are * adjacent. Alters the rgb color tables and the XImage data values. */compressColormap(image) imageInfo *image;{ XImage *ximage = image->ximage; long map[MAX_CELLS]; int ncolors, w, h, m; long p; if (ximage->depth <= 1 || image->numcells > MAX_CELLS) return; if (verbose) { fprintf(stderr, "%s: compressing colormap...", programName); fflush(stderr); } ncolors = 0; /* map[] is indexed by old pixel values. It delivers new, compressed, * pixel values. */ for (m=0; m<MAX_CELLS; m++) map[m] = MAX_CELLS+1; /* bludgeon through the whole image and remap each pixel value */ for (h=0; h<ximage->height; h++) { for (w=0; w<ximage->width; w++) { /* Get the pixel index and see if it has been used or not. * Then remap the pixel */ p = XGetPixel(ximage, w, h); if (map[p] == MAX_CELLS+1) { map[p] = ncolors; ncolors++; } if (p != map[p]) XPutPixel(ximage, w, h, map[p]); } } /* now compress the color table */ memset(image->used, 0, MAX_CELLS); for (m=0; m<MAX_CELLS; m++) { if (map[m] != MAX_CELLS+1) { p = map[m]; nr[p] = image->red[m]; ng[p] = image->green[m]; nb[p] = image->blue[m]; image->used[p] = TRUE; } } memcpy(image->red, nr, ncolors*sizeof(word)); memcpy(image->green, ng, ncolors*sizeof(word)); memcpy(image->blue, nb, ncolors*sizeof(word)); image->numcells = ncolors; if (verbose) fprintf(stderr, " %d colors used\n", ncolors);}/* * Get the image bounded by the given rectangle. * The associated colormap information is also extracted and returned. * TRUE is returned if an image was successfully grabbed, and FALSE * otherwise. */getImage(xrect, image, window) XRectangle *xrect; imageInfo *image; Window window;{ XImage *ximage; int depth, ncolors, cmapSize, numCmaps; int h, w; long i; XColor colors[MAX_CELLS]; Colormap *cmaps, cmap; if (xrect->width == 0 || xrect->height == 0) return FALSE; depth = DefaultDepth(hDisplay, hScreen); ximage = XGetImage(hDisplay, window, xrect->x, xrect->y, xrect->width, xrect->height, AllPlanes, depth==1 ? XYPixmap : ZPixmap); image->ximage = ximage; /* get the colormap info too */ cmaps = XListInstalledColormaps(hDisplay, window, &numCmaps); if (numCmaps == 0) cmap = DefaultColormap(hDisplay, hScreen); else { cmap = *cmaps; if (numCmaps > 1) fprintf(stderr, "%s: more than one colormap found - using first encountered", programName); } XFree(cmaps); ncolors = DisplayCells(hDisplay, hScreen); /* this won't cut the mustard for DirectColor */ for (i=0; i<ncolors; i++) colors[i].pixel = i; XQueryColors(hDisplay, cmap, colors, ncolors); for (i=0; i<ncolors; i++) { image->red[i] = colors[i].red; image->green[i] = colors[i].green; image->blue[i] = colors[i].blue; } /* figure out which colormap entries are actually used by the image */ ncolors = cmapSize = 0; memset(image->used, 0, MAX_CELLS); for (h=0; h<ximage->height; h++) for (w=0; w<ximage->width; w++) { i = XGetPixel(ximage, w, h); if (!image->used[i]) { image->used[i] = TRUE; if (i+1 > cmapSize) /* keep track of colormap size */ cmapSize = i+1; ncolors++; } } image->numcells = cmapSize; if (verbose) fprintf(stderr, "%s: image has %d colors\n", programName, ncolors); return TRUE;}/* * Let the user stretch a rectangle on the screen and return its values. * It may be wise to grab the server before calling this routine. If the * screen is allowed to change during XOR drawing video droppings may result. */getRectangle(xrect) XRectangle *xrect;{ XEvent event; unsigned int mask, x, y, rootx, rooty; GC gc; Cursor pointer1, pointer2; int boxDrawn = False; int rx, ry, rw, rh; Window root, child; int discarded; /* get some cursors for rectangle formation */ pointer1 = XCreateFontCursor(hDisplay, XC_ul_angle); pointer2 = XCreateFontCursor(hDisplay, XC_lr_angle); /* grab the pointer */ if (GrabSuccess != XGrabPointer(hDisplay, hRoot, False, ButtonPressMask, GrabModeAsync, GrabModeAsync, hRoot, pointer1, CurrentTime)) { fprintf(stderr,"%s - could not grab pointer!\n", programName); exit(3); } /* create a graphics context to draw with */ gc = XCreateGC(hDisplay, hRoot, 0, NULL); if (!gc) { fprintf(stderr,"%s - could not get drawing resources\n", programName); exit(3); } XSetSubwindowMode(hDisplay, gc, IncludeInferiors); XSetForeground(hDisplay, gc, 255); XSetFunction(hDisplay, gc, GXxor); /* get a button-press and pull out the root location */ XMaskEvent(hDisplay, ButtonPressMask, &event); rootx = rx = event.xbutton.x_root; rooty = ry = event.xbutton.y_root; /* get pointer motion events */ XChangeActivePointerGrab(hDisplay, ButtonMotionMask | ButtonReleaseMask, pointer2, CurrentTime); /* MAKE_RECT converts the original root coordinates and the event root * coordinates into a rectangle in xrect */#define MAKE_RECT(etype) \ x = event.etype.x_root; \ y = event.etype.y_root; \ rw = x - rootx; \ if (rw < 0) rw = -rw; \ rh = y - rooty; \ if (rh < 0) rh = -rh; \ rx = x < rootx ? x : rootx; \ ry = y < rooty ? y : rooty /* loop to let the user drag a rectangle */ while (TRUE) { XNextEvent(hDisplay, &event); switch(event.type) { case ButtonRelease: if (boxDrawn) { XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh); boxDrawn = False; } XFlush(hDisplay); /* record the final location */ MAKE_RECT(xbutton); /* release resources */ XFreeGC(hDisplay, gc); XFreeCursor(hDisplay, pointer1); XFreeCursor(hDisplay, pointer2); xrect->x = rx; xrect->y = ry; xrect->width = rw; xrect->height = rh; XUngrabPointer(hDisplay, CurrentTime); if (verbose) fprintf(stderr, "%s: rectangle is %d@%d, %dx%d\n", programName, xrect->x, xrect->y, xrect->width, xrect->height); return True; case MotionNotify: if (boxDrawn) { XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh); boxDrawn = False; } /* discard incoming motion notifies while we handle this one */ discarded = False; while (XCheckTypedEvent(hDisplay, MotionNotify, &event)) {} MAKE_RECT(xmotion); XDrawRectangle(hDisplay, hRoot, gc, rx, ry, rw, rh); boxDrawn = True; break; } }}/* * choose a window as in xwd */Window getWindow() { int status; Cursor cursor; XEvent event; Window result; result = None; cursor = XCreateFontCursor(hDisplay, XC_target); status = XGrabPointer(hDisplay, hRoot, FALSE, ButtonPressMask|ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, cursor, CurrentTime); if (status != GrabSuccess) { fprintf(stderr, "%s: can't grab mouse\n", programName); exit(3); } while (TRUE) { XAllowEvents(hDisplay, SyncPointer, CurrentTime); XWindowEvent(hDisplay, hRoot, ButtonPressMask|ButtonReleaseMask, &event); switch (event.type) { case ButtonRelease: result = event.xbutton.subwindow; if (result == None) result = hRoot; XUngrabPointer(hDisplay, CurrentTime); /* Done with pointer */ return result; break; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -