ImUtil.c revision ebe525bc
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#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) 243 244#define XYNORMALIZE(bp, img) \ 245 if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \ 246 _xynormalizeimagebits((unsigned char *)(bp), img) 247 248#define ZNORMALIZE(bp, img) \ 249 if (img->byte_order == MSBFirst) \ 250 _znormalizeimagebits((unsigned char *)(bp), img) 251 252#define XYINDEX(x, y, img) \ 253 ((y) * img->bytes_per_line) + \ 254 (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3) 255 256#define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \ 257 (((x) * img->bits_per_pixel) >> 3) 258 259/* 260 * This routine initializes the image object function pointers. The 261 * intent is to provide native (i.e. fast) routines for native format images 262 * only using the generic (i.e. slow) routines when fast ones don't exist. 263 * However, with the current rather botched external interface, clients may 264 * have to mung image attributes after the image gets created, so the fast 265 * routines always have to check to make sure the optimization is still 266 * valid, and reinit the functions if not. 267 */ 268void _XInitImageFuncPtrs ( 269 XImage *image) 270{ 271 image->f.create_image = XCreateImage; 272 image->f.destroy_image = _XDestroyImage; 273 if ((image->format == ZPixmap) && (image->bits_per_pixel == 8)) { 274 image->f.get_pixel = _XGetPixel8; 275 image->f.put_pixel = _XPutPixel8; 276 } else if (((image->bits_per_pixel | image->depth) == 1) && 277 (image->byte_order == image->bitmap_bit_order)) { 278 image->f.get_pixel = _XGetPixel1; 279 image->f.put_pixel = _XPutPixel1; 280 } else if ((image->format == ZPixmap) && 281 (image->bits_per_pixel == 32)) { 282 image->f.get_pixel = _XGetPixel32; 283 image->f.put_pixel = _XPutPixel32; 284 } else if ((image->format == ZPixmap) && 285 (image->bits_per_pixel == 16)) { 286 image->f.get_pixel = _XGetPixel16; 287 image->f.put_pixel = _XPutPixel16; 288 } else { 289 image->f.get_pixel = _XGetPixel; 290 image->f.put_pixel = _XPutPixel; 291 } 292 image->f.sub_image = _XSubImage; 293/* image->f.set_image = _XSetImage;*/ 294 image->f.add_pixel = _XAddPixel; 295} 296 297/* 298 * CreateImage 299 * 300 * Allocates the memory necessary for an XImage data structure. 301 * Initializes the structure with "default" values and returns XImage. 302 * 303 */ 304 305XImage *XCreateImage ( 306 register Display *dpy, 307 register Visual *visual, 308 unsigned int depth, 309 int format, 310 int offset, /*How many pixels from the start of the data does the 311 picture to be transmitted start?*/ 312 313 char *data, 314 unsigned int width, 315 unsigned int height, 316 int xpad, 317 int image_bytes_per_line) 318 /*How many bytes between a pixel on one line and the pixel with 319 the same X coordinate on the next line? 0 means 320 XCreateImage can calculate it.*/ 321{ 322 register XImage *image; 323 int bits_per_pixel = 1; 324 int min_bytes_per_line; 325 326 if (depth == 0 || depth > 32 || 327 (format != XYBitmap && format != XYPixmap && format != ZPixmap) || 328 (format == XYBitmap && depth != 1) || 329 (xpad != 8 && xpad != 16 && xpad != 32) || 330 offset < 0) 331 return (XImage *) NULL; 332 if ((image = Xcalloc(1, sizeof(XImage))) == NULL) 333 return (XImage *) NULL; 334 335 image->width = width; 336 image->height = height; 337 image->format = format; 338 image->byte_order = dpy->byte_order; 339 image->bitmap_unit = dpy->bitmap_unit; 340 image->bitmap_bit_order = dpy->bitmap_bit_order; 341 if (visual != NULL) { 342 image->red_mask = visual->red_mask; 343 image->green_mask = visual->green_mask; 344 image->blue_mask = visual->blue_mask; 345 } 346 else { 347 image->red_mask = image->green_mask = image->blue_mask = 0; 348 } 349 if (format == ZPixmap) 350 { 351 bits_per_pixel = _XGetBitsPerPixel(dpy, (int) depth); 352 } 353 354 image->xoffset = offset; 355 image->bitmap_pad = xpad; 356 image->depth = depth; 357 image->data = data; 358 /* 359 * compute per line accelerator. 360 */ 361 if (format == ZPixmap) { 362 if ((INT_MAX / bits_per_pixel) < width) { 363 Xfree(image); 364 return NULL; 365 } 366 367 min_bytes_per_line = 368 ROUNDUP((bits_per_pixel * width), image->bitmap_pad); 369 } else { 370 if ((INT_MAX - offset) < width) { 371 Xfree(image); 372 return NULL; 373 } 374 375 min_bytes_per_line = 376 ROUNDUP((width + offset), image->bitmap_pad); 377 } 378 if (image_bytes_per_line == 0) { 379 image->bytes_per_line = min_bytes_per_line; 380 } else if (image_bytes_per_line < min_bytes_per_line) { 381 Xfree(image); 382 return NULL; 383 } else { 384 image->bytes_per_line = image_bytes_per_line; 385 } 386 387 image->bits_per_pixel = bits_per_pixel; 388 image->obdata = NULL; 389 _XInitImageFuncPtrs (image); 390 391 return image; 392} 393 394Status XInitImage (XImage *image) 395{ 396 int min_bytes_per_line; 397 398 if (image->depth == 0 || image->depth > 32 || 399 image->bits_per_pixel > 32 || image->bitmap_unit > 32 || 400 image->bits_per_pixel < 0 || image->bitmap_unit < 0 || 401 (image->format != XYBitmap && 402 image->format != XYPixmap && 403 image->format != ZPixmap) || 404 (image->format == XYBitmap && image->depth != 1) || 405 (image->bitmap_pad != 8 && 406 image->bitmap_pad != 16 && 407 image->bitmap_pad != 32) || 408 image->xoffset < 0) 409 return 0; 410 411 /* 412 * compute per line accelerator. 413 */ 414 if (image->format == ZPixmap) 415 min_bytes_per_line = 416 ROUNDUP((image->bits_per_pixel * image->width), 417 image->bitmap_pad); 418 else 419 min_bytes_per_line = 420 ROUNDUP((image->width + image->xoffset), image->bitmap_pad); 421 422 if (image->bytes_per_line == 0) { 423 image->bytes_per_line = min_bytes_per_line; 424 } else if (image->bytes_per_line < min_bytes_per_line) { 425 return 0; 426 } 427 428 _XInitImageFuncPtrs (image); 429 430 return 1; 431} 432 433/* 434 * _DestroyImage 435 * 436 * Deallocates the memory associated with the ximage data structure. 437 * this version handles the case of the image data being malloc'd 438 * entirely by the library. 439 */ 440 441static int _XDestroyImage (XImage *ximage) 442{ 443 Xfree(ximage->data); 444 Xfree(ximage->obdata); 445 Xfree(ximage); 446 return 1; 447} 448 449 450/* 451 * GetPixel 452 * 453 * Returns the specified pixel. The X and Y coordinates are relative to 454 * the origin (upper left [0,0]) of the image. The pixel value is returned 455 * in normalized format, i.e. the LSB of the long is the LSB of the pixel. 456 * The algorithm used is: 457 * 458 * copy the source bitmap_unit or Zpixel into temp 459 * normalize temp if needed 460 * extract the pixel bits into return value 461 * 462 */ 463 464static unsigned long const low_bits_table[] = { 465 0x00000000, 0x00000001, 0x00000003, 0x00000007, 466 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, 467 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, 468 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 469 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, 470 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, 471 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, 472 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 473 0xffffffff 474}; 475 476static unsigned long _XGetPixel ( 477 register XImage *ximage, 478 int x, 479 int y) 480 481{ 482 unsigned long pixel, px; 483 register char *src; 484 register char *dst; 485 register int i, j; 486 int bits, nbytes; 487 long plane; 488 489 if ((ximage->bits_per_pixel | ximage->depth) == 1) { 490 src = &ximage->data[XYINDEX(x, y, ximage)]; 491 dst = (char *)&pixel; 492 pixel = 0; 493 for (i = ximage->bitmap_unit >> 3; --i >= 0; ) *dst++ = *src++; 494 XYNORMALIZE(&pixel, ximage); 495 bits = (x + ximage->xoffset) % ximage->bitmap_unit; 496 pixel = ((((char *)&pixel)[bits>>3])>>(bits&7)) & 1; 497 } else if (ximage->format == XYPixmap) { 498 pixel = 0; 499 plane = 0; 500 nbytes = ximage->bitmap_unit >> 3; 501 for (i = ximage->depth; --i >= 0; ) { 502 src = &ximage->data[XYINDEX(x, y, ximage)+ plane]; 503 dst = (char *)&px; 504 px = 0; 505 for (j = nbytes; --j >= 0; ) *dst++ = *src++; 506 XYNORMALIZE(&px, ximage); 507 bits = (x + ximage->xoffset) % ximage->bitmap_unit; 508 pixel = (pixel << 1) | 509 (((((char *)&px)[bits>>3])>>(bits&7)) & 1); 510 plane = plane + (ximage->bytes_per_line * ximage->height); 511 } 512 } else if (ximage->format == ZPixmap) { 513 src = &ximage->data[ZINDEX(x, y, ximage)]; 514 dst = (char *)&px; 515 px = 0; 516 for (i = (ximage->bits_per_pixel + 7) >> 3; --i >= 0; ) 517 *dst++ = *src++; 518 ZNORMALIZE(&px, ximage); 519 pixel = 0; 520 for (i=sizeof(unsigned long); --i >= 0; ) 521 pixel = (pixel << 8) | ((unsigned char *)&px)[i]; 522 if (ximage->bits_per_pixel == 4) { 523 if (x & 1) 524 pixel >>= 4; 525 else 526 pixel &= 0xf; 527 } 528 } else { 529 return 0; /* bad image */ 530 } 531 if (ximage->bits_per_pixel == ximage->depth) 532 return pixel; 533 else 534 return (pixel & low_bits_table[ximage->depth]); 535} 536 537static CARD32 const byteorderpixel = MSBFirst << 24; 538 539static unsigned long _XGetPixel32 ( 540 register XImage *ximage, 541 int x, 542 int y) 543{ 544 register unsigned char *addr; 545 unsigned long pixel; 546 547 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) { 548 addr = &((unsigned char *)ximage->data) 549 [y * ximage->bytes_per_line + (x << 2)]; 550 if (*((const char *)&byteorderpixel) == ximage->byte_order) 551 pixel = *((CARD32 *)addr); 552 else if (ximage->byte_order == MSBFirst) 553 pixel = ((unsigned long)addr[0] << 24 | 554 (unsigned long)addr[1] << 16 | 555 (unsigned long)addr[2] << 8 | 556 addr[3]); 557 else 558 pixel = ((unsigned long)addr[3] << 24 | 559 (unsigned long)addr[2] << 16 | 560 (unsigned long)addr[1] << 8 | 561 addr[0]); 562 if (ximage->depth != 32) 563 pixel &= low_bits_table[ximage->depth]; 564 return pixel; 565 } else { 566 _XInitImageFuncPtrs(ximage); 567 return XGetPixel(ximage, x, y); 568 } 569} 570 571static unsigned long _XGetPixel16 ( 572 register XImage *ximage, 573 int x, 574 int y) 575{ 576 register unsigned char *addr; 577 unsigned long pixel; 578 579 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) { 580 addr = &((unsigned char *)ximage->data) 581 [y * ximage->bytes_per_line + (x << 1)]; 582 if (ximage->byte_order == MSBFirst) 583 pixel = addr[0] << 8 | addr[1]; 584 else 585 pixel = addr[1] << 8 | addr[0]; 586 if (ximage->depth != 16) 587 pixel &= low_bits_table[ximage->depth]; 588 return pixel; 589 } else { 590 _XInitImageFuncPtrs(ximage); 591 return XGetPixel(ximage, x, y); 592 } 593} 594 595static unsigned long _XGetPixel8 ( 596 register XImage *ximage, 597 int x, 598 int y) 599{ 600 unsigned char pixel; 601 602 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) { 603 pixel = ((unsigned char *)ximage->data) 604 [y * ximage->bytes_per_line + x]; 605 if (ximage->depth != 8) 606 pixel &= low_bits_table[ximage->depth]; 607 return pixel; 608 } else { 609 _XInitImageFuncPtrs(ximage); 610 return XGetPixel(ximage, x, y); 611 } 612} 613 614static unsigned long _XGetPixel1 ( 615 register XImage *ximage, 616 int x, 617 int y) 618{ 619 unsigned char bit; 620 int xoff, yoff; 621 622 if (((ximage->bits_per_pixel | ximage->depth) == 1) && 623 (ximage->byte_order == ximage->bitmap_bit_order)) { 624 xoff = x + ximage->xoffset; 625 yoff = y * ximage->bytes_per_line + (xoff >> 3); 626 xoff &= 7; 627 if (ximage->bitmap_bit_order == MSBFirst) 628 bit = 0x80 >> xoff; 629 else 630 bit = 1 << xoff; 631 return (ximage->data[yoff] & bit) ? 1 : 0; 632 } else { 633 _XInitImageFuncPtrs(ximage); 634 return XGetPixel(ximage, x, y); 635 } 636} 637 638/* 639 * PutPixel 640 * 641 * Overwrites the specified pixel. The X and Y coordinates are relative to 642 * the origin (upper left [0,0]) of the image. The input pixel value must be 643 * in normalized format, i.e. the LSB of the long is the LSB of the pixel. 644 * The algorithm used is: 645 * 646 * copy the destination bitmap_unit or Zpixel to temp 647 * normalize temp if needed 648 * copy the pixel bits into the temp 649 * renormalize temp if needed 650 * copy the temp back into the destination image data 651 * 652 */ 653 654static int _XPutPixel ( 655 register XImage *ximage, 656 int x, 657 int y, 658 unsigned long pixel) 659 660{ 661 unsigned long px, npixel; 662 register char *src; 663 register char *dst; 664 register int i; 665 int j, nbytes; 666 long plane; 667 668 if (ximage->depth == 4) 669 pixel &= 0xf; 670 npixel = pixel; 671 for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8) 672 ((unsigned char *)&pixel)[i] = px; 673 if ((ximage->bits_per_pixel | ximage->depth) == 1) { 674 src = &ximage->data[XYINDEX(x, y, ximage)]; 675 dst = (char *)&px; 676 px = 0; 677 nbytes = ximage->bitmap_unit >> 3; 678 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 679 XYNORMALIZE(&px, ximage); 680 i = ((x + ximage->xoffset) % ximage->bitmap_unit); 681 _putbits ((char *)&pixel, i, 1, (char *)&px); 682 XYNORMALIZE(&px, ximage); 683 src = (char *) &px; 684 dst = &ximage->data[XYINDEX(x, y, ximage)]; 685 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 686 } else if (ximage->format == XYPixmap) { 687 plane = (ximage->bytes_per_line * ximage->height) * 688 (ximage->depth - 1); /* do least signif plane 1st */ 689 nbytes = ximage->bitmap_unit >> 3; 690 for (j = ximage->depth; --j >= 0; ) { 691 src = &ximage->data[XYINDEX(x, y, ximage) + plane]; 692 dst = (char *) &px; 693 px = 0; 694 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 695 XYNORMALIZE(&px, ximage); 696 i = ((x + ximage->xoffset) % ximage->bitmap_unit); 697 _putbits ((char *)&pixel, i, 1, (char *)&px); 698 XYNORMALIZE(&px, ximage); 699 src = (char *)&px; 700 dst = &ximage->data[XYINDEX(x, y, ximage) + plane]; 701 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 702 npixel = npixel >> 1; 703 for (i=0, px=npixel; i<sizeof(unsigned long); i++, px>>=8) 704 ((unsigned char *)&pixel)[i] = px; 705 plane = plane - (ximage->bytes_per_line * ximage->height); 706 } 707 } else if (ximage->format == ZPixmap) { 708 src = &ximage->data[ZINDEX(x, y, ximage)]; 709 dst = (char *)&px; 710 px = 0; 711 nbytes = (ximage->bits_per_pixel + 7) >> 3; 712 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 713 ZNORMALIZE(&px, ximage); 714 _putbits ((char *)&pixel, 715 (x * ximage->bits_per_pixel) & 7, 716 ximage->bits_per_pixel, (char *)&px); 717 ZNORMALIZE(&px, ximage); 718 src = (char *)&px; 719 dst = &ximage->data[ZINDEX(x, y, ximage)]; 720 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 721 } else { 722 return 0; /* bad image */ 723 } 724 return 1; 725} 726 727static int _XPutPixel32 ( 728 register XImage *ximage, 729 int x, 730 int y, 731 unsigned long pixel) 732{ 733 unsigned char *addr; 734 735 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) { 736 addr = &((unsigned char *)ximage->data) 737 [y * ximage->bytes_per_line + (x << 2)]; 738 if (*((const char *)&byteorderpixel) == ximage->byte_order) 739 *((CARD32 *)addr) = pixel; 740 else if (ximage->byte_order == MSBFirst) { 741 addr[0] = pixel >> 24; 742 addr[1] = pixel >> 16; 743 addr[2] = pixel >> 8; 744 addr[3] = pixel; 745 } else { 746 addr[3] = pixel >> 24; 747 addr[2] = pixel >> 16; 748 addr[1] = pixel >> 8; 749 addr[0] = pixel; 750 } 751 return 1; 752 } else { 753 _XInitImageFuncPtrs(ximage); 754 return XPutPixel(ximage, x, y, pixel); 755 } 756} 757 758static int _XPutPixel16 ( 759 register XImage *ximage, 760 int x, 761 int y, 762 unsigned long pixel) 763{ 764 unsigned char *addr; 765 766 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) { 767 addr = &((unsigned char *)ximage->data) 768 [y * ximage->bytes_per_line + (x << 1)]; 769 if (ximage->byte_order == MSBFirst) { 770 addr[0] = pixel >> 8; 771 addr[1] = pixel; 772 } else { 773 addr[1] = pixel >> 8; 774 addr[0] = pixel; 775 } 776 return 1; 777 } else { 778 _XInitImageFuncPtrs(ximage); 779 return XPutPixel(ximage, x, y, pixel); 780 } 781} 782 783static int _XPutPixel8 ( 784 register XImage *ximage, 785 int x, 786 int y, 787 unsigned long pixel) 788{ 789 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) { 790 ximage->data[y * ximage->bytes_per_line + x] = pixel; 791 return 1; 792 } else { 793 _XInitImageFuncPtrs(ximage); 794 return XPutPixel(ximage, x, y, pixel); 795 } 796} 797 798static int _XPutPixel1 ( 799 register XImage *ximage, 800 int x, 801 int y, 802 unsigned long pixel) 803{ 804 unsigned char bit; 805 int xoff, yoff; 806 807 if (((ximage->bits_per_pixel | ximage->depth) == 1) && 808 (ximage->byte_order == ximage->bitmap_bit_order)) { 809 xoff = x + ximage->xoffset; 810 yoff = y * ximage->bytes_per_line + (xoff >> 3); 811 xoff &= 7; 812 if (ximage->bitmap_bit_order == MSBFirst) 813 bit = 0x80 >> xoff; 814 else 815 bit = 1 << xoff; 816 if (pixel & 1) 817 ximage->data[yoff] |= bit; 818 else 819 ximage->data[yoff] &= ~bit; 820 return 1; 821 } else { 822 _XInitImageFuncPtrs(ximage); 823 return XPutPixel(ximage, x, y, pixel); 824 } 825} 826 827/* 828 * SubImage 829 * 830 * Creates a new image that is a subsection of an existing one. 831 * Allocates the memory necessary for the new XImage data structure. 832 * Pointer to new image is returned. The algorithm used is repetitive 833 * calls to get and put pixel. 834 * 835 */ 836 837static XImage *_XSubImage ( 838 XImage *ximage, 839 register int x, /* starting x coordinate in existing image */ 840 register int y, /* starting y coordinate in existing image */ 841 unsigned int width, /* width in pixels of new subimage */ 842 unsigned int height)/* height in pixels of new subimage */ 843 844{ 845 register XImage *subimage; 846 int dsize; 847 register int row, col; 848 register unsigned long pixel; 849 char *data; 850 851 if ((subimage = Xcalloc (1, sizeof (XImage))) == NULL) 852 return (XImage *) NULL; 853 subimage->width = width; 854 subimage->height = height; 855 subimage->xoffset = 0; 856 subimage->format = ximage->format; 857 subimage->byte_order = ximage->byte_order; 858 subimage->bitmap_unit = ximage->bitmap_unit; 859 subimage->bitmap_bit_order = ximage->bitmap_bit_order; 860 subimage->bitmap_pad = ximage->bitmap_pad; 861 subimage->bits_per_pixel = ximage->bits_per_pixel; 862 subimage->depth = ximage->depth; 863 /* 864 * compute per line accelerator. 865 */ 866 if (subimage->format == ZPixmap) 867 subimage->bytes_per_line = 868 ROUNDUP(subimage->bits_per_pixel * width, 869 subimage->bitmap_pad); 870 else 871 subimage->bytes_per_line = 872 ROUNDUP(width, subimage->bitmap_pad); 873 subimage->obdata = NULL; 874 _XInitImageFuncPtrs (subimage); 875 dsize = subimage->bytes_per_line * height; 876 if (subimage->format == XYPixmap) dsize = dsize * subimage->depth; 877 if (((data = Xcalloc (1, dsize)) == NULL) && (dsize > 0)) { 878 Xfree(subimage); 879 return (XImage *) NULL; 880 } 881 subimage->data = data; 882 883 /* 884 * Test for cases where the new subimage is larger than the region 885 * that we are copying from the existing data. In those cases, 886 * copy the area of the existing image, and allow the "uncovered" 887 * area of new subimage to remain with zero filled pixels. 888 */ 889 if (height > ximage->height - y ) height = ximage->height - y; 890 if (width > ximage->width - x ) width = ximage->width - x; 891 892 for (row = y; row < (y + height); row++) { 893 for (col = x; col < (x + width); col++) { 894 pixel = XGetPixel(ximage, col, row); 895 XPutPixel(subimage, (col - x), (row - y), pixel); 896 } 897 } 898 return subimage; 899} 900 901 902/* 903 * SetImage 904 * 905 * Overwrites a section of one image with all of the data from another. 906 * If the two images are not of the same format (i.e. XYPixmap and ZPixmap), 907 * the image data is converted to the destination format. The following 908 * restrictions apply: 909 * 910 * 1. The depths of the source and destination images must be equal. 911 * 912 * 2. If the height of the source image is too large to fit between 913 * the specified y starting point and the bottom of the image, 914 * then scanlines are truncated on the bottom. 915 * 916 * 3. If the width of the source image is too large to fit between 917 * the specified x starting point and the end of the scanline, 918 * then pixels are truncated on the right. 919 * 920 * The images need not have the same bitmap_bit_order, byte_order, 921 * bitmap_unit, bits_per_pixel, bitmap_pad, or xoffset. 922 * 923 */ 924 925int _XSetImage( 926 XImage *srcimg, 927 XImage *dstimg, 928 int x, 929 int y) 930{ 931 register unsigned long pixel; 932 register int row, col; 933 int width, height, startrow, startcol; 934 if (x < 0) { 935 startcol = -x; 936 x = 0; 937 } else 938 startcol = 0; 939 if (y < 0) { 940 startrow = -y; 941 y = 0; 942 } else 943 startrow = 0; 944 width = dstimg->width - x; 945 if (srcimg->width < width) 946 width = srcimg->width; 947 height = dstimg->height - y; 948 if (srcimg->height < height) 949 height = srcimg->height; 950 951 /* this is slow, will do better later */ 952 for (row = startrow; row < height; row++) { 953 for (col = startcol; col < width; col++) { 954 pixel = XGetPixel(srcimg, col, row); 955 XPutPixel(dstimg, x + col, y + row, pixel); 956 } 957 } 958 return 1; 959} 960 961/* 962 * AddPixel 963 * 964 * Adds a constant value to every pixel in a pixmap. 965 * 966 */ 967 968static int 969_XAddPixel ( 970 register XImage *ximage, 971 register long value) 972{ 973 register int x; 974 register int y; 975 976 if (!value) 977 return 0; 978 if ((ximage->bits_per_pixel | ximage->depth) == 1) { 979 /* The only value that we can add here to an XYBitmap 980 * is one. Since 1 + value = ~value for one bit wide 981 * data, we do this quickly by taking the ones complement 982 * of the entire bitmap data (offset and pad included!). 983 * Note that we don't need to be concerned with bit or 984 * byte order at all. 985 */ 986 register unsigned char *dp = (unsigned char *) ximage->data; 987 x = ximage->bytes_per_line * ximage->height; 988 while (--x >= 0) { 989 *dp = ~*dp; 990 dp++; 991 } 992 } else if ((ximage->format == ZPixmap) && 993 (ximage->bits_per_pixel == 8)) { 994 register unsigned char *dp = (unsigned char *) ximage->data; 995 x = ximage->bytes_per_line * ximage->height; 996 while (--x >= 0) 997 *dp++ += value; 998 } else if ((ximage->format == ZPixmap) && 999 (ximage->bits_per_pixel == 16) && 1000 (*((const char *)&byteorderpixel) == ximage->byte_order)) { 1001 register unsigned short *dp = (unsigned short *) ximage->data; 1002 x = (ximage->bytes_per_line >> 1) * ximage->height; 1003 while (--x >= 0) 1004 *dp++ += value; 1005 } else if ((ximage->format == ZPixmap) && 1006 (ximage->bits_per_pixel == 32) && 1007 (*((const char *)&byteorderpixel) == ximage->byte_order)) { 1008 register CARD32 *dp = (CARD32 *) ximage->data; 1009 x = (ximage->bytes_per_line >> 2) * ximage->height; 1010 while (--x >= 0) 1011 *dp++ += value; 1012 } else { 1013 for (y = ximage->height; --y >= 0; ) { 1014 for (x = ximage->width; --x >= 0; ) { 1015 register unsigned long pixel = XGetPixel(ximage, x, y); 1016 pixel = pixel + value; 1017 XPutPixel(ximage, x, y, pixel); 1018 } 1019 } 1020 } 1021 return 0; 1022} 1023 1024