ImUtil.c revision 818534a1
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 if (ximage->data != NULL) Xfree(ximage->data); 438 if (ximage->obdata != NULL) 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