ImUtil.c revision cbfda780
1/*
2
3Copyright 1986, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25*/
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#include <X11/Xlibint.h>
31#include <X11/Xutil.h>
32#include <stdio.h>
33#include <limits.h>
34#include "ImUtil.h"
35
36static int _XDestroyImage(XImage *);
37static unsigned long _XGetPixel(XImage *, int, int);
38static unsigned long _XGetPixel1(XImage *, int, int);
39static unsigned long _XGetPixel8(XImage *, int, int);
40static unsigned long _XGetPixel16(XImage *, int, int);
41static unsigned long _XGetPixel32(XImage *, int, int);
42static int _XPutPixel(XImage *, int, int, unsigned long);
43static int _XPutPixel1(XImage *, int, int, unsigned long);
44static int _XPutPixel8(XImage *, int, int, unsigned long);
45static int _XPutPixel16(XImage *, int, int, unsigned long);
46static int _XPutPixel32(XImage *, int, int, unsigned long);
47static XImage *_XSubImage(XImage *, int, int, unsigned int, unsigned int);
48static int _XAddPixel(XImage *, long);
49
50static unsigned char const _lomask[0x09] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
51static unsigned char const _himask[0x09] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 };
52
53/* These two convenience routines return the scanline_pad and bits_per_pixel
54	associated with a specific depth of ZPixmap format image for a
55	display. */
56
57int
58_XGetScanlinePad(
59 Display *dpy,
60 int depth)
61 {
62 	register ScreenFormat *fmt = dpy->pixmap_format;
63 	register int i;
64
65 	for (i = dpy->nformats + 1; --i; ++fmt)
66 		if (fmt->depth == depth)
67 			return(fmt->scanline_pad);
68
69 	return(dpy->bitmap_pad);
70 }
71
72int
73_XGetBitsPerPixel(
74 Display *dpy,
75 int depth)
76 {
77 	register ScreenFormat *fmt = dpy->pixmap_format;
78 	register int i;
79
80 	for (i = dpy->nformats + 1; --i; ++fmt)
81 		if (fmt->depth == depth)
82 			return(fmt->bits_per_pixel);
83	if (depth <= 4)
84	    return 4;
85	if (depth <= 8)
86	    return 8;
87	if (depth <= 16)
88	    return 16;
89	return 32;
90 }
91
92
93/*
94 * This module provides rudimentary manipulation routines for image data
95 * structures.  The functions provided are:
96 *
97 *	XCreateImage	Creates a default XImage data structure
98 *	_XDestroyImage	Deletes an XImage data structure
99 *	_XGetPixel	Reads a pixel from an image data structure
100 *	_XGetPixel32	Reads a pixel from a 32-bit Z image data structure
101 *	_XGetPixel16	Reads a pixel from a 16-bit Z image data structure
102 *	_XGetPixel8	Reads a pixel from an 8-bit Z image data structure
103 *	_XGetPixel1	Reads a pixel from an 1-bit image data structure
104 *	_XPutPixel	Writes a pixel into an image data structure
105 *	_XPutPixel32	Writes a pixel into a 32-bit Z image data structure
106 *	_XPutPixel16	Writes a pixel into a 16-bit Z image data structure
107 *	_XPutPixel8	Writes a pixel into an 8-bit Z image data structure
108 *	_XPutPixel1	Writes a pixel into an 1-bit image data structure
109 *	_XSubImage	Clones a new (sub)image from an existing one
110 *	_XSetImage	Writes an image data pattern into another image
111 *	_XAddPixel	Adds a constant value to every pixel in an image
112 *
113 * The logic contained in these routines makes several assumptions about
114 * the image data structures, and at least for current implementations
115 * these assumptions are believed to be true.  They are:
116 *
117 *	For all formats, bits_per_pixel is less than or equal to 32.
118 *	For XY formats, bitmap_unit is always less than or equal to bitmap_pad.
119 *	For XY formats, bitmap_unit is 8, 16, or 32 bits.
120 *	For Z format, bits_per_pixel is 1, 4, 8, 16, 24, or 32 bits.
121 */
122static void _xynormalizeimagebits (
123    register unsigned char *bp,
124    register XImage *img)
125{
126	register unsigned char c;
127
128	if (img->byte_order != img->bitmap_bit_order) {
129	    switch (img->bitmap_unit) {
130
131		case 16:
132		    c = *bp;
133		    *bp = *(bp + 1);
134		    *(bp + 1) = c;
135		    break;
136
137		case 32:
138		    c = *(bp + 3);
139		    *(bp + 3) = *bp;
140		    *bp = c;
141		    c = *(bp + 2);
142		    *(bp + 2) = *(bp + 1);
143		    *(bp + 1) = c;
144		    break;
145	    }
146	}
147	if (img->bitmap_bit_order == MSBFirst)
148	    _XReverse_Bytes (bp, img->bitmap_unit >> 3);
149}
150
151static void _znormalizeimagebits (
152    register unsigned char *bp,
153    register XImage *img)
154{
155	register unsigned char c;
156	switch (img->bits_per_pixel) {
157
158	    case 4:
159		*bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
160		break;
161
162	    case 16:
163		c = *bp;
164		*bp = *(bp + 1);
165		*(bp + 1) = c;
166		break;
167
168	    case 24:
169		c = *(bp + 2);
170		*(bp + 2) = *bp;
171		*bp = c;
172		break;
173
174	    case 32:
175		c = *(bp + 3);
176		*(bp + 3) = *bp;
177		*bp = c;
178		c = *(bp + 2);
179		*(bp + 2) = *(bp + 1);
180		*(bp + 1) = c;
181		break;
182	}
183}
184
185static void _putbits(
186    register char *src,	/* address of source bit string */
187    int dstoffset,	/* bit offset into destination; range is 0-31 */
188    register int numbits,/* number of bits to copy to destination */
189    register char *dst)	/* address of destination bit string */
190{
191	register unsigned char chlo, chhi;
192	int hibits;
193	dst = dst + (dstoffset >> 3);
194	dstoffset = dstoffset & 7;
195	hibits = 8 - dstoffset;
196	chlo = *dst & _lomask[dstoffset];
197	for (;;) {
198	    chhi = (*src << dstoffset) & _himask[dstoffset];
199	    if (numbits <= hibits) {
200		chhi = chhi & _lomask[dstoffset + numbits];
201		*dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
202		break;
203	    }
204	    *dst = chhi | chlo;
205	    dst++;
206	    numbits = numbits - hibits;
207	    chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
208	    src++;
209	    if (numbits <= dstoffset) {
210		chlo = chlo & _lomask[numbits];
211		*dst = (*dst & _himask[numbits]) | chlo;
212		break;
213	    }
214	    numbits = numbits - dstoffset;
215	}
216}
217
218
219/*
220 * Macros
221 *
222 * The ROUNDUP macro rounds up a quantity to the specified boundary,
223 * then truncates to bytes.
224 *
225 * The XYNORMALIZE macro determines whether XY format data requires
226 * normalization and calls a routine to do so if needed. The logic in
227 * this module is designed for LSBFirst byte and bit order, so
228 * normalization is done as required to present the data in this order.
229 *
230 * The ZNORMALIZE macro performs byte and nibble order normalization if
231 * required for Z format data.
232 *
233 * The XYINDEX macro computes the index to the starting byte (char) boundary
234 * for a bitmap_unit containing a pixel with coordinates x and y for image
235 * data in XY format.
236 *
237 * The ZINDEX macro computes the index to the starting byte (char) boundary
238 * for a pixel with coordinates x and y for image data in ZPixmap format.
239 *
240 */
241
242#if defined(Lynx) && defined(ROUNDUP)
243#undef ROUNDUP
244#endif
245
246#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3))
247
248#define XYNORMALIZE(bp, img) \
249    if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \
250	_xynormalizeimagebits((unsigned char *)(bp), img)
251
252#define ZNORMALIZE(bp, img) \
253    if (img->byte_order == MSBFirst) \
254	_znormalizeimagebits((unsigned char *)(bp), img)
255
256#define XYINDEX(x, y, img) \
257    ((y) * img->bytes_per_line) + \
258    (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3)
259
260#define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \
261    (((x) * img->bits_per_pixel) >> 3)
262
263/*
264 * This routine initializes the image object function pointers.  The
265 * intent is to provide native (i.e. fast) routines for native format images
266 * only using the generic (i.e. slow) routines when fast ones don't exist.
267 * However, with the current rather botched external interface, clients may
268 * have to mung image attributes after the image gets created, so the fast
269 * routines always have to check to make sure the optimization is still
270 * valid, and reinit the functions if not.
271 */
272void _XInitImageFuncPtrs (
273    XImage *image)
274{
275	image->f.create_image = XCreateImage;
276	image->f.destroy_image = _XDestroyImage;
277	if ((image->format == ZPixmap) && (image->bits_per_pixel == 8)) {
278	    image->f.get_pixel = _XGetPixel8;
279	    image->f.put_pixel = _XPutPixel8;
280	} else if (((image->bits_per_pixel | image->depth) == 1) &&
281		   (image->byte_order == image->bitmap_bit_order)) {
282	    image->f.get_pixel = _XGetPixel1;
283	    image->f.put_pixel = _XPutPixel1;
284	} else if ((image->format == ZPixmap) &&
285		   (image->bits_per_pixel == 32)) {
286	    image->f.get_pixel = _XGetPixel32;
287	    image->f.put_pixel = _XPutPixel32;
288	} else if ((image->format == ZPixmap) &&
289		   (image->bits_per_pixel == 16)) {
290	    image->f.get_pixel = _XGetPixel16;
291	    image->f.put_pixel = _XPutPixel16;
292	} else {
293	    image->f.get_pixel = _XGetPixel;
294	    image->f.put_pixel = _XPutPixel;
295	}
296	image->f.sub_image = _XSubImage;
297/*	image->f.set_image = _XSetImage;*/
298	image->f.add_pixel = _XAddPixel;
299}
300
301/*
302 * CreateImage
303 *
304 * Allocates the memory necessary for an XImage data structure.
305 * Initializes the structure with "default" values and returns XImage.
306 *
307 */
308
309XImage *XCreateImage (
310    register Display *dpy,
311    register Visual *visual,
312    unsigned int depth,
313    int format,
314    int offset, /*How many pixels from the start of the data does the
315		picture to be transmitted start?*/
316
317    char *data,
318    unsigned int width,
319    unsigned int height,
320    int xpad,
321    int image_bytes_per_line)
322		/*How many bytes between a pixel on one line and the pixel with
323		  the same X coordinate on the next line? 0 means
324		  XCreateImage can calculate it.*/
325{
326	register XImage *image;
327	int bits_per_pixel = 1;
328	int min_bytes_per_line;
329
330	if (depth == 0 || depth > 32 ||
331	    (format != XYBitmap && format != XYPixmap && format != ZPixmap) ||
332	    (format == XYBitmap && depth != 1) ||
333	    (xpad != 8 && xpad != 16 && xpad != 32) ||
334	    offset < 0)
335	    return (XImage *) NULL;
336	if ((image = Xcalloc(1, sizeof(XImage))) == NULL)
337	    return (XImage *) NULL;
338
339	image->width = width;
340	image->height = height;
341	image->format = format;
342	image->byte_order = dpy->byte_order;
343	image->bitmap_unit = dpy->bitmap_unit;
344	image->bitmap_bit_order = dpy->bitmap_bit_order;
345	if (visual != NULL) {
346		image->red_mask = visual->red_mask;
347		image->green_mask = visual->green_mask;
348		image->blue_mask = visual->blue_mask;
349	}
350	else {
351		image->red_mask = image->green_mask = image->blue_mask = 0;
352	}
353	if (format == ZPixmap)
354	{
355	    bits_per_pixel = _XGetBitsPerPixel(dpy, (int) depth);
356	}
357
358	image->xoffset = offset;
359	image->bitmap_pad = xpad;
360	image->depth = depth;
361 	image->data = data;
362	/*
363	 * compute per line accelerator.
364	 */
365	if (format == ZPixmap) {
366	    if ((INT_MAX / bits_per_pixel) < width) {
367		Xfree(image);
368		return NULL;
369	    }
370
371	    min_bytes_per_line =
372		ROUNDUP((bits_per_pixel * width), image->bitmap_pad);
373	} else {
374	    if ((INT_MAX - offset) < width) {
375		Xfree(image);
376		return NULL;
377	    }
378
379	    min_bytes_per_line =
380		ROUNDUP((width + offset), image->bitmap_pad);
381	}
382	if (image_bytes_per_line == 0) {
383	    image->bytes_per_line = min_bytes_per_line;
384	} else if (image_bytes_per_line < min_bytes_per_line) {
385	    Xfree(image);
386	    return NULL;
387	} else {
388	    image->bytes_per_line = image_bytes_per_line;
389	}
390
391	image->bits_per_pixel = bits_per_pixel;
392	image->obdata = NULL;
393	_XInitImageFuncPtrs (image);
394
395	return image;
396}
397
398Status XInitImage (XImage *image)
399{
400	int min_bytes_per_line;
401
402	if (image->depth == 0 || image->depth > 32 ||
403	    image->bits_per_pixel > 32 || image->bitmap_unit > 32 ||
404	    image->bits_per_pixel < 0 || image->bitmap_unit < 0 ||
405	    (image->format != XYBitmap &&
406	     image->format != XYPixmap &&
407	     image->format != ZPixmap) ||
408	    (image->format == XYBitmap && image->depth != 1) ||
409	    (image->bitmap_pad != 8 &&
410	     image->bitmap_pad != 16 &&
411	     image->bitmap_pad != 32) ||
412	    image->xoffset < 0)
413	    return 0;
414
415	/*
416	 * compute per line accelerator.
417	 */
418	if (image->format == ZPixmap)
419	    min_bytes_per_line =
420	       ROUNDUP((image->bits_per_pixel * image->width),
421		       image->bitmap_pad);
422	else
423	    min_bytes_per_line =
424	        ROUNDUP((image->width + image->xoffset), image->bitmap_pad);
425
426	if (image->bytes_per_line == 0) {
427	    image->bytes_per_line = min_bytes_per_line;
428	} else if (image->bytes_per_line < min_bytes_per_line) {
429	    return 0;
430	}
431
432	_XInitImageFuncPtrs (image);
433
434	return 1;
435}
436
437/*
438 * _DestroyImage
439 *
440 * Deallocates the memory associated with the ximage data structure.
441 * this version handles the case of the image data being malloc'd
442 * entirely by the library.
443 */
444
445static int _XDestroyImage (XImage *ximage)
446{
447	Xfree(ximage->data);
448	Xfree(ximage->obdata);
449	Xfree(ximage);
450	return 1;
451}
452
453
454/*
455 * GetPixel
456 *
457 * Returns the specified pixel.  The X and Y coordinates are relative to
458 * the origin (upper left [0,0]) of the image.  The pixel value is returned
459 * in normalized format, i.e. the LSB of the long is the LSB of the pixel.
460 * The algorithm used is:
461 *
462 *	copy the source bitmap_unit or Zpixel into temp
463 *	normalize temp if needed
464 *	extract the pixel bits into return value
465 *
466 */
467
468static unsigned long const low_bits_table[] = {
469    0x00000000, 0x00000001, 0x00000003, 0x00000007,
470    0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
471    0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
472    0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
473    0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
474    0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
475    0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
476    0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
477    0xffffffff
478};
479
480static unsigned long _XGetPixel (
481    register XImage *ximage,
482    int x,
483    int y)
484
485{
486	unsigned long pixel, px;
487	register char *src;
488	register char *dst;
489	register int i, j;
490	int bits, nbytes;
491	long plane;
492
493	if ((ximage->bits_per_pixel | ximage->depth) == 1) {
494		src = &ximage->data[XYINDEX(x, y, ximage)];
495		dst = (char *)&pixel;
496		pixel = 0;
497		for (i = ximage->bitmap_unit >> 3; --i >= 0; ) *dst++ = *src++;
498		XYNORMALIZE(&pixel, ximage);
499          	bits = (x + ximage->xoffset) % ximage->bitmap_unit;
500		pixel = ((((char *)&pixel)[bits>>3])>>(bits&7)) & 1;
501	} else if (ximage->format == XYPixmap) {
502		pixel = 0;
503		plane = 0;
504		nbytes = ximage->bitmap_unit >> 3;
505		for (i = ximage->depth; --i >= 0; ) {
506		    src = &ximage->data[XYINDEX(x, y, ximage)+ plane];
507		    dst = (char *)&px;
508		    px = 0;
509		    for (j = nbytes; --j >= 0; ) *dst++ = *src++;
510		    XYNORMALIZE(&px, ximage);
511		    bits = (x + ximage->xoffset) % ximage->bitmap_unit;
512		    pixel = (pixel << 1) |
513			    (((((char *)&px)[bits>>3])>>(bits&7)) & 1);
514		    plane = plane + (ximage->bytes_per_line * ximage->height);
515		}
516	} else if (ximage->format == ZPixmap) {
517		src = &ximage->data[ZINDEX(x, y, ximage)];
518		dst = (char *)&px;
519		px = 0;
520		for (i = (ximage->bits_per_pixel + 7) >> 3; --i >= 0; )
521		    *dst++ = *src++;
522		ZNORMALIZE(&px, ximage);
523		pixel = 0;
524		for (i=sizeof(unsigned long); --i >= 0; )
525		    pixel = (pixel << 8) | ((unsigned char *)&px)[i];
526		if (ximage->bits_per_pixel == 4) {
527		    if (x & 1)
528			pixel >>= 4;
529		    else
530			pixel &= 0xf;
531		}
532	} else {
533		return 0; /* bad image */
534	}
535	if (ximage->bits_per_pixel == ximage->depth)
536	  return pixel;
537	else
538	  return (pixel & low_bits_table[ximage->depth]);
539}
540
541static CARD32 const byteorderpixel = MSBFirst << 24;
542
543static unsigned long _XGetPixel32 (
544    register XImage *ximage,
545    int x,
546    int y)
547{
548	register unsigned char *addr;
549	unsigned long pixel;
550
551	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) {
552	    addr = &((unsigned char *)ximage->data)
553			[y * ximage->bytes_per_line + (x << 2)];
554	    if (*((const char *)&byteorderpixel) == ximage->byte_order)
555		pixel = *((CARD32 *)addr);
556	    else if (ximage->byte_order == MSBFirst)
557		pixel = ((unsigned long)addr[0] << 24 |
558			 (unsigned long)addr[1] << 16 |
559			 (unsigned long)addr[2] << 8 |
560			 addr[3]);
561	    else
562		pixel = ((unsigned long)addr[3] << 24 |
563			 (unsigned long)addr[2] << 16 |
564			 (unsigned long)addr[1] << 8 |
565			 addr[0]);
566	    if (ximage->depth != 32)
567		pixel &= low_bits_table[ximage->depth];
568	    return pixel;
569	} else {
570	    _XInitImageFuncPtrs(ximage);
571	    return XGetPixel(ximage, x, y);
572	}
573}
574
575static unsigned long _XGetPixel16 (
576    register XImage *ximage,
577    int x,
578    int y)
579{
580	register unsigned char *addr;
581	unsigned long pixel;
582
583	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) {
584	    addr = &((unsigned char *)ximage->data)
585			[y * ximage->bytes_per_line + (x << 1)];
586	    if (ximage->byte_order == MSBFirst)
587		pixel = addr[0] << 8 | addr[1];
588	    else
589		pixel = addr[1] << 8 | addr[0];
590	    if (ximage->depth != 16)
591		pixel &= low_bits_table[ximage->depth];
592	    return pixel;
593	} else {
594	    _XInitImageFuncPtrs(ximage);
595	    return XGetPixel(ximage, x, y);
596	}
597}
598
599static unsigned long _XGetPixel8 (
600    register XImage *ximage,
601    int x,
602    int y)
603{
604	unsigned char pixel;
605
606	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) {
607	    pixel = ((unsigned char *)ximage->data)
608			[y * ximage->bytes_per_line + x];
609	    if (ximage->depth != 8)
610		pixel &= low_bits_table[ximage->depth];
611	    return pixel;
612	} else {
613	    _XInitImageFuncPtrs(ximage);
614	    return XGetPixel(ximage, x, y);
615	}
616}
617
618static unsigned long _XGetPixel1 (
619    register XImage *ximage,
620    int x,
621    int y)
622{
623	unsigned char bit;
624	int xoff, yoff;
625
626	if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
627	    (ximage->byte_order == ximage->bitmap_bit_order)) {
628	    xoff = x + ximage->xoffset;
629	    yoff = y * ximage->bytes_per_line + (xoff >> 3);
630	    xoff &= 7;
631	    if (ximage->bitmap_bit_order == MSBFirst)
632	        bit = 0x80 >> xoff;
633	    else
634		bit = 1 << xoff;
635	    return (ximage->data[yoff] & bit) ? 1 : 0;
636	} else {
637	    _XInitImageFuncPtrs(ximage);
638	    return XGetPixel(ximage, x, y);
639	}
640}
641
642/*
643 * PutPixel
644 *
645 * Overwrites the specified pixel.  The X and Y coordinates are relative to
646 * the origin (upper left [0,0]) of the image.  The input pixel value must be
647 * in normalized format, i.e. the LSB of the long is the LSB of the pixel.
648 * The algorithm used is:
649 *
650 *	copy the destination bitmap_unit or Zpixel to temp
651 *	normalize temp if needed
652 *	copy the pixel bits into the temp
653 *	renormalize temp if needed
654 *	copy the temp back into the destination image data
655 *
656 */
657
658static int _XPutPixel (
659    register XImage *ximage,
660    int x,
661    int y,
662    unsigned long pixel)
663
664{
665	unsigned long px, npixel;
666	register char *src;
667	register char *dst;
668	register int i;
669	int j, nbytes;
670	long plane;
671
672	if (ximage->depth == 4)
673	    pixel &= 0xf;
674        npixel = pixel;
675	for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
676	    ((unsigned char *)&pixel)[i] = px;
677	if ((ximage->bits_per_pixel | ximage->depth) == 1) {
678		src = &ximage->data[XYINDEX(x, y, ximage)];
679		dst = (char *)&px;
680		px = 0;
681		nbytes = ximage->bitmap_unit >> 3;
682		for (i = nbytes; --i >= 0; ) *dst++ = *src++;
683		XYNORMALIZE(&px, ximage);
684		i = ((x + ximage->xoffset) % ximage->bitmap_unit);
685		_putbits ((char *)&pixel, i, 1, (char *)&px);
686		XYNORMALIZE(&px, ximage);
687		src = (char *) &px;
688		dst = &ximage->data[XYINDEX(x, y, ximage)];
689		for (i = nbytes; --i >= 0; ) *dst++ = *src++;
690	} else if (ximage->format == XYPixmap) {
691		plane = (ximage->bytes_per_line * ximage->height) *
692		    (ximage->depth - 1); /* do least signif plane 1st */
693		nbytes = ximage->bitmap_unit >> 3;
694		for (j = ximage->depth; --j >= 0; ) {
695		    src = &ximage->data[XYINDEX(x, y, ximage) + plane];
696		    dst = (char *) &px;
697		    px = 0;
698		    for (i = nbytes; --i >= 0; ) *dst++ = *src++;
699		    XYNORMALIZE(&px, ximage);
700		    i = ((x + ximage->xoffset) % ximage->bitmap_unit);
701		    _putbits ((char *)&pixel, i, 1, (char *)&px);
702		    XYNORMALIZE(&px, ximage);
703		    src = (char *)&px;
704		    dst = &ximage->data[XYINDEX(x, y, ximage) + plane];
705		    for (i = nbytes; --i >= 0; ) *dst++ = *src++;
706		    npixel = npixel >> 1;
707		    for (i=0, px=npixel; i<sizeof(unsigned long); i++, px>>=8)
708			((unsigned char *)&pixel)[i] = px;
709		    plane = plane - (ximage->bytes_per_line * ximage->height);
710		}
711	} else if (ximage->format == ZPixmap) {
712		src = &ximage->data[ZINDEX(x, y, ximage)];
713		dst = (char *)&px;
714		px = 0;
715		nbytes = (ximage->bits_per_pixel + 7) >> 3;
716		for (i = nbytes; --i >= 0; ) *dst++ = *src++;
717		ZNORMALIZE(&px, ximage);
718		_putbits ((char *)&pixel,
719			  (x * ximage->bits_per_pixel) & 7,
720			  ximage->bits_per_pixel, (char *)&px);
721		ZNORMALIZE(&px, ximage);
722		src = (char *)&px;
723		dst = &ximage->data[ZINDEX(x, y, ximage)];
724		for (i = nbytes; --i >= 0; ) *dst++ = *src++;
725	} else {
726		return 0; /* bad image */
727	}
728	return 1;
729}
730
731static int _XPutPixel32 (
732    register XImage *ximage,
733    int x,
734    int y,
735    unsigned long pixel)
736{
737	unsigned char *addr;
738
739	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) {
740	    addr = &((unsigned char *)ximage->data)
741			[y * ximage->bytes_per_line + (x << 2)];
742	    if (*((const char *)&byteorderpixel) == ximage->byte_order)
743		*((CARD32 *)addr) = pixel;
744	    else if (ximage->byte_order == MSBFirst) {
745		addr[0] = pixel >> 24;
746		addr[1] = pixel >> 16;
747		addr[2] = pixel >> 8;
748		addr[3] = pixel;
749	    } else {
750		addr[3] = pixel >> 24;
751		addr[2] = pixel >> 16;
752		addr[1] = pixel >> 8;
753		addr[0] = pixel;
754	    }
755	    return 1;
756	} else {
757	    _XInitImageFuncPtrs(ximage);
758	    return XPutPixel(ximage, x, y, pixel);
759	}
760}
761
762static int _XPutPixel16 (
763    register XImage *ximage,
764    int x,
765    int y,
766    unsigned long pixel)
767{
768	unsigned char *addr;
769
770	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) {
771	    addr = &((unsigned char *)ximage->data)
772			[y * ximage->bytes_per_line + (x << 1)];
773	    if (ximage->byte_order == MSBFirst) {
774		addr[0] = pixel >> 8;
775		addr[1] = pixel;
776	    } else {
777		addr[1] = pixel >> 8;
778		addr[0] = pixel;
779	    }
780	    return 1;
781	} else {
782	    _XInitImageFuncPtrs(ximage);
783	    return XPutPixel(ximage, x, y, pixel);
784	}
785}
786
787static int _XPutPixel8 (
788    register XImage *ximage,
789    int x,
790    int y,
791    unsigned long pixel)
792{
793	if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) {
794	    ximage->data[y * ximage->bytes_per_line + x] = pixel;
795	    return 1;
796	} else {
797	    _XInitImageFuncPtrs(ximage);
798	    return XPutPixel(ximage, x, y, pixel);
799	}
800}
801
802static int _XPutPixel1 (
803    register XImage *ximage,
804    int x,
805    int y,
806    unsigned long pixel)
807{
808	unsigned char bit;
809	int xoff, yoff;
810
811	if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
812	    (ximage->byte_order == ximage->bitmap_bit_order)) {
813	    xoff = x + ximage->xoffset;
814	    yoff = y * ximage->bytes_per_line + (xoff >> 3);
815	    xoff &= 7;
816	    if (ximage->bitmap_bit_order == MSBFirst)
817		bit = 0x80 >> xoff;
818	    else
819		bit = 1 << xoff;
820	    if (pixel & 1)
821		ximage->data[yoff] |= bit;
822	    else
823		ximage->data[yoff] &= ~bit;
824	    return 1;
825	} else {
826	    _XInitImageFuncPtrs(ximage);
827	    return XPutPixel(ximage, x, y, pixel);
828	}
829}
830
831/*
832 * SubImage
833 *
834 * Creates a new image that is a subsection of an existing one.
835 * Allocates the memory necessary for the new XImage data structure.
836 * Pointer to new image is returned.  The algorithm used is repetitive
837 * calls to get and put pixel.
838 *
839 */
840
841static XImage *_XSubImage (
842    XImage *ximage,
843    register int x,	/* starting x coordinate in existing image */
844    register int y,	/* starting y coordinate in existing image */
845    unsigned int width,	/* width in pixels of new subimage */
846    unsigned int height)/* height in pixels of new subimage */
847
848{
849	register XImage *subimage;
850	int dsize;
851	register int row, col;
852	register unsigned long pixel;
853	char *data;
854
855	if ((subimage = Xcalloc (1, sizeof (XImage))) == NULL)
856	    return (XImage *) NULL;
857	subimage->width = width;
858	subimage->height = height;
859	subimage->xoffset = 0;
860	subimage->format = ximage->format;
861	subimage->byte_order = ximage->byte_order;
862	subimage->bitmap_unit = ximage->bitmap_unit;
863	subimage->bitmap_bit_order = ximage->bitmap_bit_order;
864	subimage->bitmap_pad = ximage->bitmap_pad;
865	subimage->bits_per_pixel = ximage->bits_per_pixel;
866	subimage->depth = ximage->depth;
867	/*
868	 * compute per line accelerator.
869	 */
870	if (subimage->format == ZPixmap)
871	    subimage->bytes_per_line =
872		ROUNDUP(subimage->bits_per_pixel * width,
873			subimage->bitmap_pad);
874	else
875	    subimage->bytes_per_line =
876		ROUNDUP(width, subimage->bitmap_pad);
877	subimage->obdata = NULL;
878	_XInitImageFuncPtrs (subimage);
879	dsize = subimage->bytes_per_line * height;
880	if (subimage->format == XYPixmap) dsize = dsize * subimage->depth;
881	if (((data = Xcalloc (1, dsize)) == NULL) && (dsize > 0)) {
882	    Xfree(subimage);
883	    return (XImage *) NULL;
884	}
885	subimage->data = data;
886
887	/*
888	 * Test for cases where the new subimage is larger than the region
889	 * that we are copying from the existing data.  In those cases,
890	 * copy the area of the existing image, and allow the "uncovered"
891	 * area of new subimage to remain with zero filled pixels.
892	 */
893	if (height > ximage->height - y ) height = ximage->height - y;
894	if (width > ximage->width - x ) width = ximage->width - x;
895
896	for (row = y; row < (y + height); row++) {
897	    for (col = x; col < (x + width); col++) {
898		pixel = XGetPixel(ximage, col, row);
899		XPutPixel(subimage, (col - x), (row - y), pixel);
900	    }
901	}
902	return subimage;
903}
904
905
906/*
907 * SetImage
908 *
909 * Overwrites a section of one image with all of the data from another.
910 * If the two images are not of the same format (i.e. XYPixmap and ZPixmap),
911 * the image data is converted to the destination format.  The following
912 * restrictions apply:
913 *
914 *	1. The depths of the source and destination images must be equal.
915 *
916 *	2. If the height of the source image is too large to fit between
917 *	   the specified y starting point and the bottom of the image,
918 *	   then scanlines are truncated on the bottom.
919 *
920 *	3. If the width of the source image is too large to fit between
921 *	   the specified x starting point and the end of the scanline,
922 *	   then pixels are truncated on the right.
923 *
924 * The images need not have the same bitmap_bit_order, byte_order,
925 * bitmap_unit, bits_per_pixel, bitmap_pad, or xoffset.
926 *
927 */
928
929int _XSetImage(
930    XImage *srcimg,
931    XImage *dstimg,
932    int x,
933    int y)
934{
935	register unsigned long pixel;
936	register int row, col;
937	int width, height, startrow, startcol;
938	if (x < 0) {
939	    startcol = -x;
940	    x = 0;
941	} else
942	    startcol = 0;
943	if (y < 0) {
944	    startrow = -y;
945	    y = 0;
946	} else
947	    startrow = 0;
948	width = dstimg->width - x;
949	if (srcimg->width < width)
950	    width = srcimg->width;
951	height = dstimg->height - y;
952	if (srcimg->height < height)
953	    height = srcimg->height;
954
955	/* this is slow, will do better later */
956	for (row = startrow; row < height; row++) {
957	    for (col = startcol; col < width; col++) {
958		pixel = XGetPixel(srcimg, col, row);
959		XPutPixel(dstimg, x + col, y + row, pixel);
960	    }
961	}
962	return 1;
963}
964
965/*
966 * AddPixel
967 *
968 * Adds a constant value to every pixel in a pixmap.
969 *
970 */
971
972static int
973_XAddPixel (
974    register XImage *ximage,
975    register long value)
976{
977	register int x;
978	register int y;
979
980	if (!value)
981	    return 0;
982	if ((ximage->bits_per_pixel | ximage->depth) == 1) {
983	    /* The only value that we can add here to an XYBitmap
984	     * is one.  Since 1 + value = ~value for one bit wide
985	     * data, we do this quickly by taking the ones complement
986	     * of the entire bitmap data (offset and pad included!).
987	     * Note that we don't need to be concerned with bit or
988	     * byte order at all.
989	     */
990	    register unsigned char *dp = (unsigned char *) ximage->data;
991	    x = ximage->bytes_per_line * ximage->height;
992	    while (--x >= 0) {
993		*dp = ~*dp;
994		dp++;
995	    }
996	} else if ((ximage->format == ZPixmap) &&
997		   (ximage->bits_per_pixel == 8)) {
998	    register unsigned char *dp = (unsigned char *) ximage->data;
999	    x = ximage->bytes_per_line * ximage->height;
1000	    while (--x >= 0)
1001		*dp++ += value;
1002	} else if ((ximage->format == ZPixmap) &&
1003		   (ximage->bits_per_pixel == 16) &&
1004		   (*((const char *)&byteorderpixel) == ximage->byte_order)) {
1005	    register unsigned short *dp = (unsigned short *) ximage->data;
1006	    x = (ximage->bytes_per_line >> 1) * ximage->height;
1007	    while (--x >= 0)
1008		*dp++ += value;
1009	} else if ((ximage->format == ZPixmap) &&
1010		   (ximage->bits_per_pixel == 32) &&
1011		   (*((const char *)&byteorderpixel) == ximage->byte_order)) {
1012	    register CARD32 *dp = (CARD32 *) ximage->data;
1013	    x = (ximage->bytes_per_line >> 2) * ximage->height;
1014	    while (--x >= 0)
1015		*dp++ += value;
1016	} else {
1017	    for (y = ximage->height; --y >= 0; ) {
1018		for (x = ximage->width; --x >= 0; ) {
1019		    register unsigned long pixel = XGetPixel(ximage, x, y);
1020		    pixel = pixel + value;
1021		    XPutPixel(ximage, x, y, pixel);
1022		}
1023	    }
1024	}
1025	return 0;
1026}
1027
1028