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