📄 xgrabsc.c
字号:
#ifdef MEMCPY/* memcpy and memset routines from C News *//* * memcpy - copy bytes */char *memcpy(dst, src, size)char * dst; char * src;int size;{ register char *d; register char *s; register int n; if (size <= 0) return(dst); s = src; d = dst; if (s <= d && s + (size-1) >= d) { /* Overlap, must copy right-to-left. */ s += size-1; d += size-1; for (n = size; n > 0; n--) *d-- = *s--; } else for (n = size; n > 0; n--) *d++ = *s++; return(dst);}/* * memset - set bytes * * CHARBITS should be defined only if the compiler lacks "unsigned char". * It should be a mask, e.g. 0377 for an 8-bit machine. */#ifndef CHARBITS# define UNSCHAR(c) ((unsigned char)(c))#else# define UNSCHAR(c) ((c)&CHARBITS)#endifchar *memset(s, ucharfill, size) char * s;register int ucharfill;int size;{ register char *scan; register int n; register int uc; scan = s; uc = UNSCHAR(ucharfill); for (n = size; n > 0; n--) *scan++ = uc; return(s);}#endif /* MEMCPY *//* * convert a pixmap image into a bitmap image */pixmap2bitmap(image) imageInfo *image;{ XImage *ximage = image->ximage; int x, y; word v, black, mid; dw total, blackrgb, midrgb, lowDelta, l; XImage *newImage; byte *newBytes; int usedCount; int blackp, whitep; if (ximage->bits_per_pixel == 1 || image->numcells < 1) return; blackp = BlackPixel(hDisplay,hScreen); whitep = WhitePixel(hDisplay,hScreen); /* get the darkest color */ blackrgb = 0x2FFFD; /* 3 * 0xFFFF == white */ usedCount = total = 0; for (x=0; x<image->numcells; x++) { if (image->used[x]) { l = (unsigned)image->red[x] +(unsigned)image->green[x] +(unsigned)image->blue[x]; if (l <= blackrgb) { black = x; blackrgb = l; } total += l; usedCount++; } } /* now find the mid color and use it as the cut-off for black */ midrgb = total / usedCount; lowDelta = 0x2FFFD; for (x=0; x<image->numcells; x++) { if (image->used[x]) { l = (unsigned)image->red[x] +(unsigned)image->green[x] +(unsigned)image->blue[x]; l -= midrgb; if (l < lowDelta) { mid = x; lowDelta = l; } } } midrgb = (unsigned)image->red[mid] +(unsigned)image->green[mid] +(unsigned)image->blue[mid]; /* create a bitmap image */ x = (ximage->width + 7) / 8; newBytes = (byte *)malloc(x * ximage->height); memset(newBytes, 0, x * ximage->height); newImage = XCreateImage(hDisplay, DefaultVisual(hDisplay, hScreen), 1, XYBitmap, 0, newBytes, ximage->width, ximage->height, 0, x); if (!newImage) { fprintf(stderr, "%s: unable to create bitmap for conversion\n", programName); XCloseDisplay(hDisplay); exit(3); } /* pound the pixels into it */ for (y = 0; y < ximage->height; y++) { for (x = 0; x < ximage->width; x++) { v = XGetPixel(ximage, x, y); l = (dw)image->red[v]+(dw)image->green[v]+(dw)image->blue[v]; XPutPixel(newImage, x, y, l<midrgb? blackp : whitep); } } free(ximage->data); memcpy(ximage, newImage, sizeof(XImage)); free(newImage); memset(image->used, 0, MAX_CELLS); image->used[whitep] = 1; image->used[blackp] = 1; image->numcells = 2;}#define GRAYS 17 /* ((4 * 4) + 1) patterns for a good dither */#define GRAYSTEP ((dw)(65536 / GRAYS))static byte DitherBits[GRAYS][4] = { 0xf, 0xf, 0xf, 0xf, 0xe, 0xf, 0xf, 0xf, 0xe, 0xf, 0xb, 0xf, 0xa, 0xf, 0xb, 0xf, 0xa, 0xf, 0xa, 0xf, 0xa, 0xd, 0xa, 0xf, 0xa, 0xd, 0xa, 0x7, 0xa, 0x5, 0xa, 0x7, 0xa, 0x5, 0xa, 0x5, 0x8, 0x5, 0xa, 0x5, 0x8, 0x5, 0x2, 0x5, 0x0, 0x5, 0x2, 0x5, 0x0, 0x5, 0x0, 0x5, 0x0, 0x4, 0x0, 0x5, 0x0, 0x4, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0};/* halftone or dither a color image, changing it into a monochrome * image */pixmap2halftone(image, dither) imageInfo *image; ditherType dither; /* type of dithering to perform */{ XImage *ximage = image->ximage; XImage *newImage; byte *newBytes, *ditherBits; word dindex; /* index into dither array */ dw color; /* pixel color */ word *index; /* index into dither array for a given pixel */ word x, y; /* random counters */ word x4, y4; register word w, h; register byte bits; char *str; dw intensity; int maxIntensity, threshold; word *fsIndex; int err, i; int *row1, *row2; int blackp = BlackPixel(hDisplay,hScreen); int whitep = WhitePixel(hDisplay,hScreen); if (ximage->depth <= 1 || dither == NO_DITHER) return; if (verbose) { switch (dither) { case MATRIX_HALFTONE: str = "Matrix halfton"; break; case MATRIX_DITHER: str = "Matrix dither"; break; case FS_DITHER: str = "Floyd-Steinberg dither"; break; default: fprintf(stderr, "%s: unknown type of dithering requested. Exiting...\n", programName); exit(3); } fprintf(stderr, "%s: %sing image...", programName, str); fflush(stderr); } /* create a bitmap image */ x = (dither == MATRIX_HALFTONE)? 4 : 1; w = ((ximage->width + 7) / 8) * x; h = ximage->height * x; newBytes = (byte *)malloc(w * h); memset(newBytes, 0, w * h); newImage = XCreateImage(hDisplay, DefaultVisual(hDisplay, hScreen), 1, XYBitmap, 0, newBytes, ximage->width * x, h, 0, w); if (!newImage) { fprintf(stderr, "%s: unable to create bitmap for conversion\n", programName); XCloseDisplay(hDisplay); exit(3); } /* if the number of possible pixels isn't very large, build an array * which we index by the pixel value to find the dither array index * by color brightness. we do this in advance so we don't have to do * it for each pixel. things will break if a pixel value is greater * than (1 << depth), which is bogus anyway. this calculation is done * on a per-pixel basis if the colormap is too big. */ if (ximage->depth <= 16) { index= (word *)malloc(sizeof(word) * MAX_CELLS); fsIndex= (word *)malloc(sizeof(word) * MAX_CELLS); if (index) for (x= 0; x < image->numcells; x++) { fsIndex[x] = (word)(0.30 * image->red[x] + 0.59 * image->green[x] + 0.11 * image->blue[x]); index[x] = fsIndex[x]/GRAYSTEP; if (index[x] >= GRAYS) index[x] = GRAYS - 1; } } else index = fsIndex = NULL; if (dither == FS_DITHER) { maxIntensity = 65535; threshold = maxIntensity/2; row1 = (int *)malloc(ximage->width*sizeof(int)); row2 = (int *)malloc(ximage->width*sizeof(int)); /* initialize row2 */ for (x= 0; x < ximage->width; x++) { color = XGetPixel(ximage, x, 0); row2[x] = fsIndex? fsIndex[color] : (dw)(0.30*image->red[color] + 0.59*image->green[color] + 0.11*image->blue[color]); } for (y= 0; y < ximage->height; y++) { /* row1 := row2 */ memcpy(row1, row2, ximage->width*sizeof(int)); /* Fill in next row */ if (y != ximage->height-1) for (x= 0; x < ximage->width; x++) { color = XGetPixel(ximage, x, y+1); row2[x] = fsIndex? fsIndex[color] : (dw)(0.30*image->red[color] + 0.59*image->green[color] + 0.11*image->blue[color]); } for (x= 0; x < ximage->width; x++) { color = XGetPixel(ximage, x, y); intensity = fsIndex? fsIndex[color] : (dw)(0.30*image->red[color] + 0.59*image->green[color] + 0.11*image->blue[color]); if ((i = row1[x]) > threshold) err = i - maxIntensity; else { XPutPixel(newImage, x, y, blackp); err = i; } /* Diagonal gets 1/4 of error. */ row2[x+1] += err/4; /* Right and below get 3/8 of error */ err = err*3/8; row2[x] += err; row1[x+1] += err; } } if (row1) free(row1); if (row2) free(row2); } else { /* matrix dither or halftone */ for (y= 0; y < ximage->height; y++) { for (x= 0; x < ximage->width; x++) { color = XGetPixel(ximage, x, y); dindex = index? index[color] : (dw)(0.30*image->red[color] + 0.59*image->green[color] + 0.11*image->blue[color])/GRAYSTEP; if (dindex >= GRAYS) /* catch rounding errors */ dindex= GRAYS - 1; if (dither == MATRIX_DITHER) { if (DitherBits[dindex][y & 3] & (1 << (x & 3))) XPutPixel(newImage, x, y, blackp); } else { /* halftone */ /* loop for the four Y bits in the dither pattern, putting all * four X bits in at once. if you think this would be hard to * change to be an NxN dithering array, you're right, since we're * banking on the fact that we need only shift the mask based on * whether x is odd or not. an 8x8 array wouldn't even need that, * but blowing an image up by 64x is probably not a feature. */ ditherBits = &(DitherBits[dindex][0]); x4 = x * 4; y4 = y * 4; for (h= 0; h < 4; h++) { bits = ditherBits[h]; for (w=0; w < 4; w++) { XPutPixel(newImage, x4+w, y4+h, bits & 1 ? blackp : whitep); bits /= 2; } } } } } } if (verbose) fputc('\n', stderr); free(ximage->data); memcpy(ximage, newImage, sizeof(XImage)); free(newImage); if (index) free(index); if (fsIndex) free(fsIndex); image->numcells = 0;}/* swap the bits in a byte */swapbits(b) byte b;{ byte b2; b2 = 0; b2 |= (b & 0x01) << 7; b2 |= (b & 0x02) << 5; b2 |= (b & 0x04) << 3; b2 |= (b & 0x08) << 1; b2 |= (b & 0x10) >> 1; b2 |= (b & 0x20) >> 3; b2 |= (b & 0x40) >> 5; b2 |= (b & 0x80) >> 7; return b2;}/* swap the bytes in a long int */swapbytes(pDblw) dw *pDblw; { union { dw dbl; byte bytes[4]; } cnv; byte aByte; cnv.dbl = *pDblw; aByte = cnv.bytes[0]; cnv.bytes[0] = cnv.bytes[3]; cnv.bytes[3] = aByte; aByte = cnv.bytes[1]; cnv.bytes[1] = cnv.bytes[2]; cnv.bytes[2] = aByte; *pDblw = cnv.dbl; }/* swap some long ints. (n is number of BYTES, not number of longs) */swapdws (bp, n) register char *bp; register unsigned n;{ register char c; register char *ep = bp + n; register char *sp; while (bp < ep) { sp = bp + 3; c = *sp; *sp = *bp; *bp++ = c; sp = bp + 1; c = *sp; *sp = *bp; *bp++ = c; bp += 2; }}/* swap some short ints */swapwords (bp, n) register char *bp; register unsigned n;{ register char c; register char *ep = bp + n; while (bp < ep) { c = *bp; *bp = *(bp + 1); bp++; *bp++ = c; }}writeSimple(image, outfile) imageInfo *image; FILE *outfile;{ dw width, height, hasColormap, colormapSize; dw swaptest = 1; int i, w, h; if (verbose) fprintf("%s: writing in simple output format\n", programName); if (image->ximage->depth != 8) { fprintf("%s: can't write simple image format if depth is not 8\n", programName); return; } width = image->ximage->width; height = image->ximage->height; hasColormap = 1; colormapSize = image->numcells; if (*(char *)&swaptest==0) { swapdws(&width, 1); swapdws(&height, 1); swapdws(&hasColormap, 1); swapdws(&colormapSize, 1); } fwrite(&width, 4, 1, outfile); fwrite(&height, 4, 1, outfile); fwrite(&hasColormap, 4, 1, outfile); fwrite(&colormapSize, 4, 1, outfile); for (i=0; i<image->numcells; i++) fputc((byte)(image->red[i]>>8), outfile); for (i=0; i<image->numcells; i++) fputc((byte)(image->green[i]>>8), outfile); for (i=0; i<image->numcells; i++) fputc((byte)(image->blue[i]>>8), outfile); for (i=0; i<image->numcells; i++) fputc((byte)(image->used[i]), outfile); for (h=0; h<image->ximage->height; h++) for (w=0; w<image->ximage->width; w++) fputc(XGetPixel(image->ximage, w, h), outfile);}/* * Write an image in Postscript format */writePostscript(image, outfile, encode, encapsulate) imageInfo *image; FILE *outfile; int encode; /* TRUE if we're to encode the Postscript output */ int encapsulate; /* TRUE if encapsulated Postscript output is wanted */{ register byte b, *ptr; register int x, y; register int i; XImage *ximage = image->ximage; XImage *psimage; double xdpi, ydpi, xscale, yscale, f; int lshift, lmask; int depth, bpl, spb; int reverse; long p; /* rle variables */ int rlecount; byte rlesample; dw rletotal; int widthcount; int firstSample; if (verbose) fprintf(stderr, "%s: formatting Postscript output\n", programName);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -