#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
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)
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];
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)
{
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)
{
bluecolors <<= 1;
}
- /* sanity check */
-
+ /* consistency check */
if (redcolors > visual->map_entries ||
greencolors > visual->map_entries ||
bluecolors > visual->map_entries)
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)))
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;
case PseudoColor:
ximageinfo->cmap = global_cmap;
- ximageinfo->index =
- (Pixel *)checked_malloc(sizeof(Pixel) * image->rgb.used);
-
-#if 0
- for (a=0; a<image->rgb.used; a++)
-#endif
for (a=0; a<MAX_COLORS; a++)
{
}
if (!color_found) /* no more free color cells */
- {
- printf("Sorry, cannot allocate enough colors!\n");
- exit(0);
- }
+ Error(ERR_EXIT, "cannot allocate enough color cells");
xcolor.pixel = xcolor2.pixel;
xcolor_private[xcolor.pixel] = xcolor;
count1 = Counter();
#endif
- /* CREATE IMAGE ITSELF */
- /* modify image data to match visual and colormap */
+ /* create XImage from internal image structure and convert it to Pixmap */
- dbits = bitsPerPixelAtDepth(display, screen, ddepth);/* bits per pixel */
- dpixlen = (dbits + 7) / 8; /* bytes per pixel */
+ bits_per_pixel = bitsPerPixelAtDepth(display, screen, depth);
+ bytes_per_pixel = (bits_per_pixel + 7) / 8;
- ximageinfo->ximage = 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)
{
{
Pixel pixval;
- for (y=0; y<image->height; y++)
+ for (y=0; y<image->height; y++) /* general case */
{
for (x=0; x<image->width; x++)
{
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;
case PseudoColor:
{
- if (dpixlen == 1) /* most common */
+ if (bytes_per_pixel == 1) /* (common) special case */
{
for (y=0; y<image->height; y++)
for (x=0; x<image->width; x++)
*dst_ptr++ = ximageinfo->index[c + *src_ptr++];
}
- else /* less common */
+ else /* general case */
{
for (y=0; y<image->height; y++)
{
for (x=0; x<image->width; 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;
}
}
}
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;
for (i=0; i<MAX_COLORS; i++)
image->rgb.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;
count1 = Counter();
#endif
+ /* read the graphic file in PCX format to image structure */
if ((image = Read_PCX_to_Image(filename)) == NULL)
return PCX_FileInvalid;
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
#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
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
#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 */