X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fimage.c;h=09a75fcee078a7eb6628042246a6acd67ecef6be;hp=cfd42ace044d963f89bacc1f2d5efbad8134125e;hb=3ae3dff29ac1a6022b1e5af414ba2c99391148c8;hpb=2f9311c5cfa019e40c127df71e25659b641986d3 diff --git a/src/image.c b/src/image.c index cfd42ace..09a75fce 100644 --- a/src/image.c +++ b/src/image.c @@ -12,33 +12,44 @@ ***********************************************************/ #include "image.h" +#include "pcx.h" #include "misc.h" +/* exclude all except newImage() and freeImage() */ +#ifndef MSDOS -#ifdef DEBUG - -#define DEBUG_TIMING - -#endif - -#ifdef DEBUG_TIMING - long count1, count2; -#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; + byte *src_ptr, *dst_ptr, *dst_ptr2; unsigned int bytes_per_row; unsigned int x, y; - unsigned char bitmask; + byte 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,71 +75,37 @@ 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); - } + mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data, + image->width, image->height); + free(mask_data); - XPutImage(ximageinfo->display, ximageinfo->pixmap, ximageinfo->gc, - ximageinfo->ximage, 0, 0, 0, 0, - ximageinfo->ximage->width, ximageinfo->ximage->height); - - 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. - */ - -static unsigned int bitsPerPixelAtDepth(Display *display, int screen, - unsigned int depth) +static int bitsPerPixelAtDepth(Display *display, int screen, int depth) { - XPixmapFormatValues *xf; - int nxf, a; + XPixmapFormatValues *pixmap_format; + int i, num_pixmap_formats, bits_per_pixel = -1; - xf = XListPixmapFormats(display, &nxf); - for (a = 0; a < nxf; a++) - { - if (xf[a].depth == depth) - { - int bpp; - bpp = xf[a].bits_per_pixel; - XFree(xf); - return (unsigned int) bpp; - } - } - XFree(xf); + /* get Pixmap formats supported by the X server */ + pixmap_format = XListPixmapFormats(display, &num_pixmap_formats); + + /* find format that matches the given depth */ + for (i=0; idisplay = 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 +171,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 +197,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 +209,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 +234,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 = (byte *)ximage->data; switch (visual->class) { @@ -432,7 +384,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 +393,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 +402,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; } } } @@ -471,7 +424,7 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, } default: - Error(ERR_RETURN, "display type not supported"); + Error(ERR_RETURN, "display class not supported"); Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed"); break; } @@ -483,34 +436,42 @@ XImageInfo *Image_to_XImage(Display *display, int screen, Visual *visual, free((byte *)bluevalue); } +#if DEBUG_TIMING + debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:"); +#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); } +#endif /* !MSDOS */ + 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,95 +488,61 @@ 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); } -/* ------------------------------------------------------------------------- */ - +#ifndef MSDOS - -int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, - Pixmap *pixmap, Pixmap *pixmap_mask) +int Read_PCX_to_Pixmap(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; + int depth; -#ifdef DEBUG_TIMING - count1 = Counter(); +#if DEBUG_TIMING + debug_print_timestamp(2, NULL); /* initialize timestamp function */ #endif + /* read the graphic file in PCX format to image structure */ if ((image = Read_PCX_to_Image(filename)) == NULL) return PCX_FileInvalid; -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" LOADING '%s' IN %.2f SECONDS\n", - filename, (float)(count2-count1)/1000.0); - 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(); +#if DEBUG_TIMING + printf("%s:\n", filename); + debug_print_timestamp(2, " READING PCX FILE TO IMAGE: "); #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); - } - -#ifdef DEBUG_TIMING - count2 = Counter(); - printf(" CONVERTING IMAGE TO XIMAGE IN %.2f SECONDS\n", - (float)(count2-count1)/1000.0); - count1 = Counter(); -#endif + /* 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); - /* convert XImage to Pixmap */ - if (!(XImage_to_Pixmap(display, window, ximageinfo, image))) - { - fprintf(stderr, "Cannot convert XImage to Pixmap.\n"); - exit(1); - } +#if DEBUG_TIMING + debug_print_timestamp(2, " CONVERTING IMAGE TO PIXMAP:"); +#endif + + /* 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", - (float)(count2-count1)/1000.0); - count1 = Counter(); +#if DEBUG_TIMING + debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: "); #endif *pixmap = ximageinfo->pixmap; @@ -623,3 +550,5 @@ int Read_PCX_to_Pixmaps(Display *display, Window window, char *filename, return(PCX_Success); } + +#endif /* !MSDOS */