From ab0879a8bcb3e816912bc89b8e21c22cc2a4c0c2 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Thu, 12 Nov 1998 20:49:26 +0100 Subject: [PATCH] rnd-19981112-1 --- src/Makefile | 2 - src/image.c | 857 +++++++++++++-------------------------------------- src/image.h | 120 +++----- src/init.c | 34 +- src/pcx.c | 179 +++++++---- 5 files changed, 386 insertions(+), 806 deletions(-) diff --git a/src/Makefile b/src/Makefile index a3a5b396..6dc3a1a2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -92,7 +92,6 @@ SRCS = main.c \ joystick.c \ cartoons.c \ random.c \ - gif.c \ pcx.c \ image.c \ network.c \ @@ -113,7 +112,6 @@ OBJS = main.o \ joystick.o \ cartoons.o \ random.o \ - gif.o \ pcx.o \ image.o \ network.o \ diff --git a/src/image.c b/src/image.c index d73c9a5a..f82a981b 100644 --- a/src/image.c +++ b/src/image.c @@ -17,370 +17,87 @@ /* extra colors to try allocating in private color maps to minimise flashing */ #define NOFLASH_COLORS 256 -Image *monochrome(Image *cimage) +static void Image_to_Mask(Image *image) { - Image *image; - unsigned char *sp, *dp, *dp2; /* data pointers */ - unsigned int spl; /* source pixel length in bytes */ - unsigned int dll; /* destination line length in bytes */ - Pixel color; /* pixel color */ - unsigned int x, y; /* random counters */ - int bitmap_pixel; - - if (BITMAPP(cimage)) - { - printf("-->ERROR(monochrome)\n"); - - return(NULL); - } - - image = newBitImage(cimage->width, cimage->height); - - spl = cimage->pixlen; - dll = (image->width / 8) + (image->width % 8 ? 1 : 0); - - sp = cimage->data; - dp = image->data; - - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - dp2 = dp + (x / 8); /* dp + x/8 */ - color = memToVal(sp, spl); - - if (cimage->rgb.red[color] > 0x0000 || - cimage->rgb.green[color] > 0x0000 || - cimage->rgb.blue[color] > 0x0000) - bitmap_pixel = 0x00; - else - bitmap_pixel = 0x80; - - *dp2 |= bitmap_pixel >> (x % 8); - sp += spl; - } - - dp += dll; /* next row */ - } + unsigned char *src_ptr, *dst_ptr, *dst_ptr2; + unsigned int bytes_per_row; + unsigned int x, y; + unsigned char bitmask; - return(image); -} - -static unsigned int *buildIndex(unsigned int width, - unsigned int zoom, - unsigned int *rwidth) -{ - float fzoom; - unsigned int *index; - unsigned int a; + bytes_per_row = (image->width + 7) / 8; + src_ptr = image->data; + dst_ptr = image->data_mask; - if (!zoom) + for (y=0; yheight; y++) { - fzoom = 100.0; - *rwidth = width; - } - else - { - fzoom = (float)zoom / 100.0; - *rwidth = (unsigned int)(fzoom * width + 0.5); - } - index = (unsigned int *)checked_malloc(sizeof(unsigned int) * *rwidth); - for (a=0; a<*rwidth; a++) - { - if (zoom) - *(index + a) = (unsigned int)((float)a / fzoom + 0.5); - else - *(index + a) = a; - } - return(index); -} - -Image *zoom(Image *oimage, unsigned int xzoom, unsigned int yzoom) -{ - Image *image; - unsigned int *xindex, *yindex; - unsigned int xwidth, ywidth; - unsigned int x, y, xsrc, ysrc; - unsigned int pixlen; - unsigned int srclinelen; - unsigned int destlinelen; - byte *srcline, *srcptr; - byte *destline, *destptr; - byte srcmask, destmask, bit; - Pixel value; - - if ((!xzoom || xzoom == 100) && (!yzoom || yzoom == 100)) - return(oimage); - - if (!xzoom) - printf(" Zooming image Y axis by %d%%...", yzoom); - else if (!yzoom) - printf(" Zooming image X axis by %d%%...", xzoom); - else if (xzoom == yzoom) - printf(" Zooming image by %d%%...", xzoom); - else - printf(" Zooming image X axis by %d%% and Y axis by %d%%...", - xzoom, yzoom); - fflush(stdout); - - xindex = buildIndex(oimage->width, xzoom, &xwidth); - yindex = buildIndex(oimage->height, yzoom, &ywidth); - - switch (oimage->type) - { - case IBITMAP: - image = newBitImage(xwidth, ywidth); - for (x=0; xrgb.used; x++) - { - *(image->rgb.red + x) = *(oimage->rgb.red + x); - *(image->rgb.green + x) = *(oimage->rgb.green + x); - *(image->rgb.blue + x) = *(oimage->rgb.blue + x); - } - image->rgb.used = oimage->rgb.used; - destline = image->data; - destlinelen = (xwidth / 8) + (xwidth % 8 ? 1 : 0); - srcline = oimage->data; - srclinelen = (oimage->width / 8) + (oimage->width % 8 ? 1 : 0); - for (y=0, ysrc=*(yindex + y); y>= 1)) - { - srcmask = 0x80; - srcptr++; - } - } - while (xsrc != *(xindex + x)); + bitmask = 0x80; /* start with leftmost bit in the byte */ + dst_ptr2 = dst_ptr; /* start with leftmost byte in the row */ - bit = srcmask & *srcptr; - } - if (bit) - *destptr |= destmask; - if (!(destmask >>= 1)) - { - destmask = 0x80; - destptr++; - } - } - destline += destlinelen; - } - break; + for (x=0; xwidth; x++) + { + if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ + *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ - case IRGB: - image = newRGBImage(xwidth, ywidth, oimage->depth); - for (x=0; xrgb.used; x++) + if ((bitmask >>= 1) == 0) /* bit at rightmost byte position reached? */ { - *(image->rgb.red + x) = *(oimage->rgb.red + x); - *(image->rgb.green + x) = *(oimage->rgb.green + x); - *(image->rgb.blue + x) = *(oimage->rgb.blue + x); + bitmask = 0x80; /* start again with leftmost bit position */ + dst_ptr2++; /* continue with next byte in image mask */ } - image->rgb.used = oimage->rgb.used; - - pixlen = oimage->pixlen; - destptr = image->data; - srcline = oimage->data; - srclinelen = oimage->width * pixlen; - for (y=0, ysrc=*(yindex + y); ypixlen); - - for (x=0, xsrc=*(xindex + x); xrgb.red, - *green = image->rgb.green, - *blue = image->rgb.blue; - Intensity r,g,b; - unsigned int x, y, badcount = 0, dupcount = 0, unusedcount = 0; - unsigned char *pixptr, *pixend; - - if (!RGBP(image) || image->rgb.compressed) - return; - - used = (unsigned char *)checked_calloc(sizeof(unsigned char) * depthToColors(image->depth)); - dmask = (1 << image->depth) -1; /* Mask any illegal bits for that depth */ - map = (Pixel *)checked_calloc(sizeof(Pixel) * depthToColors(image->depth)); - - /* init fast duplicate check table */ - for(r=0;r<32;r++) - for(g=0;g<32;g++) - for(b=0;b<32;b++) - fast[r][g][b] = 0; - - /* do pass 1 through the image to check index usage */ - - pixptr = image->data; - pixend = pixptr + (image->height * image->width); - for(;pixptr < pixend; pixptr++) - used[(*pixptr) & dmask] = 1; - - /* count the bad pixels */ - for (x = image->rgb.used; x < depthToColors(image->depth); x++) - if (used[x]) - badcount++; - - /* figure out duplicates and unuseds, and create the new mapping */ - next_index = 0; - for (x = 0; x < image->rgb.used; x++) - { - if (!used[x]) - { - unusedcount++; - continue; /* delete this index */ - } + XGCValues gcv; - /* check for duplicate */ - r = red[x]; - g = green[x]; - b = blue[x]; - if (fast[r>>11][g>>11][b>>11]) /* if matches fast check */ - { - /* then do a linear search */ - for (y = x+1; y < image->rgb.used; y++) - { - if (r == red[y] && g == green[y] && b == blue[y]) - break; - } - if (y < image->rgb.used) /* found match */ - { - map[x] = y; - dupcount++; - continue; /* delete this index */ - } - fast[r>>11][g>>11][b>>11] = 1; - } - /* will map to this index */ - map[x] = next_index; - next_index++; - } + ximageinfo->pixmap = + XCreatePixmap(display, parent, + ximageinfo->ximage->width, + ximageinfo->ximage->height, + ximageinfo->depth); + + ximageinfo->pixmap_mask = + XCreatePixmap(display, parent, + ximageinfo->ximage->width, + ximageinfo->ximage->height, + 1); - /* change the image pixels */ - pixptr = image->data; - pixend = pixptr + (image->height * image->width); - for(;pixptr < pixend; pixptr++) - *pixptr = map[(*pixptr) & dmask]; + /* build and cache the GC */ - /* change the colormap */ - for (x = 0; x < image->rgb.used; x++) + if (!ximageinfo->gc) { - if (!used[x]) - continue; - red[map[x]] = red[x]; - green[map[x]] = green[x]; - blue[map[x]] = blue[x]; + gcv.function = GXcopy; + ximageinfo->gc = + XCreateGC(ximageinfo->display, ximageinfo->pixmap, + GCFunction, &gcv); } - image->rgb.used = next_index; - /* clean up */ - free(map); - free(used); - - - -#if 0 - if (badcount) - printf("%d out-of-range pixels, ", badcount); - - if (!unusedcount && !dupcount) - printf("no improvment\n"); - else + if (!ximageinfo->gc_mask) { - if (dupcount) - printf("%d duplicate%s and %d unused color%s removed...", - dupcount, (dupcount == 1 ? "" : "s"), - unusedcount, (unusedcount == 1 ? "" : "s")); - printf("%d unique color%s\n", - next_index, (next_index == 1 ? "" : "s")); + gcv.function = GXcopy; + gcv.foreground = ximageinfo->foreground; + gcv.background = ximageinfo->background; + ximageinfo->gc_mask = + XCreateGC(ximageinfo->display, ximageinfo->pixmap_mask, + GCFunction | GCForeground | GCBackground, &gcv); } -#endif - + XPutImage(ximageinfo->display, ximageinfo->pixmap, ximageinfo->gc, + ximageinfo->ximage, 0, 0, 0, 0, + ximageinfo->ximage->width, ximageinfo->ximage->height); + XPutImage(ximageinfo->display, ximageinfo->pixmap_mask, ximageinfo->gc_mask, + ximageinfo->ximage_mask, 0, 0, 0, 0, + ximageinfo->ximage->width, ximageinfo->ximage->height); - image->rgb.compressed = TRUE; /* don't do it again */ -} - - - - -Pixmap XImage_to_Pixmap(Display *display, Window parent, - XImageInfo *ximageinfo) -{ - Pixmap pixmap; - - pixmap = XCreatePixmap(display, parent, - ximageinfo->ximage->width, ximageinfo->ximage->height, - ximageinfo->depth); - - ximageinfo->drawable = pixmap; - - XImage_to_Drawable(ximageinfo, 0, 0, 0, 0, - ximageinfo->ximage->width, ximageinfo->ximage->height); - return(pixmap); + return (ximageinfo->pixmap != None && ximageinfo->pixmap_mask != None); } /* find the best pixmap depth supported by the server for a particular * visual and return that depth. - * - * this is complicated by R3's lack of XListPixmapFormats so we fake it - * by looking at the structure ourselves. */ static unsigned int bitsPerPixelAtDepth(Display *display, int screen, @@ -402,8 +119,7 @@ static unsigned int bitsPerPixelAtDepth(Display *display, int screen, } XFree(xf); - /* this should never happen; if it does, we're in trouble - */ + /* this should never happen; if it does, we're in trouble */ fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); exit(1); @@ -424,6 +140,12 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, XGCValues gcv; XImageInfo *ximageinfo; + /* for building image */ + byte *data, *destptr, *srcptr; + + /* for building image mask */ + byte *data_mask; + if (!global_cmap) { if (visual == DefaultVisual(display, screen)) @@ -447,7 +169,9 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, ximageinfo->rootimage = FALSE; ximageinfo->foreground = ximageinfo->background= 0; ximageinfo->gc = NULL; + ximageinfo->gc_mask = NULL; ximageinfo->ximage = NULL; + ximageinfo->ximage_mask = NULL; switch (visual->class) { @@ -556,13 +280,20 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, ximageinfo->index = (Pixel *)checked_malloc(sizeof(Pixel) * image->rgb.used); +#if 0 for (a=0; argb.used; a++) +#endif + + for (a=0; argb.color_used[a]) + continue; + xcolor.red = *(image->rgb.red + a); xcolor.green = *(image->rgb.green + a); xcolor.blue = *(image->rgb.blue + a); @@ -572,9 +303,8 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, { if (!private_cmap) { - /* - printf("switching to private colormap...\n"); - */ + if (options.verbose) + Error(ERR_RETURN, "switching to private colormap"); /* we just filled up the default colormap -- get a private one which contains all already allocated colors */ @@ -680,186 +410,150 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, break; } - /* create an XImage and related colormap based on the image type - * we have. - */ - - /* - printf(" Building XImage..."); - fflush(stdout); - */ - - switch (image->type) - { - case IBITMAP: - { - byte *data; - - /* we copy the data to be more consistent - */ + /* CREATE IMAGE ITSELF */ + /* modify image data to match visual and colormap */ - linelen = ((image->width + 7) / 8); - data= checked_malloc(linelen * image->height); + dbits = bitsPerPixelAtDepth(display, screen, ddepth);/* bits per pixel */ + dpixlen = (dbits + 7) / 8; /* bytes per pixel */ - memcpy((char *)data, (char *)image->data, linelen * image->height); + ximageinfo->ximage = XCreateImage(display, visual, ddepth, ZPixmap, 0, + NULL, image->width, image->height, + 8, image->width * dpixlen); - gcv.function= GXcopy; - ximageinfo->ximage= XCreateImage(display, visual, 1, XYBitmap, - 0, (char *)data, image->width, - image->height, - 8, linelen); + data = (byte *)checked_malloc(image->width * image->height * dpixlen); + ximageinfo->depth = ddepth; + ximageinfo->ximage->data = (char *)data; + ximageinfo->ximage->byte_order = MSBFirst; + srcptr = image->data; + destptr = data; - /* use this if you want to use the bitmap as a mask */ - ximageinfo->depth = image->depth; + switch (visual->class) + { + case DirectColor: + case TrueColor: + { + Pixel pixval; - if(visual->class == DirectColor || visual->class == TrueColor) + for (y=0; yheight; y++) { - Pixel pixval; - dbits= bitsPerPixelAtDepth(display, screen, ddepth); - dpixlen= (dbits + 7) / 8; - pixval= redvalue[image->rgb.red[0] >> 8] | - greenvalue[image->rgb.green[0] >> 8] | - bluevalue[image->rgb.blue[0] >> 8]; - ximageinfo->background = pixval; - pixval= redvalue[image->rgb.red[1] >> 8] | - greenvalue[image->rgb.green[1] >> 8] | - bluevalue[image->rgb.blue[1] >> 8]; - ximageinfo->foreground = pixval; - } - else /* Not Direct or True Color */ - { - ximageinfo->foreground = BlackPixel(display, screen); - ximageinfo->background = WhitePixel(display, screen); + for (x=0; xwidth; x++) + { + pixval = memToVal(srcptr, 1); + pixval = + redvalue[image->rgb.red[pixval] >> 8] | + greenvalue[image->rgb.green[pixval] >> 8] | + bluevalue[image->rgb.blue[pixval] >> 8]; + valToMem(pixval, destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; + } } - ximageinfo->ximage->bitmap_bit_order= MSBFirst; - ximageinfo->ximage->byte_order= MSBFirst; - break; } - case IRGB: + default: { - /* modify image data to match visual and colormap - */ - - byte *data, *destptr, *srcptr; - - dbits = bitsPerPixelAtDepth(display, screen, ddepth);/* bits per pixel */ - dpixlen = (dbits + 7) / 8; /* bytes per pixel */ - - ximageinfo->ximage = XCreateImage(display, visual, ddepth, ZPixmap, 0, - NULL, image->width, image->height, - 8, image->width * dpixlen); - - data = (byte *)checked_malloc(image->width * image->height * dpixlen); - ximageinfo->depth = ddepth; - ximageinfo->ximage->data = (char *)data; - ximageinfo->ximage->byte_order = MSBFirst; - srcptr = image->data; - destptr = data; - - switch (visual->class) + if (dpixlen == 1) /* most common */ { - case DirectColor: - case TrueColor: - { - Pixel pixval; - - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - pixval = memToVal(srcptr, 1); - pixval = redvalue[image->rgb.red[pixval] >> 8] | - greenvalue[image->rgb.green[pixval] >> 8] | - bluevalue[image->rgb.blue[pixval] >> 8]; - valToMem(pixval, destptr, dpixlen); - srcptr += 1; - destptr += dpixlen; - } - } - break; - } - - default: - { - if (dpixlen == 1) /* most common */ + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) { - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - *destptr = ximageinfo->index[c + *srcptr]; - srcptr++; - destptr++; - } - } + *destptr = ximageinfo->index[c + *srcptr]; + srcptr++; + destptr++; } - else /* less common */ + } + } + else /* less common */ + { + for (y=0; yheight; y++) + { + for (x=0; xwidth; x++) { - for (y=0; yheight; y++) - { - for (x=0; xwidth; x++) - { - register unsigned long temp; - temp = memToVal(srcptr, 1); - valToMem(ximageinfo->index[c + temp], destptr, dpixlen); - srcptr += 1; - destptr += dpixlen; - } - } + register unsigned long temp; + temp = memToVal(srcptr, 1); + valToMem(ximageinfo->index[c + temp], destptr, dpixlen); + srcptr += 1; + destptr += dpixlen; } } - break; } } } + /* NOW CREATE IMAGE MASK */ + /* we copy the data to be more consistent */ + + linelen = ((image->width + 7) / 8); + data_mask = checked_malloc(linelen * image->height); + + memcpy((char *)data_mask, (char *)image->data_mask, + linelen * image->height); + + gcv.function = GXcopy; + ximageinfo->ximage_mask = + XCreateImage(display, visual, 1, XYBitmap, 0, (char *)data_mask, + image->width, image->height, 8, linelen); + + + /* use this if you want to use the bitmap as a mask */ /* - printf("done\n"); - */ + ximageinfo->depth = image->depth; + */ - if (redvalue) + if (visual->class == DirectColor || visual->class == TrueColor) { - free((byte *)redvalue); - free((byte *)greenvalue); - free((byte *)bluevalue); + Pixel pixval; + dbits = bitsPerPixelAtDepth(display, screen, ddepth); + dpixlen = (dbits + 7) / 8; + pixval = + redvalue[65535 >> 8] | + greenvalue[65535 >> 8] | + bluevalue[65535 >> 8]; + /* + redvalue[image->rgb.red[0] >> 8] | + greenvalue[image->rgb.green[0] >> 8] | + bluevalue[image->rgb.blue[0] >> 8]; + */ + ximageinfo->background = pixval; + pixval = + redvalue[0 >> 8] | + greenvalue[0 >> 8] | + bluevalue[0 >> 8]; + /* + redvalue[image->rgb.red[1] >> 8] | + greenvalue[image->rgb.green[1] >> 8] | + bluevalue[image->rgb.blue[1] >> 8]; + */ + ximageinfo->foreground = pixval; + } + else /* Not Direct or True Color */ + { + ximageinfo->foreground = BlackPixel(display, screen); + ximageinfo->background = WhitePixel(display, screen); } - return(ximageinfo); -} + /* + ximageinfo->foreground = BlackPixel(display, screen); + ximageinfo->background = WhitePixel(display, screen); + */ -/* Given an XImage and a drawable, move a rectangle from the Ximage - * to the drawable. - */ + ximageinfo->foreground = WhitePixel(display, screen); + ximageinfo->background = BlackPixel(display, screen); -void XImage_to_Drawable(XImageInfo *ximageinfo, - int src_x, int src_y, int dst_x, int dst_y, - unsigned int w, unsigned int h) -{ - XGCValues gcv; - /* build and cache the GC - */ + ximageinfo->ximage_mask->bitmap_bit_order = MSBFirst; + ximageinfo->ximage_mask->byte_order = MSBFirst; - if (!ximageinfo->gc) + if (redvalue) { - gcv.function = GXcopy; - if (ximageinfo->ximage->depth == 1) - { - gcv.foreground = ximageinfo->foreground; - gcv.background = ximageinfo->background; - ximageinfo->gc = XCreateGC(ximageinfo->display, ximageinfo->drawable, - GCFunction | GCForeground | GCBackground, - &gcv); - } - else - ximageinfo->gc = XCreateGC(ximageinfo->display, ximageinfo->drawable, - GCFunction, &gcv); + free((byte *)redvalue); + free((byte *)greenvalue); + free((byte *)bluevalue); } - XPutImage(ximageinfo->display, ximageinfo->drawable, ximageinfo->gc, - ximageinfo->ximage, src_x, src_y, dst_x, dst_y, w, h); + return(ximageinfo); } /* free up anything cached in the local Ximage structure. @@ -883,123 +577,60 @@ void freeXImage(Image *image, XImageInfo *ximageinfo) /* should we free private color map to ??? */ } - - -/* this table is useful for quick conversions between depth and ncolors - */ - -unsigned long DepthToColorsTable[] = +Image *newImage(unsigned int width, unsigned int height, unsigned int depth) { - /* 0 */ 1, - /* 1 */ 2, - /* 2 */ 4, - /* 3 */ 8, - /* 4 */ 16, - /* 5 */ 32, - /* 6 */ 64, - /* 7 */ 128, - /* 8 */ 256, - /* 9 */ 512, - /* 10 */ 1024, - /* 11 */ 2048, - /* 12 */ 4096, - /* 13 */ 8192, - /* 14 */ 16384, - /* 15 */ 32768, - /* 16 */ 65536, - /* 17 */ 131072, - /* 18 */ 262144, - /* 19 */ 524288, - /* 20 */ 1048576, - /* 21 */ 2097152, - /* 22 */ 4194304, - /* 23 */ 8388608, - /* 24 */ 16777216 -}; - -void newRGBMapData(RGBMap *rgb, unsigned int size) -{ - rgb->used = 0; - rgb->size = size; - rgb->compressed = FALSE; - rgb->red = (Intensity *)checked_malloc(sizeof(Intensity) * size); - rgb->green = (Intensity *)checked_malloc(sizeof(Intensity) * size); - rgb->blue = (Intensity *)checked_malloc(sizeof(Intensity) * size); -} - -void freeRGBMapData(RGBMap *rgb) -{ - free((byte *)rgb->red); - free((byte *)rgb->green); - free((byte *)rgb->blue); -} + Image *image; + unsigned int bytes_per_row; + const unsigned int bytes_per_pixel = 1; + int i; -Image *newBitImage(unsigned int width, unsigned int height) -{ - Image *image; - unsigned int linelen; - - image = (Image *)checked_malloc(sizeof(Image)); - image->type = IBITMAP; - newRGBMapData(&(image->rgb), (unsigned int)2); - *(image->rgb.red)= *(image->rgb.green) = *(image->rgb.blue)= 65535; - *(image->rgb.red + 1)= *(image->rgb.green + 1) = *(image->rgb.blue + 1)= 0; - image->rgb.used = 2; - image->width = width; - image->height = height; - image->depth = 1; - linelen = ((width + 7) / 8); - image->data = (unsigned char *)checked_calloc(linelen * height); - return(image); -} + if (depth > 8) + Error(ERR_EXIT, "images with more than 256 colors are not supported"); -Image *newRGBImage(unsigned int width, unsigned int height, unsigned int depth) -{ - Image *image; - unsigned int pixlen, numcolors; - - if (depth == 0) /* special case for `zero' depth image, which is */ - depth = 1; /* sometimes interpreted as `one color' */ - pixlen = ((depth+7) / 8); - numcolors = depthToColors(depth); - image = (Image *)checked_malloc(sizeof(Image)); - image->type = IRGB; - newRGBMapData(&(image->rgb), numcolors); + depth = 8; + image = checked_malloc(sizeof(Image)); + image->data = checked_malloc(width * height * bytes_per_pixel); image->width = width; image->height = height; image->depth = depth; - image->pixlen = pixlen; - image->data = (unsigned char *)checked_malloc(width * height * pixlen); - return(image); -} + image->rgb.used = 0; + for (i=0; irgb.color_used[i] = FALSE; -void freeImageData(Image *image) -{ - freeRGBMapData(&(image->rgb)); - free(image->data); + bytes_per_row = (width + 7) / 8; + image->data_mask = checked_calloc(bytes_per_row * height); + + return image; } void freeImage(Image *image) { - freeImageData(image); - free((byte *)image); + free(image->data); + free(image->data_mask); + free(image); } /* ------------------------------------------------------------------------- */ #ifdef DEBUG -/* + #define DEBUG_TIMING -*/ + #endif int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, Pixmap *pixmap, Pixmap *pixmap_mask) { + Image *image; + XImageInfo *ximageinfo; + + /* Image *image, *image_mask; XImageInfo *ximageinfo, *ximageinfo_mask; + */ + int screen; Visual *visual; unsigned int depth; @@ -1009,12 +640,8 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, count1 = Counter(); #endif - /* load GIF file */ - if (!(image = Read_PCX_to_Image(filename))) - { - printf("Loading GIF image failed -- maybe no GIF...\n"); - exit(1); - } + if ((image = Read_PCX_to_Image(filename)) == NULL) + return PCX_FileInvalid; #ifdef DEBUG_TIMING count2 = Counter(); @@ -1023,18 +650,12 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, count1 = Counter(); #endif - if (image->depth > 8) - { - printf("Sorry, GIFs with more than 256 colors are not supported.\n"); - exit(1); - } - - /* minimize colormap */ - compress(image); + /* create image mask */ + Image_to_Mask(image); #ifdef DEBUG_TIMING count2 = Counter(); - printf(" COMPRESSING IMAGE COLORMAP IN %.2f SECONDS\n", + printf(" CONVERTING IMAGE TO MASK IN %.2f SECONDS\n", (float)(count2-count1)/1000.0); count1 = Counter(); #endif @@ -1061,7 +682,7 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, XSetWindowColormap(display, window, ximageinfo->cmap); /* convert XImage to Pixmap */ - if ((*pixmap = XImage_to_Pixmap(display, window, ximageinfo)) == None) + if (!(XImage_to_Pixmap(display, window, ximageinfo))) { fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); exit(1); @@ -1074,44 +695,8 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, count1 = Counter(); #endif - /* create mono image for masking */ - image_mask = monochrome(image); - -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" CONVERTING IMAGE TO MASK IN %.2f SECONDS\n", - (float)(count2-count1)/1000.0); - count1 = Counter(); -#endif - - /* convert internal image structure to X11 XImage */ - if (!(ximageinfo_mask = Image_to_XImage(display, screen, visual, depth, - image_mask))) - { - fprintf(stderr, "Cannot convert Image to XImage.\n"); - exit(1); - } - -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" CONVERTING MASK TO XIMAGE IN %.2f SECONDS\n", - (float)(count2-count1)/1000.0); - count1 = Counter(); -#endif - - /* convert XImage to Pixmap */ - if ((*pixmap_mask = XImage_to_Pixmap(display, window, ximageinfo_mask)) == None) - { - fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); - exit(1); - } - -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" CONVERTING MASK TO PIXMAP IN %.2f SECONDS\n", - (float)(count2-count1)/1000.0); - count1 = Counter(); -#endif + *pixmap = ximageinfo->pixmap; + *pixmap_mask = ximageinfo->pixmap_mask; - return(GIF_Success); + return(PCX_Success); } diff --git a/src/image.h b/src/image.h index 087ad921..0561257f 100644 --- a/src/image.h +++ b/src/image.h @@ -16,67 +16,52 @@ #include "main.h" +#define MAX_COLORS 256 /* maximal number of colors for each image */ + typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ -/* This struct holds the X-client side bits for a rendered image. */ typedef struct { - Display *display; /* destination display */ - int screen; /* destination screen */ - int depth; /* depth of drawable we want/have */ - Drawable drawable; /* drawable to send image to */ - Pixel *index; /* array of pixel values allocated */ - int no; /* number of pixels in the array */ - int rootimage; /* True if is a root image - eg, retain colors */ + Display *display; /* destination display */ + int screen; /* destination screen */ + int depth; /* depth of drawable we want/have */ + Drawable drawable; /* drawable to send image to */ + Pixel *index; /* array of pixel values allocated */ + int no; /* number of pixels in the array */ + int rootimage; /* True if is a root image - eg, retain colors */ Pixel foreground; /* foreground and background pixels for mono images */ Pixel background; - Colormap cmap; /* colormap used for image */ - GC gc; /* cached gc for sending image */ - XImage *ximage; /* ximage structure */ + Colormap cmap; /* colormap used for image */ + GC gc; /* cached gc for sending image */ + GC gc_mask; /* cached gc for sending image mask */ + XImage *ximage; /* ximage structure */ + XImage *ximage_mask;/* ximage structure of mask */ + Pixmap pixmap; /* final pixmap */ + Pixmap pixmap_mask; /* final pixmap of mask */ } XImageInfo; -/* Function declarations */ -void sendXImage(); /* send.c */ -XImageInfo *imageToXImage(); -Pixmap ximageToPixmap(); -void freeXImage(); - - -typedef struct rgbmap +struct RGBMap { - unsigned int size; /* size of RGB map */ - unsigned int used; /* number of colors used in RGB map */ - int compressed; /* image uses colormap fully */ - Intensity *red; /* color values in X style */ - Intensity *green; - Intensity *blue; -} RGBMap; - -/* image structure - */ + unsigned int used; /* number of colors used in RGB map */ + Intensity red[MAX_COLORS]; /* color values in X style */ + Intensity green[MAX_COLORS]; + Intensity blue[MAX_COLORS]; + boolean color_used[MAX_COLORS]; /* flag if color cell is used */ +}; -typedef struct { - unsigned int type; /* type of image */ - RGBMap rgb; /* RGB map of image if IRGB type */ - unsigned int width; /* width of image in pixels */ - unsigned int height; /* height of image in pixels */ - unsigned int depth; /* depth of image in bits if IRGB type */ - unsigned int pixlen; /* length of pixel if IRGB type */ - byte *data; /* data rounded to full byte for each row */ - float gamma; /* gamma of display the image is adjusted for */ +typedef struct +{ + struct RGBMap rgb; /* RGB map of image if IRGB type */ + unsigned int width; /* width of image in pixels */ + unsigned int height; /* height of image in pixels */ + unsigned int depth; /* depth of image in bits if IRGB type */ + byte *data; /* image data */ + byte *data_mask; /* clip mask data */ } Image; -#define IBITMAP 0 /* image is a bitmap */ -#define IRGB 1 /* image is RGB */ - -#define BITMAPP(IMAGE) ((IMAGE)->type == IBITMAP) -#define RGBP(IMAGE) ((IMAGE)->type == IRGB) - -#define depthToColors(n) DepthToColorsTable[((n) < 24 ? (n) : 24)] - /* - * Architecture independent memory to value conversions. - * Note the "Normal" internal format is big endian. + * architecture independent memory-to-value conversions + * note: the internal format is big endian */ #define memToVal(PTR,LEN) ( \ @@ -103,16 +88,6 @@ typedef struct { *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ *(((byte *)(PTR))+3) = ( VAL ) )) - -/* return values */ - -#define GIF_Success 0 -#define GIF_OpenFailed -1 -#define GIF_ReadFailed -2 -#define GIF_FileInvalid -3 -#define GIF_NoMemory -4 -#define GIF_ColorFailed -5 - #define PCX_Success 0 #define PCX_OpenFailed -1 #define PCX_ReadFailed -2 @@ -120,32 +95,11 @@ typedef struct { #define PCX_NoMemory -4 #define PCX_ColorFailed -5 -/* functions */ - -extern unsigned long DepthToColorsTable[]; -Image *newBitImage(); -Image *newRGBImage(); -void freeImage(); -void freeImageData(); -void newRGBMapData(); -void freeRGBMapData(); -byte *lcalloc(); -byte *lmalloc(); - -Image *Read_GIF_to_Image(); -Image *Read_PCX_to_Image(); - -int Read_GIF_to_Pixmaps(Display *, Window, char *, Pixmap *, Pixmap *); int Read_PCX_to_Pixmaps(Display *, Window, char *, Pixmap *, Pixmap *); -Image *monochrome(); -Image *zoom(); - -void compress(); - -Pixmap XImage_to_Pixmap(Display *, Window, XImageInfo *); -XImageInfo *Image_to_XImage(Display *, int, Visual *, unsigned int, Image *); -void XImage_to_Drawable(XImageInfo *, int, int, int, int, - unsigned int, unsigned int); +Image *Read_PCX_to_Image(); +Image *newImage(); +void freeImage(); +void freeXImage(); #endif /* IMAGE_H */ diff --git a/src/init.c b/src/init.c index e19daafd..184ea73f 100644 --- a/src/init.c +++ b/src/init.c @@ -25,9 +25,9 @@ #include "netserv.h" #ifdef DEBUG -/* + #define DEBUG_TIMING -*/ + #endif struct PictureFileInfo @@ -640,7 +640,7 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) char *picture_ext = ".xpm"; char *picturemask_ext = "Mask.xbm"; #else - int gif_err; + int pcx_err; char *picture_ext = ".pcx"; #endif @@ -693,30 +693,30 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) #else - gif_err = Read_PCX_to_Pixmaps(display, window, filename, + pcx_err = Read_PCX_to_Pixmaps(display, window, filename, &pix[pos], &clipmask[pos]); - switch(gif_err) + switch(pcx_err) { - case GIF_Success: + case PCX_Success: break; - case GIF_OpenFailed: - Error(ERR_EXIT, "cannot open GIF file '%s'", filename); - case GIF_ReadFailed: - Error(ERR_EXIT, "cannot read GIF file '%s'", filename); - case GIF_FileInvalid: - Error(ERR_EXIT, "invalid GIF file '%s'", filename); - case GIF_NoMemory: - Error(ERR_EXIT, "not enough memory for GIF file '%s'", filename); - case GIF_ColorFailed: - Error(ERR_EXIT, "cannot get colors for GIF file '%s'", filename); + case PCX_OpenFailed: + Error(ERR_EXIT, "cannot open PCX file '%s'", filename); + case PCX_ReadFailed: + Error(ERR_EXIT, "cannot read PCX file '%s'", filename); + case PCX_FileInvalid: + Error(ERR_EXIT, "invalid PCX file '%s'", filename); + case PCX_NoMemory: + Error(ERR_EXIT, "not enough memory for PCX file '%s'", filename); + case PCX_ColorFailed: + Error(ERR_EXIT, "cannot get colors for PCX file '%s'", filename); default: break; } #ifdef DEBUG_TIMING count2 = Counter(); - printf("GIF LOADING %s IN %.2f SECONDS\n", + printf("PCX LOADING %s IN %.2f SECONDS\n", filename,(float)(count2-count1)/1000.0); #endif diff --git a/src/pcx.c b/src/pcx.c index 582f4ce5..f2dac1d9 100644 --- a/src/pcx.c +++ b/src/pcx.c @@ -12,15 +12,17 @@ ***********************************************************/ #include "image.h" +#include "misc.h" -#define PCX_MAGIC 0x0a /* first byte in a PCX image file */ -#define PCX_LAST_VERSION 5 /* last acceptable version number */ -#define PCX_ENCODING 1 /* PCX encoding method */ +#define PCX_MAGIC 0x0a /* first byte in a PCX image file */ +#define PCX_LAST_VERSION 5 /* last acceptable version number */ +#define PCX_ENCODING 1 /* PCX encoding method */ #define PCX_256COLORS_MAGIC 0x0c /* first byte of a PCX 256 color map */ -#define PCX_MAXDEPTH 8 /* supports up to 8 bits per pixel */ -#define PCX_MAXCOLORS 256 /* maximum number of colors */ +#define PCX_MAXDEPTH 8 /* supports up to 8 bits per pixel */ +#define PCX_MAXCOLORS 256 /* maximum number of colors */ + #define PCX_HEADER_SIZE 128 -#define PCX_PALETTE_SIZE (3 * PCX_MAXCOLORS) +#define PCX_COLORMAP_SIZE (3 * PCX_MAXCOLORS) struct PCX_Header { @@ -42,48 +44,69 @@ struct PCX_Header unsigned char filler[58]; /* fill to struct size of 128 */ }; -static boolean PCX_LoadImage(); /* Routine to load PCX bitmap */ -static boolean PCX_LoadColormap(); /* Routine to load PCX colormap */ +static byte *PCX_ReadBitmap(Image *, byte *, byte *); +static byte *PCX_ReadColormap(Image *, byte *, byte *); Image *Read_PCX_to_Image(char *filename) { FILE *file; - unsigned char buffer[PCX_HEADER_SIZE]; + byte *file_buffer; + byte *buffer_ptr, *buffer_last; + unsigned int file_length; struct PCX_Header pcx; Image *image; int width, height, depth; + int i; if (!(file = fopen(filename, "r"))) return NULL; - /* read PCX header */ - if (fread(buffer, 1, PCX_HEADER_SIZE, file) != PCX_HEADER_SIZE) + if (fseek(file, 0, SEEK_END) == -1) { fclose(file); return NULL; } - pcx.signature = buffer[0]; - pcx.version = buffer[1]; - pcx.encoding = buffer[2]; - pcx.bits_per_pixel = buffer[3]; - pcx.xmin = buffer[4] + 256 * buffer[5]; - pcx.ymin = buffer[6] + 256 * buffer[7]; - pcx.xmax = buffer[8] + 256 * buffer[9]; - pcx.ymax = buffer[10] + 256 * buffer[11]; - pcx.color_planes = buffer[65]; - pcx.bytes_per_line = buffer[66] + 256 * buffer[67]; - pcx.palette_type = buffer[68] + 256 * buffer[69]; - - width = pcx.xmax - pcx.xmin + 1; + file_length = ftell(file); + rewind(file); + + if (file_length < PCX_HEADER_SIZE + PCX_COLORMAP_SIZE) + { + fclose(file); + return NULL; + } + + file_buffer = checked_malloc(file_length); + + if (fread(file_buffer, 1, file_length, file) != file_length) + { + fclose(file); + return NULL; + } + + fclose(file); + + pcx.signature = file_buffer[0]; + pcx.version = file_buffer[1]; + pcx.encoding = file_buffer[2]; + pcx.bits_per_pixel = file_buffer[3]; + pcx.xmin = file_buffer[4] + 256 * file_buffer[5]; + pcx.ymin = file_buffer[6] + 256 * file_buffer[7]; + pcx.xmax = file_buffer[8] + 256 * file_buffer[9]; + pcx.ymax = file_buffer[10] + 256 * file_buffer[11]; + pcx.color_planes = file_buffer[65]; + pcx.bytes_per_line = file_buffer[66] + 256 * file_buffer[67]; + pcx.palette_type = file_buffer[68] + 256 * file_buffer[69]; + + width = pcx.xmax - pcx.xmin + 1; height = pcx.ymax - pcx.ymin + 1; - depth = pcx.bits_per_pixel; + depth = pcx.bits_per_pixel; if (pcx.signature != PCX_MAGIC || pcx.version > PCX_LAST_VERSION || pcx.encoding != PCX_ENCODING || pcx.color_planes > PCX_MAXDEPTH || width < 0 || height < 0) { - fclose(file); + free(file_buffer); return NULL; } @@ -100,27 +123,42 @@ Image *Read_PCX_to_Image(char *filename) } /* allocate new image structure */ - image = newRGBImage(width, height, depth); + image = newImage(width, height, depth); + + buffer_ptr = file_buffer + PCX_HEADER_SIZE; + buffer_last = file_buffer + file_length; /* read compressed bitmap data */ - if (!PCX_LoadImage(file, image)) + if ((buffer_ptr = PCX_ReadBitmap(image, buffer_ptr, buffer_last)) == NULL) { - fclose(file); - return image; + free(file_buffer); + freeImage(image); + return NULL; } /* read colormap data */ - if (!PCX_LoadColormap(file, image)) + if (!PCX_ReadColormap(image, buffer_ptr, buffer_last)) { - fclose(file); - return image; + free(file_buffer); + freeImage(image); + return NULL; } - fclose(file); - return(image); + free(file_buffer); + + /* determine number of used colormap entries */ + image->rgb.used = 0; + for (i=0; irgb.color_used[i]) + image->rgb.used++; + + if (options.verbose) + printf("Read_PCX_to_Image: %d colors found\n", image->rgb.used); + + return image; } -static boolean PCX_LoadImage(FILE *file, Image *image) +static byte *PCX_ReadBitmap(Image *image, byte *buffer_ptr, byte *buffer_last) { /* Run Length Encoding: If the two high bits are set, * then the low 6 bits contain a repeat count, and the byte to @@ -128,60 +166,65 @@ static boolean PCX_LoadImage(FILE *file, Image *image) * not set, then this is the byte to write. */ - register unsigned char *ptr, *ptr_last; - int value, count; + unsigned int bytes_per_pixel = (image->depth + 7) / 8; + register byte *bitmap_ptr, *bitmap_last; + register byte value, count; - ptr = image->data; - ptr_last = ptr + (image->width * image->height * image->pixlen); + bitmap_ptr = image->data; + bitmap_last = bitmap_ptr + (image->width * image->height * bytes_per_pixel); - while (ptr < ptr_last) + while (bitmap_ptr < bitmap_last && buffer_ptr < buffer_last) { - if ((value = fgetc(file)) == EOF) - return FALSE; + value = *buffer_ptr++; - if ((value & 0xc0) == 0xc0) + if ((value & 0xc0) == 0xc0) /* this is a repeat count byte */ { - count = value & 0x3f; + count = value & 0x3f; /* extract repeat count from byte */ + value = *buffer_ptr++; /* next byte is value to repeat */ - if ((value = fgetc(file)) == EOF) - return FALSE; + for (; count && bitmap_ptr < bitmap_last; count--) + *bitmap_ptr++ = value; - for ( ; count && (ptr < ptr_last); count--) - *ptr++ = (unsigned char)value; - - if (count) - printf("Repeat count spans end of image!\n"); + if (count) /* repeat count spans end of bitmap */ + return NULL; } else - *ptr++ = (unsigned char)value; + *bitmap_ptr++ = value; + + image->rgb.color_used[value] = TRUE; } - return TRUE; + /* check if end of buffer was reached before end of bitmap */ + if (bitmap_ptr < bitmap_last) + return NULL; + + /* return current buffer position for next decoding function */ + return buffer_ptr; } -static boolean PCX_LoadColormap(FILE *file, Image *image) +static byte *PCX_ReadColormap(Image *image,byte *buffer_ptr, byte *buffer_last) { - unsigned char buffer[PCX_PALETTE_SIZE]; - int i, result, magic; + int i, magic; /* read colormap magic byte */ - if ((magic = fgetc(file)) == EOF) - return FALSE; + magic = *buffer_ptr++; + /* check magic colormap header byte */ if (magic != PCX_256COLORS_MAGIC) - return FALSE; + return NULL; - /* read PCX 256 colors colormap */ - if ((result = fread(buffer, 1, PCX_PALETTE_SIZE, file)) != PCX_PALETTE_SIZE) - return FALSE; + /* check if enough bytes left for a complete colormap */ + if (buffer_ptr + PCX_COLORMAP_SIZE > buffer_last) + return NULL; + /* read 256 colors from PCX colormap */ for (i=0; irgb.red[i] = buffer[i*3 + 0] << 8; - image->rgb.green[i] = buffer[i*3 + 1] << 8; - image->rgb.blue[i] = buffer[i*3 + 2] << 8; + image->rgb.red[i] = *buffer_ptr++ << 8; + image->rgb.green[i] = *buffer_ptr++ << 8; + image->rgb.blue[i] = *buffer_ptr++ << 8; } - image->rgb.used = PCX_MAXCOLORS; - return TRUE; + /* return current buffer position for next decoding function */ + return buffer_ptr; } -- 2.34.1