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