ImUtil.c revision 57f47464
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 = (XImage *) Xcalloc(1, (unsigned) 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((char *)ximage->data); 438 if (ximage->obdata != NULL) Xfree((char *)ximage->obdata); 439 Xfree((char *)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 531#ifndef WORD64 532static CARD32 const byteorderpixel = MSBFirst << 24; 533#endif 534 535static unsigned long _XGetPixel32 ( 536 register XImage *ximage, 537 int x, 538 int y) 539{ 540 register unsigned char *addr; 541 unsigned long pixel; 542 543 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) { 544 addr = &((unsigned char *)ximage->data) 545 [y * ximage->bytes_per_line + (x << 2)]; 546#ifndef WORD64 547 if (*((const char *)&byteorderpixel) == ximage->byte_order) 548 pixel = *((CARD32 *)addr); 549 else 550#endif 551 if (ximage->byte_order == MSBFirst) 552 pixel = ((unsigned long)addr[0] << 24 | 553 (unsigned long)addr[1] << 16 | 554 (unsigned long)addr[2] << 8 | 555 addr[3]); 556 else 557 pixel = ((unsigned long)addr[3] << 24 | 558 (unsigned long)addr[2] << 16 | 559 (unsigned long)addr[1] << 8 | 560 addr[0]); 561 if (ximage->depth != 32) 562 pixel &= low_bits_table[ximage->depth]; 563 return pixel; 564 } else { 565 _XInitImageFuncPtrs(ximage); 566 return XGetPixel(ximage, x, y); 567 } 568} 569 570static unsigned long _XGetPixel16 ( 571 register XImage *ximage, 572 int x, 573 int y) 574{ 575 register unsigned char *addr; 576 unsigned long pixel; 577 578 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) { 579 addr = &((unsigned char *)ximage->data) 580 [y * ximage->bytes_per_line + (x << 1)]; 581 if (ximage->byte_order == MSBFirst) 582 pixel = addr[0] << 8 | addr[1]; 583 else 584 pixel = addr[1] << 8 | addr[0]; 585 if (ximage->depth != 16) 586 pixel &= low_bits_table[ximage->depth]; 587 return pixel; 588 } else { 589 _XInitImageFuncPtrs(ximage); 590 return XGetPixel(ximage, x, y); 591 } 592} 593 594static unsigned long _XGetPixel8 ( 595 register XImage *ximage, 596 int x, 597 int y) 598{ 599 unsigned char pixel; 600 601 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) { 602 pixel = ((unsigned char *)ximage->data) 603 [y * ximage->bytes_per_line + x]; 604 if (ximage->depth != 8) 605 pixel &= low_bits_table[ximage->depth]; 606 return pixel; 607 } else { 608 _XInitImageFuncPtrs(ximage); 609 return XGetPixel(ximage, x, y); 610 } 611} 612 613static unsigned long _XGetPixel1 ( 614 register XImage *ximage, 615 int x, 616 int y) 617{ 618 unsigned char bit; 619 int xoff, yoff; 620 621 if (((ximage->bits_per_pixel | ximage->depth) == 1) && 622 (ximage->byte_order == ximage->bitmap_bit_order)) { 623 xoff = x + ximage->xoffset; 624 yoff = y * ximage->bytes_per_line + (xoff >> 3); 625 xoff &= 7; 626 if (ximage->bitmap_bit_order == MSBFirst) 627 bit = 0x80 >> xoff; 628 else 629 bit = 1 << xoff; 630 return (ximage->data[yoff] & bit) ? 1 : 0; 631 } else { 632 _XInitImageFuncPtrs(ximage); 633 return XGetPixel(ximage, x, y); 634 } 635} 636 637/* 638 * PutPixel 639 * 640 * Overwrites the specified pixel. The X and Y coordinates are relative to 641 * the origin (upper left [0,0]) of the image. The input pixel value must be 642 * in normalized format, i.e. the LSB of the long is the LSB of the pixel. 643 * The algorithm used is: 644 * 645 * copy the destination bitmap_unit or Zpixel to temp 646 * normalize temp if needed 647 * copy the pixel bits into the temp 648 * renormalize temp if needed 649 * copy the temp back into the destination image data 650 * 651 */ 652 653static int _XPutPixel ( 654 register XImage *ximage, 655 int x, 656 int y, 657 unsigned long pixel) 658 659{ 660 unsigned long px, npixel; 661 register char *src; 662 register char *dst; 663 register int i; 664 int j, nbytes; 665 long plane; 666 667 if (ximage->depth == 4) 668 pixel &= 0xf; 669 npixel = pixel; 670 for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8) 671 ((unsigned char *)&pixel)[i] = px; 672 if ((ximage->bits_per_pixel | ximage->depth) == 1) { 673 src = &ximage->data[XYINDEX(x, y, ximage)]; 674 dst = (char *)&px; 675 px = 0; 676 nbytes = ximage->bitmap_unit >> 3; 677 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 678 XYNORMALIZE(&px, ximage); 679 i = ((x + ximage->xoffset) % ximage->bitmap_unit); 680 _putbits ((char *)&pixel, i, 1, (char *)&px); 681 XYNORMALIZE(&px, ximage); 682 src = (char *) &px; 683 dst = &ximage->data[XYINDEX(x, y, ximage)]; 684 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 685 } else if (ximage->format == XYPixmap) { 686 plane = (ximage->bytes_per_line * ximage->height) * 687 (ximage->depth - 1); /* do least signif plane 1st */ 688 nbytes = ximage->bitmap_unit >> 3; 689 for (j = ximage->depth; --j >= 0; ) { 690 src = &ximage->data[XYINDEX(x, y, ximage) + plane]; 691 dst = (char *) &px; 692 px = 0; 693 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 694 XYNORMALIZE(&px, ximage); 695 i = ((x + ximage->xoffset) % ximage->bitmap_unit); 696 _putbits ((char *)&pixel, i, 1, (char *)&px); 697 XYNORMALIZE(&px, ximage); 698 src = (char *)&px; 699 dst = &ximage->data[XYINDEX(x, y, ximage) + plane]; 700 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 701 npixel = npixel >> 1; 702 for (i=0, px=npixel; i<sizeof(unsigned long); i++, px>>=8) 703 ((unsigned char *)&pixel)[i] = px; 704 plane = plane - (ximage->bytes_per_line * ximage->height); 705 } 706 } else if (ximage->format == ZPixmap) { 707 src = &ximage->data[ZINDEX(x, y, ximage)]; 708 dst = (char *)&px; 709 px = 0; 710 nbytes = (ximage->bits_per_pixel + 7) >> 3; 711 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 712 ZNORMALIZE(&px, ximage); 713 _putbits ((char *)&pixel, 714 (x * ximage->bits_per_pixel) & 7, 715 ximage->bits_per_pixel, (char *)&px); 716 ZNORMALIZE(&px, ximage); 717 src = (char *)&px; 718 dst = &ximage->data[ZINDEX(x, y, ximage)]; 719 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 720 } else { 721 return 0; /* bad image */ 722 } 723 return 1; 724} 725 726static int _XPutPixel32 ( 727 register XImage *ximage, 728 int x, 729 int y, 730 unsigned long pixel) 731{ 732 unsigned char *addr; 733 734 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 32)) { 735 addr = &((unsigned char *)ximage->data) 736 [y * ximage->bytes_per_line + (x << 2)]; 737#ifndef WORD64 738 if (*((const char *)&byteorderpixel) == ximage->byte_order) 739 *((CARD32 *)addr) = pixel; 740 else 741#endif 742 if (ximage->byte_order == MSBFirst) { 743 addr[0] = pixel >> 24; 744 addr[1] = pixel >> 16; 745 addr[2] = pixel >> 8; 746 addr[3] = pixel; 747 } else { 748 addr[3] = pixel >> 24; 749 addr[2] = pixel >> 16; 750 addr[1] = pixel >> 8; 751 addr[0] = pixel; 752 } 753 return 1; 754 } else { 755 _XInitImageFuncPtrs(ximage); 756 return XPutPixel(ximage, x, y, pixel); 757 } 758} 759 760static int _XPutPixel16 ( 761 register XImage *ximage, 762 int x, 763 int y, 764 unsigned long pixel) 765{ 766 unsigned char *addr; 767 768 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 16)) { 769 addr = &((unsigned char *)ximage->data) 770 [y * ximage->bytes_per_line + (x << 1)]; 771 if (ximage->byte_order == MSBFirst) { 772 addr[0] = pixel >> 8; 773 addr[1] = pixel; 774 } else { 775 addr[1] = pixel >> 8; 776 addr[0] = pixel; 777 } 778 return 1; 779 } else { 780 _XInitImageFuncPtrs(ximage); 781 return XPutPixel(ximage, x, y, pixel); 782 } 783} 784 785static int _XPutPixel8 ( 786 register XImage *ximage, 787 int x, 788 int y, 789 unsigned long pixel) 790{ 791 if ((ximage->format == ZPixmap) && (ximage->bits_per_pixel == 8)) { 792 ximage->data[y * ximage->bytes_per_line + x] = pixel; 793 return 1; 794 } else { 795 _XInitImageFuncPtrs(ximage); 796 return XPutPixel(ximage, x, y, pixel); 797 } 798} 799 800static int _XPutPixel1 ( 801 register XImage *ximage, 802 int x, 803 int y, 804 unsigned long pixel) 805{ 806 unsigned char bit; 807 int xoff, yoff; 808 809 if (((ximage->bits_per_pixel | ximage->depth) == 1) && 810 (ximage->byte_order == ximage->bitmap_bit_order)) { 811 xoff = x + ximage->xoffset; 812 yoff = y * ximage->bytes_per_line + (xoff >> 3); 813 xoff &= 7; 814 if (ximage->bitmap_bit_order == MSBFirst) 815 bit = 0x80 >> xoff; 816 else 817 bit = 1 << xoff; 818 if (pixel & 1) 819 ximage->data[yoff] |= bit; 820 else 821 ximage->data[yoff] &= ~bit; 822 return 1; 823 } else { 824 _XInitImageFuncPtrs(ximage); 825 return XPutPixel(ximage, x, y, pixel); 826 } 827} 828 829/* 830 * SubImage 831 * 832 * Creates a new image that is a subsection of an existing one. 833 * Allocates the memory necessary for the new XImage data structure. 834 * Pointer to new image is returned. The algorithm used is repetitive 835 * calls to get and put pixel. 836 * 837 */ 838 839static XImage *_XSubImage ( 840 XImage *ximage, 841 register int x, /* starting x coordinate in existing image */ 842 register int y, /* starting y coordinate in existing image */ 843 unsigned int width, /* width in pixels of new subimage */ 844 unsigned int height)/* height in pixels of new subimage */ 845 846{ 847 register XImage *subimage; 848 int dsize; 849 register int row, col; 850 register unsigned long pixel; 851 char *data; 852 853 if ((subimage = (XImage *) Xcalloc (1, sizeof (XImage))) == NULL) 854 return (XImage *) NULL; 855 subimage->width = width; 856 subimage->height = height; 857 subimage->xoffset = 0; 858 subimage->format = ximage->format; 859 subimage->byte_order = ximage->byte_order; 860 subimage->bitmap_unit = ximage->bitmap_unit; 861 subimage->bitmap_bit_order = ximage->bitmap_bit_order; 862 subimage->bitmap_pad = ximage->bitmap_pad; 863 subimage->bits_per_pixel = ximage->bits_per_pixel; 864 subimage->depth = ximage->depth; 865 /* 866 * compute per line accelerator. 867 */ 868 if (subimage->format == ZPixmap) 869 subimage->bytes_per_line = 870 ROUNDUP(subimage->bits_per_pixel * width, 871 subimage->bitmap_pad); 872 else 873 subimage->bytes_per_line = 874 ROUNDUP(width, subimage->bitmap_pad); 875 subimage->obdata = NULL; 876 _XInitImageFuncPtrs (subimage); 877 dsize = subimage->bytes_per_line * height; 878 if (subimage->format == XYPixmap) dsize = dsize * subimage->depth; 879 if (((data = Xcalloc (1, (unsigned) dsize)) == NULL) && (dsize > 0)) { 880 Xfree((char *) subimage); 881 return (XImage *) NULL; 882 } 883 subimage->data = data; 884 885 /* 886 * Test for cases where the new subimage is larger than the region 887 * that we are copying from the existing data. In those cases, 888 * copy the area of the existing image, and allow the "uncovered" 889 * area of new subimage to remain with zero filled pixels. 890 */ 891 if (height > ximage->height - y ) height = ximage->height - y; 892 if (width > ximage->width - x ) width = ximage->width - x; 893 894 for (row = y; row < (y + height); row++) { 895 for (col = x; col < (x + width); col++) { 896 pixel = XGetPixel(ximage, col, row); 897 XPutPixel(subimage, (col - x), (row - y), pixel); 898 } 899 } 900 return subimage; 901} 902 903 904/* 905 * SetImage 906 * 907 * Overwrites a section of one image with all of the data from another. 908 * If the two images are not of the same format (i.e. XYPixmap and ZPixmap), 909 * the image data is converted to the destination format. The following 910 * restrictions apply: 911 * 912 * 1. The depths of the source and destination images must be equal. 913 * 914 * 2. If the height of the source image is too large to fit between 915 * the specified y starting point and the bottom of the image, 916 * then scanlines are truncated on the bottom. 917 * 918 * 3. If the width of the source image is too large to fit between 919 * the specified x starting point and the end of the scanline, 920 * then pixels are truncated on the right. 921 * 922 * The images need not have the same bitmap_bit_order, byte_order, 923 * bitmap_unit, bits_per_pixel, bitmap_pad, or xoffset. 924 * 925 */ 926 927int _XSetImage( 928 XImage *srcimg, 929 register XImage *dstimg, 930 register int x, 931 register int y) 932{ 933 register unsigned long pixel; 934 register int row, col; 935 int width, height, startrow, startcol; 936 if (x < 0) { 937 startcol = -x; 938 x = 0; 939 } else 940 startcol = 0; 941 if (y < 0) { 942 startrow = -y; 943 y = 0; 944 } else 945 startrow = 0; 946 width = dstimg->width - x; 947 if (srcimg->width < width) 948 width = srcimg->width; 949 height = dstimg->height - y; 950 if (srcimg->height < height) 951 height = srcimg->height; 952 953 /* this is slow, will do better later */ 954 for (row = startrow; row < height; row++) { 955 for (col = startcol; col < width; col++) { 956 pixel = XGetPixel(srcimg, col, row); 957 XPutPixel(dstimg, x + col, y + row, pixel); 958 } 959 } 960 return 1; 961} 962 963/* 964 * AddPixel 965 * 966 * Adds a constant value to every pixel in a pixmap. 967 * 968 */ 969 970static int 971_XAddPixel ( 972 register XImage *ximage, 973 register long value) 974{ 975 register int x; 976 register int y; 977 978 if (!value) 979 return 0; 980 if ((ximage->bits_per_pixel | ximage->depth) == 1) { 981 /* The only value that we can add here to an XYBitmap 982 * is one. Since 1 + value = ~value for one bit wide 983 * data, we do this quickly by taking the ones complement 984 * of the entire bitmap data (offset and pad included!). 985 * Note that we don't need to be concerned with bit or 986 * byte order at all. 987 */ 988 register unsigned char *dp = (unsigned char *) ximage->data; 989 x = ximage->bytes_per_line * ximage->height; 990 while (--x >= 0) { 991 *dp = ~*dp; 992 dp++; 993 } 994 } else if ((ximage->format == ZPixmap) && 995 (ximage->bits_per_pixel == 8)) { 996 register unsigned char *dp = (unsigned char *) ximage->data; 997 x = ximage->bytes_per_line * ximage->height; 998 while (--x >= 0) 999 *dp++ += value; 1000#ifndef WORD64 1001 } else if ((ximage->format == ZPixmap) && 1002 (ximage->bits_per_pixel == 16) && 1003 (*((const char *)&byteorderpixel) == ximage->byte_order)) { 1004 register unsigned short *dp = (unsigned short *) ximage->data; 1005 x = (ximage->bytes_per_line >> 1) * ximage->height; 1006 while (--x >= 0) 1007 *dp++ += value; 1008 } else if ((ximage->format == ZPixmap) && 1009 (ximage->bits_per_pixel == 32) && 1010 (*((const char *)&byteorderpixel) == ximage->byte_order)) { 1011 register CARD32 *dp = (CARD32 *) ximage->data; 1012 x = (ximage->bytes_per_line >> 2) * ximage->height; 1013 while (--x >= 0) 1014 *dp++ += value; 1015#endif 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