X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fimage.c;h=09a75fcee078a7eb6628042246a6acd67ecef6be;hp=85861dcc56ed6072c0ef3e6884b8eedcfa904530;hb=d4c11da68a7271553ca5591adfae54fd3b45011f;hpb=333896e44bae70515b2d82877dd14e7e28338977 diff --git a/src/image.c b/src/image.c index 85861dcc..09a75fce 100644 --- a/src/image.c +++ b/src/image.c @@ -1,442 +1,142 @@ - -/* image.c */ +/*********************************************************** +* Rocks'n'Diamonds -- McDuffin Strikes Back! * +*----------------------------------------------------------* +* (c) 1995-98 Artsoft Entertainment * +* Holger Schemel * +* Oststrasse 11a * +* 33604 Bielefeld * +* phone: ++49 +521 290471 * +* email: aeglos@valinor.owl.de * +*----------------------------------------------------------* +* image.c * +***********************************************************/ #include "image.h" +#include "pcx.h" #include "misc.h" -/* extra colors to try allocating in private color maps to minimise flashing */ -#define NOFLASH_COLORS 256 - -Image *monochrome(Image *cimage) -{ - 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; y < cimage->height; y++) - { - for (x= 0; x < cimage->width; 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; - } +/* exclude all except newImage() and freeImage() */ +#ifndef MSDOS - dp += dll; /* next row */ - } - - return(image); -} +/* extra colors to try allocating in private color maps to minimize flashing */ +#define NOFLASH_COLORS 256 -static unsigned int *buildIndex(unsigned int width, - unsigned int zoom, - unsigned int *rwidth) +/* 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) { - float fzoom; - unsigned int *index; - unsigned int a; - - if (!zoom) - { - 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); -} + byte *src_ptr, *dst_ptr, *dst_ptr2; + unsigned int bytes_per_row; + unsigned int x, y; + 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 = 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 + * the corresponding image pixmap + */ -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) + for (y=0; yheight; y++) { - case IBITMAP: - image= newBitImage(xwidth, ywidth); - for (x= 0; x < oimage->rgb.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 < ywidth; y++) - { - while (ysrc != *(yindex + y)) - { - ysrc++; - srcline += srclinelen; - } - srcptr= srcline; - destptr= destline; - srcmask= 0x80; - destmask= 0x80; - bit= srcmask & *srcptr; - for (x= 0, xsrc= *(xindex + x); x < xwidth; x++) - { - if (xsrc != *(xindex + x)) - { - do - { - xsrc++; - if (!(srcmask >>= 1)) - { - srcmask= 0x80; - srcptr++; - } - } - while (xsrc != *(xindex + x)); + bitmask = 0x01; /* 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; - - case IRGB: - image= newRGBImage(xwidth, ywidth, oimage->depth); - for (x= 0; x < oimage->rgb.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; - - pixlen= oimage->pixlen; - destptr= image->data; - srcline= oimage->data; - srclinelen= oimage->width * pixlen; - for (y= 0, ysrc= *(yindex + y); y < ywidth; y++) - { - while (ysrc != *(yindex + y)) - { - ysrc++; - srcline += srclinelen; - } - - srcptr = srcline; - value = memToVal(srcptr, image->pixlen); - - 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]) + for (x=0; xwidth; x++) { - unusedcount++; - continue; /* delete this index */ - } + if (*src_ptr++) /* source pixel solid? (pixel index != 0) */ + *dst_ptr2 |= bitmask; /* then write a bit into the image mask */ - /* 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 ((bitmask <<= 1) == 0) /* bit at rightmost byte position reached? */ { - if (r == red[y] && g == green[y] && b == blue[y]) - break; + bitmask = 0x01; /* start again with leftmost bit position */ + dst_ptr2++; /* continue with next byte in image mask */ } - 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++; - } - /* change the image pixels */ - pixptr = image->data; - pixend = pixptr + (image->height * image->width); - for(;pixptr < pixend; pixptr++) - *pixptr = map[(*pixptr) & dmask]; - - /* change the colormap */ - for (x = 0; x < image->rgb.used; x++) - { - if (!used[x]) - continue; - red[map[x]] = red[x]; - green[map[x]] = green[x]; - blue[map[x]] = blue[x]; + dst_ptr += bytes_per_row; /* continue with leftmost byte of next row */ } - image->rgb.used = next_index; - - /* clean up */ - free(map); - free(used); - + mask_pixmap = XCreateBitmapFromData(display, window, (char *)mask_data, + image->width, image->height); + free(mask_data); -#if 0 - if (badcount) - printf("%d out-of-range pixels, ", badcount); - - if (!unusedcount && !dupcount) - printf("no improvment\n"); - else - { - 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")); - } -#endif - - - - image->rgb.compressed= TRUE; /* don't do it again */ + return mask_pixmap; } - - - -Pixmap XImage_to_Pixmap(Display *disp, Window parent, XImageInfo *ximageinfo) +static int bitsPerPixelAtDepth(Display *display, int screen, int depth) { - Pixmap pixmap; - - pixmap = XCreatePixmap(disp, parent, - ximageinfo->ximage->width, ximageinfo->ximage->height, - ximageinfo->depth); + XPixmapFormatValues *pixmap_format; + int i, num_pixmap_formats, bits_per_pixel = -1; - ximageinfo->drawable = pixmap; + /* get Pixmap formats supported by the X server */ + pixmap_format = XListPixmapFormats(display, &num_pixmap_formats); - XImage_to_Drawable(ximageinfo, 0, 0, 0, 0, - ximageinfo->ximage->width, ximageinfo->ximage->height); - return(pixmap); -} + /* find format that matches the given depth */ + for (i=0; idisp = disp; - ximageinfo->scrn = scrn; - ximageinfo->depth = 0; - ximageinfo->drawable = None; - ximageinfo->index = NULL; - ximageinfo->rootimage = FALSE; - ximageinfo->foreground = ximageinfo->background= 0; - ximageinfo->gc = NULL; - ximageinfo->ximage = NULL; + ximageinfo = checked_malloc(sizeof(XImageInfo)); + ximageinfo->display = display; + ximageinfo->depth = depth; switch (visual->class) { @@ -458,8 +158,7 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, retry_direct: /* tag we hit if a DirectColor allocation fails on * default colormap */ - /* calculate number of distinct colors in each band - */ + /* calculate number of distinct colors in each band */ redcolors = greencolors = bluecolors = 1; for (pixval=1; pixval; pixval <<= 1) @@ -472,15 +171,11 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, bluecolors <<= 1; } - /* sanity check - */ - - if ((redcolors > visual->map_entries) || - (greencolors > visual->map_entries) || - (bluecolors > visual->map_entries)) - { - fprintf(stderr, "Warning: inconsistency in color information (this may be ugly)\n"); - } + /* consistency check */ + if (redcolors > visual->map_entries || + greencolors > visual->map_entries || + bluecolors > visual->map_entries) + Error(ERR_WARN, "inconsistency in color information"); redstep = 256 / redcolors; greenstep = 256 / greencolors; @@ -499,35 +194,32 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, xcolor.red = (redtop - 1) << 8; xcolor.green = (greentop - 1) << 8; xcolor.blue = (bluetop - 1) << 8; - if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) + 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(disp, scrn))) + (visual == DefaultVisual(display, screen))) { - global_cmap = XCopyColormapAndFree(disp, global_cmap); + global_cmap = XCopyColormapAndFree(display, global_cmap); ximageinfo->cmap = global_cmap; private_cmap = TRUE; 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; @@ -542,33 +234,33 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, case PseudoColor: ximageinfo->cmap = global_cmap; - ximageinfo->index = - (Pixel *)checked_malloc(sizeof(Pixel) * image->rgb.used); - for (a=0; argb.used; a++) + 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); /* look if this color already exists in our colormap */ - if (!XAllocColor(disp, ximageinfo->cmap, &xcolor)) + if (!XAllocColor(display, ximageinfo->cmap, &xcolor)) { 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 */ - global_cmap = XCopyColormapAndFree(disp, global_cmap); + global_cmap = XCopyColormapAndFree(display, global_cmap); ximageinfo->cmap = global_cmap; private_cmap = TRUE; @@ -576,7 +268,7 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, global_cmap_index = (Pixel *)checked_malloc(sizeof(Pixel) * NOFLASH_COLORS); for (i=0; icmap, &xcolor); + XStoreColor(display, ximageinfo->cmap, &xcolor); free_cmap_entries--; } @@ -664,148 +353,81 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, break; default: - printf("Sorry, only DirectColor, TrueColor and PseudoColor supported\n"); - exit(0); + Error(ERR_RETURN, "display class not supported"); + Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed"); 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; +#if DEBUG_TIMING + debug_print_timestamp(2, " ALLOCATING IMAGE COLORS: "); +#endif - /* we copy the data to be more consistent - */ + /* create XImage from internal image structure and convert it to Pixmap */ - linelen = ((image->width + 7) / 8); - data= checked_malloc(linelen * image->height); + bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth); + bytes_per_pixel = (bits_per_pixel + 7) / 8; - memcpy((char *)data, (char *)image->data, linelen * image->height); + 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; - gcv.function= GXcopy; - ximageinfo->ximage= XCreateImage(disp, visual, 1, XYBitmap, - 0, (char *)data, image->width, image->height, - 8, linelen); + src_ptr = image->data; + dst_ptr = (byte *)ximage->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++) /* general case */ { - Pixel pixval; - dbits= bitsPerPixelAtDepth(disp, scrn, 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(disp,scrn); - ximageinfo->background = WhitePixel(disp,scrn); + for (x=0; xwidth; x++) + { + pixval = *src_ptr++; + pixval = + redvalue[image->rgb.red[pixval] >> 8] | + greenvalue[image->rgb.green[pixval] >> 8] | + bluevalue[image->rgb.blue[pixval] >> 8]; + value_to_memory(pixval, dst_ptr, bytes_per_pixel); + dst_ptr += bytes_per_pixel; + } } - ximageinfo->ximage->bitmap_bit_order= MSBFirst; - ximageinfo->ximage->byte_order= MSBFirst; - break; } - case IRGB: + case PseudoColor: { - /* modify image data to match visual and colormap - */ - - byte *data, *destptr, *srcptr; - - dbits = bitsPerPixelAtDepth(disp, scrn, ddepth); /* bits per pixel */ - dpixlen = (dbits + 7) / 8; /* bytes per pixel */ - - ximageinfo->ximage = XCreateImage(disp, 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 (bytes_per_pixel == 1) /* (common) special case */ { - 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++) - { - *destptr = ximageinfo->index[c + *srcptr]; - srcptr++; - destptr++; - } - } - } - else /* less common */ + for (y=0; yheight; y++) + for (x=0; xwidth; x++) + *dst_ptr++ = ximageinfo->index[c + *src_ptr++]; + } + else /* general case */ + { + 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; - } - } + value_to_memory(ximageinfo->index[c + *src_ptr++], + dst_ptr, bytes_per_pixel); + dst_ptr += bytes_per_pixel; } } - break; } + break; } - } - /* - printf("done\n"); - */ + default: + Error(ERR_RETURN, "display class not supported"); + Error(ERR_EXIT, "DirectColor, TrueColor or PseudoColor display needed"); + break; + } if (redvalue) { @@ -814,161 +436,119 @@ XImageInfo *Image_to_XImage(Display *disp, int scrn, Visual *visual, free((byte *)bluevalue); } - return(ximageinfo); -} +#if DEBUG_TIMING + debug_print_timestamp(2, " CONVERTING IMAGE TO XIMAGE:"); +#endif -/* Given an XImage and a drawable, move a rectangle from the Ximage - * to the drawable. - */ + ximageinfo->pixmap = XCreatePixmap(display, window, + ximage->width, ximage->height, + ximageinfo->depth); -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; + XPutImage(ximageinfo->display, ximageinfo->pixmap, gc, + ximage, 0, 0, 0, 0, ximage->width, ximage->height); - /* build and cache the GC - */ - - if (!ximageinfo->gc) - { - gcv.function = GXcopy; - if (ximageinfo->ximage->depth == 1) - { - gcv.foreground = ximageinfo->foreground; - gcv.background = ximageinfo->background; - ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, - GCFunction | GCForeground | GCBackground, - &gcv); - } - else - ximageinfo->gc = XCreateGC(ximageinfo->disp, ximageinfo->drawable, - GCFunction, &gcv); - } + free(ximage->data); + ximage->data = NULL; + XDestroyImage(ximage); - XPutImage(ximageinfo->disp, 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. - */ - 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->disp, ximageinfo->cmap, ximageinfo->index, - ximageinfo->no, 0); - free(ximageinfo->index); - } - if (ximageinfo->gc) - XFreeGC(ximageinfo->disp, ximageinfo->gc); - free((byte *)ximageinfo->ximage->data); - ximageinfo->ximage->data= NULL; - XDestroyImage(ximageinfo->ximage); - free((byte *)ximageinfo); - /* should we free private color map to ??? */ -} - - - -/* this table is useful for quick conversions between depth and ncolors - */ + 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' + */ -unsigned long DepthToColorsTable[] = -{ - /* 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); + free(ximageinfo); } -void freeRGBMapData(RGBMap *rgb) -{ - free((byte *)rgb->red); - free((byte *)rgb->green); - free((byte *)rgb->blue); -} +#endif /* !MSDOS */ -Image *newBitImage(unsigned int width, unsigned int height) +Image *newImage(unsigned int width, unsigned int height, unsigned int depth) { - 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); -} + Image *image; + const unsigned int bytes_per_pixel = 1; + int i; -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); + if (depth > 8) + Error(ERR_EXIT, "images with more than 256 colors are not supported"); + + 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; + + return image; } -void freeImageData(Image *image) +void freeImage(Image *image) { - freeRGBMapData(&(image->rgb)); free(image->data); + free(image); } -void freeImage(Image *image) +#ifndef MSDOS + +int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename, + Pixmap *pixmap, Pixmap *pixmap_mask) { - freeImageData(image); - free((byte *)image); + Image *image; + XImageInfo *ximageinfo; + int screen; + Visual *visual; + int depth; + +#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; + +#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 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); + +#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); + +#if DEBUG_TIMING + debug_print_timestamp(2, " CONVERTING IMAGE TO MASK: "); +#endif + + *pixmap = ximageinfo->pixmap; + *pixmap_mask = ximageinfo->pixmap_mask; + + return(PCX_Success); } + +#endif /* !MSDOS */