From: Holger Schemel Date: Sat, 14 Nov 1998 02:29:06 +0000 (+0100) Subject: rnd-19981114-1 X-Git-Tag: 1.2.0^2~25 X-Git-Url: https://git.artsoft.org/?a=commitdiff_plain;h=40a487dcc5d3028343ff9123a72b8b3839a42861;p=rocksndiamonds.git rnd-19981114-1 --- diff --git a/src/image.c b/src/image.c index cfd42ace..675240d0 100644 --- a/src/image.c +++ b/src/image.c @@ -26,19 +26,38 @@ #endif -/* extra colors to try allocating in private color maps to minimise flashing */ +/* extra colors to try allocating in private color maps to minimize flashing */ #define NOFLASH_COLORS 256 -static void Image_to_Mask(Image *image) +/* architecture independent value-to-memory conversion + note: the internal format is big endian */ + +#define value_to_memory(value, ptr, length) ( \ +(length) == 1 ? (*( (byte *)(ptr) ) = ( value ) ) : \ +(length) == 2 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>> 8), \ + *(((byte *)(ptr))+1) = ( value ) ) : \ +(length) == 3 ? (*( (byte *)(ptr) ) = (((unsigned long)(value))>>16), \ + *(((byte *)(ptr))+1) = (((unsigned long)(value))>> 8), \ + *(((byte *)(ptr))+2) = ( value ) ) : \ + (*( (byte *)(ptr) ) = (((unsigned long)(value))>>24), \ + *(((byte *)(ptr))+1) = (((unsigned long)(value))>>16), \ + *(((byte *)(ptr))+2) = (((unsigned long)(value))>> 8), \ + *(((byte *)(ptr))+3) = ( value ) )) + +static Pixmap Image_to_Mask(Image *image, Display *display, Window window) { unsigned char *src_ptr, *dst_ptr, *dst_ptr2; unsigned int bytes_per_row; unsigned int x, y; unsigned char bitmask; + byte *mask_data; + Pixmap mask_pixmap; bytes_per_row = (image->width + 7) / 8; + mask_data = checked_calloc(bytes_per_row * image->height); + src_ptr = image->data; - dst_ptr = image->data_mask; + dst_ptr = mask_data; /* create bitmap data which can be used by 'XCreateBitmapFromData()' * directly to create a pixmap of depth 1 for use as a clip mask for @@ -64,43 +83,16 @@ static void Image_to_Mask(Image *image) dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */ } -} - -static boolean XImage_to_Pixmap(Display *display, Window parent, - XImageInfo *ximageinfo, Image *image) -{ - ximageinfo->pixmap = XCreatePixmap(display, parent, - ximageinfo->ximage->width, - ximageinfo->ximage->height, - ximageinfo->depth); - - /* build and cache the GC */ - - if (!ximageinfo->gc) - { - XGCValues gcv; - - gcv.function = GXcopy; - ximageinfo->gc = XCreateGC(ximageinfo->display, ximageinfo->pixmap, - GCFunction, &gcv); - } - XPutImage(ximageinfo->display, ximageinfo->pixmap, ximageinfo->gc, - ximageinfo->ximage, 0, 0, 0, 0, - ximageinfo->ximage->width, ximageinfo->ximage->height); + mask_pixmap = XCreateBitmapFromData(display, window, mask_data, + image->width, image->height); + free(mask_data); - ximageinfo->pixmap_mask = XCreateBitmapFromData(ximageinfo->display, - parent, - image->data_mask, - image->width, - image->height); - - return (ximageinfo->pixmap != None && ximageinfo->pixmap_mask != None); + return mask_pixmap; } /* find the best pixmap depth supported by the server for a particular - * visual and return that depth. - */ + visual and return that depth */ static unsigned int bitsPerPixelAtDepth(Display *display, int screen, unsigned int depth) @@ -122,13 +114,13 @@ static unsigned int bitsPerPixelAtDepth(Display *display, int screen, XFree(xf); /* this should never happen; if it does, we're in trouble */ - - fprintf(stderr, "bitsPerPixelAtDepth: Can't find pixmap depth info!\n"); - exit(1); + Error(ERR_EXIT, "bitsPerPixelAtDepth: can't find pixmap depth info"); + return 0; /* never reached -- just to make gcc happy */ } -XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, - unsigned int ddepth, Image *image) +XImageInfo *Image_to_Pixmap(Display *display, int screen, Visual *visual, + Window window, GC gc, + unsigned int depth, Image *image) { static XColor xcolor_private[NOFLASH_COLORS]; static int colorcell_used[NOFLASH_COLORS]; @@ -137,12 +129,11 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, static int num_cmap_entries, free_cmap_entries; static boolean private_cmap = FALSE; Pixel *redvalue, *greenvalue, *bluevalue; - unsigned int a, c = 0, x, y, dpixlen, dbits; + unsigned int a, c = 0, x, y, bytes_per_pixel, bits_per_pixel; XColor xcolor; + XImage *ximage; XImageInfo *ximageinfo; - - /* for building image */ - byte *data, *src_ptr, *dst_ptr; + byte *src_ptr, *dst_ptr; if (!global_cmap) { @@ -151,22 +142,17 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, else { global_cmap = XCreateColormap(display, RootWindow(display, screen), - visual, AllocNone); + visual, AllocNone); private_cmap = TRUE; } } xcolor.flags = DoRed | DoGreen | DoBlue; redvalue = greenvalue = bluevalue = NULL; - ximageinfo = (XImageInfo *)checked_malloc(sizeof(XImageInfo)); + ximageinfo = checked_malloc(sizeof(XImageInfo)); ximageinfo->display = display; ximageinfo->screen = screen; - ximageinfo->depth = 0; - ximageinfo->drawable = None; - ximageinfo->index = NULL; - ximageinfo->rootimage = FALSE; - ximageinfo->gc = NULL; - ximageinfo->ximage = NULL; + ximageinfo->depth = depth; switch (visual->class) { @@ -201,8 +187,7 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, bluecolors <<= 1; } - /* sanity check */ - + /* consistency check */ if (redcolors > visual->map_entries || greencolors > visual->map_entries || bluecolors > visual->map_entries) @@ -228,8 +213,7 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, if (!XAllocColor(display, ximageinfo->cmap, &xcolor)) { /* if an allocation fails for a DirectColor default visual then - * we should create a private colormap and try again. - */ + we should create a private colormap and try again. */ if ((visual->class == DirectColor) && (visual == DefaultVisual(display, screen))) @@ -241,19 +225,17 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, goto retry_direct; } - /* something completely unexpected happened - */ + /* something completely unexpected happened */ fprintf(stderr, "imageToXImage: XAllocColor failed on a TrueColor/Directcolor visual\n"); - free((byte *)redvalue); - free((byte *)greenvalue); - free((byte *)bluevalue); - free((byte *)ximageinfo); - return(NULL); + free(redvalue); + free(greenvalue); + free(bluevalue); + free(ximageinfo); + return NULL; } - /* fill in pixel values for each band at this intensity - */ + /* fill in pixel values for each band at this intensity */ while ((redbottom < 256) && (redbottom < redtop)) redvalue[redbottom++] = xcolor.pixel & visual->red_mask; @@ -268,12 +250,6 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, case PseudoColor: ximageinfo->cmap = global_cmap; - ximageinfo->index = - (Pixel *)checked_malloc(sizeof(Pixel) * image->rgb.used); - -#if 0 - for (a=0; argb.used; a++) -#endif for (a=0; aximage = XCreateImage(display, visual, ddepth, ZPixmap, 0, - NULL, image->width, image->height, - 8, image->width * dpixlen); + ximage = XCreateImage(display, visual, depth, ZPixmap, 0, + NULL, image->width, image->height, + 8, image->width * bytes_per_pixel); + ximage->data = + checked_malloc(image->width * image->height * bytes_per_pixel); + ximage->byte_order = MSBFirst; - data = checked_malloc(image->width * image->height * dpixlen); - ximageinfo->depth = ddepth; - ximageinfo->ximage->data = (char *)data; - ximageinfo->ximage->byte_order = MSBFirst; src_ptr = image->data; - dst_ptr = data; + dst_ptr = ximage->data; switch (visual->class) { @@ -432,7 +403,7 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, { Pixel pixval; - for (y=0; yheight; y++) + for (y=0; yheight; y++) /* general case */ { for (x=0; xwidth; x++) { @@ -441,8 +412,8 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, redvalue[image->rgb.red[pixval] >> 8] | greenvalue[image->rgb.green[pixval] >> 8] | bluevalue[image->rgb.blue[pixval] >> 8]; - valToMem(pixval, dst_ptr, dpixlen); - dst_ptr += dpixlen; + value_to_memory(pixval, dst_ptr, bytes_per_pixel); + dst_ptr += bytes_per_pixel; } } break; @@ -450,20 +421,21 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, case PseudoColor: { - if (dpixlen == 1) /* most common */ + if (bytes_per_pixel == 1) /* (common) special case */ { for (y=0; yheight; y++) for (x=0; xwidth; x++) *dst_ptr++ = ximageinfo->index[c + *src_ptr++]; } - else /* less common */ + else /* general case */ { for (y=0; yheight; y++) { for (x=0; xwidth; x++) { - valToMem(ximageinfo->index[c + *src_ptr++], dst_ptr, dpixlen); - dst_ptr += dpixlen; + value_to_memory(ximageinfo->index[c + *src_ptr++], + dst_ptr, bytes_per_pixel); + dst_ptr += bytes_per_pixel; } } } @@ -483,34 +455,43 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, free((byte *)bluevalue); } +#ifdef DEBUG_TIMING + count2 = Counter(); + printf(" CONVERTING IMAGE TO XIMAGE IN %.2f SECONDS\n", + (float)(count2-count1)/1000.0); + count1 = Counter(); +#endif + + ximageinfo->pixmap = XCreatePixmap(display, window, + ximage->width, ximage->height, + ximageinfo->depth); + + XPutImage(ximageinfo->display, ximageinfo->pixmap, gc, + ximage, 0, 0, 0, 0, ximage->width, ximage->height); + + free(ximage->data); + ximage->data = NULL; + XDestroyImage(ximage); + return(ximageinfo); } -/* free up anything cached in the local Ximage structure. - */ - void freeXImage(Image *image, XImageInfo *ximageinfo) { - if (ximageinfo->index != NULL) /* if we allocated colors */ - { - if (ximageinfo->no > 0 && !ximageinfo->rootimage) /* don't free root colors */ - XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index, - ximageinfo->no, 0); - free(ximageinfo->index); - } - if (ximageinfo->gc) - XFreeGC(ximageinfo->display, ximageinfo->gc); - free((byte *)ximageinfo->ximage->data); - ximageinfo->ximage->data= NULL; - XDestroyImage(ximageinfo->ximage); - free((byte *)ximageinfo); - /* should we free private color map to ??? */ + if (ximageinfo->index != NULL && ximageinfo->no > 0) + XFreeColors(ximageinfo->display, ximageinfo->cmap, ximageinfo->index, + ximageinfo->no, 0); + /* this ^^^^^^^^^^^^^^ is wrong, because the used color cells + * are somewhere between 0 and MAX_COLORS; there are indeed 'ximageinfo->no' + * used color cells, but they are not at array position 0 - 'ximageinfo->no' + */ + + free(ximageinfo); } Image *newImage(unsigned int width, unsigned int height, unsigned int depth) { Image *image; - unsigned int bytes_per_row; const unsigned int bytes_per_pixel = 1; int i; @@ -527,34 +508,20 @@ Image *newImage(unsigned int width, unsigned int height, unsigned int depth) for (i=0; irgb.color_used[i] = FALSE; - bytes_per_row = (width + 7) / 8; - image->data_mask = checked_calloc(bytes_per_row * height); - return image; } void freeImage(Image *image) { free(image->data); - free(image->data_mask); free(image); } -/* ------------------------------------------------------------------------- */ - - - -int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, +int Read_PCX_to_Pixmaps(Display *display, Window window, GC gc, 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; @@ -563,6 +530,7 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, count1 = Counter(); #endif + /* read the graphic file in PCX format to image structure */ if ((image = Read_PCX_to_Image(filename)) == NULL) return PCX_FileInvalid; @@ -573,47 +541,32 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, count1 = Counter(); #endif - /* create image mask */ - Image_to_Mask(image); - -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" CONVERTING IMAGE TO MASK IN %.2f SECONDS\n", - (float)(count2-count1)/1000.0); - count1 = Counter(); -#endif - screen = DefaultScreen(display); visual = DefaultVisual(display, screen); depth = DefaultDepth(display, screen); - /* convert internal image structure to X11 XImage */ - if (!(ximageinfo = Image_to_XImage(display, screen, visual, depth, image))) - { - fprintf(stderr, "Cannot convert Image to XImage.\n"); - exit(1); - } + /* convert image structure to X11 Pixmap */ + if (!(ximageinfo = Image_to_Pixmap(display, screen, visual, + window, gc, depth, image))) + Error(ERR_EXIT, "cannot convert Image to Pixmap"); + + /* if a private colormap has been created, install it */ + if (ximageinfo->cmap != DefaultColormap(display, screen)) + XSetWindowColormap(display, window, ximageinfo->cmap); #ifdef DEBUG_TIMING count2 = Counter(); - printf(" CONVERTING IMAGE TO XIMAGE IN %.2f SECONDS\n", + printf(" CONVERTING IMAGE TO PIXMAP IN %.2f SECONDS\n", (float)(count2-count1)/1000.0); count1 = Counter(); #endif - if (ximageinfo->cmap != DefaultColormap(display, screen)) - XSetWindowColormap(display, window, ximageinfo->cmap); - - /* convert XImage to Pixmap */ - if (!(XImage_to_Pixmap(display, window, ximageinfo, image))) - { - fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); - exit(1); - } + /* create clip mask for the image */ + ximageinfo->pixmap_mask = Image_to_Mask(image, display, window); #ifdef DEBUG_TIMING count2 = Counter(); - printf(" CONVERTING IMAGE TO PIXMAP IN %.2f SECONDS\n", + printf(" CONVERTING IMAGE TO MASK IN %.2f SECONDS\n", (float)(count2-count1)/1000.0); count1 = Counter(); #endif diff --git a/src/image.h b/src/image.h index b1d033ac..50335eea 100644 --- a/src/image.h +++ b/src/image.h @@ -18,22 +18,18 @@ #define MAX_COLORS 256 /* maximal number of colors for each image */ -typedef unsigned short Intensity; /* what X thinks an RGB intensity is */ +typedef unsigned short Intensity; /* RGB intensity for X11 */ 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 */ - Colormap cmap; /* colormap used for image */ - GC gc; /* cached gc for sending image */ - XImage *ximage; /* ximage structure */ - Pixmap pixmap; /* final pixmap */ - Pixmap pixmap_mask; /* final pixmap of mask */ + Display *display; /* destination display */ + int screen; /* destination screen */ + int depth; /* depth of destination drawable */ + Pixel index[MAX_COLORS]; /* array of pixel values */ + int no; /* number of pixels in the array */ + Colormap cmap; /* colormap used for image */ + Pixmap pixmap; /* final pixmap */ + Pixmap pixmap_mask; /* final pixmap of mask */ } XImageInfo; struct RGBMap @@ -52,38 +48,8 @@ typedef struct 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; -/* - * architecture independent memory-to-value conversions - * note: the internal format is big endian - */ - -#define memToVal(PTR,LEN) ( \ -(LEN) == 1 ? (unsigned long)( *( (byte *)(PTR)) ) : \ -(LEN) == 2 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<< 8) \ - + ( *(((byte *)(PTR))+1) ) : \ -(LEN) == 3 ? (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<16) \ - + (((unsigned long)(*(((byte *)(PTR))+1)))<< 8) \ - + ( *(((byte *)(PTR))+2) ) : \ - (unsigned long)(((unsigned long)(*( (byte *)(PTR)) ))<<24) \ - + (((unsigned long)(*(((byte *)(PTR))+1)))<<16) \ - + (((unsigned long)(*(((byte *)(PTR))+2)))<< 8) \ - + ( *(((byte *)(PTR))+3) ) ) - -#define valToMem(VAL,PTR,LEN) ( \ -(LEN) == 1 ? (*( (byte *)(PTR) ) = ( VAL ) ) : \ -(LEN) == 2 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+1) = ( VAL ) ) : \ -(LEN) == 3 ? (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>16), \ - *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+2) = ( VAL ) ) : \ - (*( (byte *)(PTR) ) = (((unsigned long)(VAL))>>24), \ - *(((byte *)(PTR))+1) = (((unsigned long)(VAL))>>16), \ - *(((byte *)(PTR))+2) = (((unsigned long)(VAL))>> 8), \ - *(((byte *)(PTR))+3) = ( VAL ) )) - #define PCX_Success 0 #define PCX_OpenFailed -1 #define PCX_ReadFailed -2 @@ -91,11 +57,11 @@ typedef struct #define PCX_NoMemory -4 #define PCX_ColorFailed -5 -int Read_PCX_to_Pixmaps(Display *, Window, char *, Pixmap *, Pixmap *); +int Read_PCX_to_Pixmaps(Display *, Window, GC, char *, Pixmap *, Pixmap *); -Image *Read_PCX_to_Image(); -Image *newImage(); -void freeImage(); -void freeXImage(); +Image *Read_PCX_to_Image(char *); +Image *newImage(unsigned int, unsigned int, unsigned int); +void freeImage(Image *); +void freeXImage(Image *, XImageInfo *); #endif /* IMAGE_H */ diff --git a/src/init.c b/src/init.c index 184ea73f..37c0a1fe 100644 --- a/src/init.c +++ b/src/init.c @@ -693,7 +693,7 @@ void LoadGfx(int pos, struct PictureFileInfo *pic) #else - pcx_err = Read_PCX_to_Pixmaps(display, window, filename, + pcx_err = Read_PCX_to_Pixmaps(display, window, gc, filename, &pix[pos], &clipmask[pos]); switch(pcx_err)