| File: | src/ImUtil.c |
| Location: | line 811, column 22 |
| Description: | Array access (via field 'data') results in a null pointer dereference |
| 1 | /* | |||
| 2 | ||||
| 3 | Copyright 1986, 1998 The Open Group | |||
| 4 | ||||
| 5 | Permission to use, copy, modify, distribute, and sell this software and its | |||
| 6 | documentation for any purpose is hereby granted without fee, provided that | |||
| 7 | the above copyright notice appear in all copies and that both that | |||
| 8 | copyright notice and this permission notice appear in supporting | |||
| 9 | documentation. | |||
| 10 | ||||
| 11 | The above copyright notice and this permission notice shall be included in | |||
| 12 | all copies or substantial portions of the Software. | |||
| 13 | ||||
| 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| 17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||
| 18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
| 19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
| 20 | ||||
| 21 | Except as contained in this notice, the name of The Open Group shall not be | |||
| 22 | used in advertising or otherwise to promote the sale, use or other dealings | |||
| 23 | in this Software without prior written authorization from The Open Group. | |||
| 24 | ||||
| 25 | */ | |||
| 26 | ||||
| 27 | #ifdef HAVE_CONFIG_H1 | |||
| 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 | ||||
| 35 | static int _XDestroyImage(XImage *); | |||
| 36 | static unsigned long _XGetPixel(XImage *, int, int); | |||
| 37 | static unsigned long _XGetPixel1(XImage *, int, int); | |||
| 38 | static unsigned long _XGetPixel8(XImage *, int, int); | |||
| 39 | static unsigned long _XGetPixel16(XImage *, int, int); | |||
| 40 | static unsigned long _XGetPixel32(XImage *, int, int); | |||
| 41 | static int _XPutPixel(XImage *, int, int, unsigned long); | |||
| 42 | static int _XPutPixel1(XImage *, int, int, unsigned long); | |||
| 43 | static int _XPutPixel8(XImage *, int, int, unsigned long); | |||
| 44 | static int _XPutPixel16(XImage *, int, int, unsigned long); | |||
| 45 | static int _XPutPixel32(XImage *, int, int, unsigned long); | |||
| 46 | static XImage *_XSubImage(XImage *, int, int, unsigned int, unsigned int); | |||
| 47 | static int _XAddPixel(XImage *, long); | |||
| 48 | ||||
| 49 | static unsigned char const _lomask[0x09] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff }; | |||
| 50 | static 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 | ||||
| 56 | int | |||
| 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 | ||||
| 71 | int | |||
| 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 | */ | |||
| 121 | static 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 == MSBFirst1) | |||
| 147 | _XReverse_Bytes (bp, img->bitmap_unit >> 3); | |||
| 148 | } | |||
| 149 | ||||
| 150 | static 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 | ||||
| 184 | static 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)) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) | |||
| 246 | ||||
| 247 | #define XYNORMALIZE(bp, img)if ((img->byte_order == 1) || (img->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(bp), img) \ | |||
| 248 | if ((img->byte_order == MSBFirst1) || (img->bitmap_bit_order == MSBFirst1)) \ | |||
| 249 | _xynormalizeimagebits((unsigned char *)(bp), img) | |||
| 250 | ||||
| 251 | #define ZNORMALIZE(bp, img)if (img->byte_order == 1) _znormalizeimagebits((unsigned char *)(bp), img) \ | |||
| 252 | if (img->byte_order == MSBFirst1) \ | |||
| 253 | _znormalizeimagebits((unsigned char *)(bp), img) | |||
| 254 | ||||
| 255 | #define XYINDEX(x, y, img)((y) * img->bytes_per_line) + (((x) + img->xoffset) / img ->bitmap_unit) * (img->bitmap_unit >> 3) \ | |||
| 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) + (((x) * img->bits_per_pixel ) >> 3) ((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 | */ | |||
| 271 | void _XInitImageFuncPtrs ( | |||
| 272 | register XImage *image) | |||
| 273 | { | |||
| 274 | image->f.create_image = XCreateImage; | |||
| 275 | image->f.destroy_image = _XDestroyImage; | |||
| 276 | if ((image->format == ZPixmap2) && (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 == ZPixmap2) && | |||
| 284 | (image->bits_per_pixel == 32)) { | |||
| 285 | image->f.get_pixel = _XGetPixel32; | |||
| 286 | image->f.put_pixel = _XPutPixel32; | |||
| 287 | } else if ((image->format == ZPixmap2) && | |||
| 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 | ||||
| 308 | XImage *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 != XYBitmap0 && format != XYPixmap1 && format != ZPixmap2) || | |||
| 331 | (format == XYBitmap0 && depth != 1) || | |||
| 332 | (xpad != 8 && xpad != 16 && xpad != 32) || | |||
| 333 | offset < 0) | |||
| 334 | return (XImage *) NULL((void*)0); | |||
| 335 | if ((image = Xcalloc(1, sizeof(XImage))calloc(((1) == 0 ? 1 : (1)), (sizeof(XImage)))) == NULL((void*)0)) | |||
| 336 | return (XImage *) NULL((void*)0); | |||
| 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((void*)0)) { | |||
| 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 == ZPixmap2) | |||
| 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 == ZPixmap2) | |||
| 366 | min_bytes_per_line = | |||
| 367 | ROUNDUP((bits_per_pixel * width), image->bitmap_pad)(((((bits_per_pixel * width)) + ((image->bitmap_pad)-1)) / (image->bitmap_pad)) * ((image->bitmap_pad)>>3)); | |||
| 368 | else | |||
| 369 | min_bytes_per_line = | |||
| 370 | ROUNDUP((width + offset), image->bitmap_pad)(((((width + offset)) + ((image->bitmap_pad)-1)) / (image-> bitmap_pad)) * ((image->bitmap_pad)>>3)); | |||
| 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)free((image)); | |||
| 376 | return NULL((void*)0); | |||
| 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((void*)0); | |||
| 383 | _XInitImageFuncPtrs (image); | |||
| 384 | ||||
| 385 | return image; | |||
| 386 | } | |||
| 387 | ||||
| 388 | Statusint 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 != XYBitmap0 && | |||
| 396 | image->format != XYPixmap1 && | |||
| 397 | image->format != ZPixmap2) || | |||
| 398 | (image->format == XYBitmap0 && 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 == ZPixmap2) | |||
| 409 | min_bytes_per_line = | |||
| 410 | ROUNDUP((image->bits_per_pixel * image->width),(((((image->bits_per_pixel * image->width)) + ((image-> bitmap_pad)-1)) / (image->bitmap_pad)) * ((image->bitmap_pad )>>3)) | |||
| 411 | image->bitmap_pad)(((((image->bits_per_pixel * image->width)) + ((image-> bitmap_pad)-1)) / (image->bitmap_pad)) * ((image->bitmap_pad )>>3)); | |||
| 412 | else | |||
| 413 | min_bytes_per_line = | |||
| 414 | ROUNDUP((image->width + image->xoffset), image->bitmap_pad)(((((image->width + image->xoffset)) + ((image->bitmap_pad )-1)) / (image->bitmap_pad)) * ((image->bitmap_pad)>> 3)); | |||
| 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 | ||||
| 435 | static int _XDestroyImage (XImage *ximage) | |||
| 436 | { | |||
| 437 | Xfree(ximage->data)free((ximage->data)); | |||
| 438 | Xfree(ximage->obdata)free((ximage->obdata)); | |||
| 439 | Xfree(ximage)free((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 | ||||
| 458 | static 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 | ||||
| 470 | static 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)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3)]; | |||
| 485 | dst = (char *)&pixel; | |||
| 486 | pixel = 0; | |||
| 487 | for (i = ximage->bitmap_unit >> 3; --i >= 0; ) *dst++ = *src++; | |||
| 488 | XYNORMALIZE(&pixel, ximage)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&pixel), ximage ); | |||
| 489 | bits = (x + ximage->xoffset) % ximage->bitmap_unit; | |||
| 490 | pixel = ((((char *)&pixel)[bits>>3])>>(bits&7)) & 1; | |||
| 491 | } else if (ximage->format == XYPixmap1) { | |||
| 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)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3)+ plane]; | |||
| 497 | dst = (char *)&px; | |||
| 498 | px = 0; | |||
| 499 | for (j = nbytes; --j >= 0; ) *dst++ = *src++; | |||
| 500 | XYNORMALIZE(&px, ximage)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&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 == ZPixmap2) { | |||
| 507 | src = &ximage->data[ZINDEX(x, y, ximage)((y) * ximage->bytes_per_line) + (((x) * ximage->bits_per_pixel ) >> 3)]; | |||
| 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)if (ximage->byte_order == 1) _znormalizeimagebits((unsigned char *)(&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 | static CARD32 const byteorderpixel = MSBFirst1 << 24; | |||
| 532 | ||||
| 533 | static 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 == ZPixmap2) && (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 == MSBFirst1) | |||
| 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)((*((ximage)->f.get_pixel))((ximage), (x), (y))); | |||
| 562 | } | |||
| 563 | } | |||
| 564 | ||||
| 565 | static 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 == ZPixmap2) && (ximage->bits_per_pixel == 16)) { | |||
| 574 | addr = &((unsigned char *)ximage->data) | |||
| 575 | [y * ximage->bytes_per_line + (x << 1)]; | |||
| 576 | if (ximage->byte_order == MSBFirst1) | |||
| 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)((*((ximage)->f.get_pixel))((ximage), (x), (y))); | |||
| 586 | } | |||
| 587 | } | |||
| 588 | ||||
| 589 | static unsigned long _XGetPixel8 ( | |||
| 590 | register XImage *ximage, | |||
| 591 | int x, | |||
| 592 | int y) | |||
| 593 | { | |||
| 594 | unsigned char pixel; | |||
| 595 | ||||
| 596 | if ((ximage->format == ZPixmap2) && (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)((*((ximage)->f.get_pixel))((ximage), (x), (y))); | |||
| 605 | } | |||
| 606 | } | |||
| 607 | ||||
| 608 | static 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 == MSBFirst1) | |||
| 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)((*((ximage)->f.get_pixel))((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 | ||||
| 648 | static 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)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3)]; | |||
| 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)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&px), ximage ); | |||
| 674 | i = ((x + ximage->xoffset) % ximage->bitmap_unit); | |||
| 675 | _putbits ((char *)&pixel, i, 1, (char *)&px); | |||
| 676 | XYNORMALIZE(&px, ximage)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&px), ximage ); | |||
| 677 | src = (char *) &px; | |||
| 678 | dst = &ximage->data[XYINDEX(x, y, ximage)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3)]; | |||
| 679 | for (i = nbytes; --i >= 0; ) *dst++ = *src++; | |||
| 680 | } else if (ximage->format == XYPixmap1) { | |||
| 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)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3) + plane]; | |||
| 686 | dst = (char *) &px; | |||
| 687 | px = 0; | |||
| 688 | for (i = nbytes; --i >= 0; ) *dst++ = *src++; | |||
| 689 | XYNORMALIZE(&px, ximage)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&px), ximage ); | |||
| 690 | i = ((x + ximage->xoffset) % ximage->bitmap_unit); | |||
| 691 | _putbits ((char *)&pixel, i, 1, (char *)&px); | |||
| 692 | XYNORMALIZE(&px, ximage)if ((ximage->byte_order == 1) || (ximage->bitmap_bit_order == 1)) _xynormalizeimagebits((unsigned char *)(&px), ximage ); | |||
| 693 | src = (char *)&px; | |||
| 694 | dst = &ximage->data[XYINDEX(x, y, ximage)((y) * ximage->bytes_per_line) + (((x) + ximage->xoffset ) / ximage->bitmap_unit) * (ximage->bitmap_unit >> 3) + 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 == ZPixmap2) { | |||
| 702 | src = &ximage->data[ZINDEX(x, y, ximage)((y) * ximage->bytes_per_line) + (((x) * ximage->bits_per_pixel ) >> 3)]; | |||
| 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)if (ximage->byte_order == 1) _znormalizeimagebits((unsigned char *)(&px), ximage); | |||
| 708 | _putbits ((char *)&pixel, | |||
| 709 | (x * ximage->bits_per_pixel) & 7, | |||
| 710 | ximage->bits_per_pixel, (char *)&px); | |||
| 711 | ZNORMALIZE(&px, ximage)if (ximage->byte_order == 1) _znormalizeimagebits((unsigned char *)(&px), ximage); | |||
| 712 | src = (char *)&px; | |||
| 713 | dst = &ximage->data[ZINDEX(x, y, ximage)((y) * ximage->bytes_per_line) + (((x) * ximage->bits_per_pixel ) >> 3)]; | |||
| 714 | for (i = nbytes; --i >= 0; ) *dst++ = *src++; | |||
| 715 | } else { | |||
| 716 | return 0; /* bad image */ | |||
| 717 | } | |||
| 718 | return 1; | |||
| 719 | } | |||
| 720 | ||||
| 721 | static 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 == ZPixmap2) && (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 == MSBFirst1) { | |||
| 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)((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))); | |||
| 749 | } | |||
| 750 | } | |||
| 751 | ||||
| 752 | static 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 == ZPixmap2) && (ximage->bits_per_pixel == 16)) { | |||
| 761 | addr = &((unsigned char *)ximage->data) | |||
| 762 | [y * ximage->bytes_per_line + (x << 1)]; | |||
| 763 | if (ximage->byte_order == MSBFirst1) { | |||
| 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)((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))); | |||
| 774 | } | |||
| 775 | } | |||
| 776 | ||||
| 777 | static int _XPutPixel8 ( | |||
| 778 | register XImage *ximage, | |||
| 779 | int x, | |||
| 780 | int y, | |||
| 781 | unsigned long pixel) | |||
| 782 | { | |||
| 783 | if ((ximage->format == ZPixmap2) && (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)((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))); | |||
| 789 | } | |||
| 790 | } | |||
| 791 | ||||
| 792 | static 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 == MSBFirst1) | |||
| 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)((*((ximage)->f.put_pixel))((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 | ||||
| 831 | static 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))calloc(((1) == 0 ? 1 : (1)), (sizeof (XImage)))) == NULL((void*)0)) | |||
| ||||
| 846 | return (XImage *) NULL((void*)0); | |||
| 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 == ZPixmap2) | |||
| 861 | subimage->bytes_per_line = | |||
| 862 | ROUNDUP(subimage->bits_per_pixel * width,((((subimage->bits_per_pixel * width) + ((subimage->bitmap_pad )-1)) / (subimage->bitmap_pad)) * ((subimage->bitmap_pad )>>3)) | |||
| 863 | subimage->bitmap_pad)((((subimage->bits_per_pixel * width) + ((subimage->bitmap_pad )-1)) / (subimage->bitmap_pad)) * ((subimage->bitmap_pad )>>3)); | |||
| 864 | else | |||
| 865 | subimage->bytes_per_line = | |||
| 866 | ROUNDUP(width, subimage->bitmap_pad)((((width) + ((subimage->bitmap_pad)-1)) / (subimage->bitmap_pad )) * ((subimage->bitmap_pad)>>3)); | |||
| 867 | subimage->obdata = NULL((void*)0); | |||
| 868 | _XInitImageFuncPtrs (subimage); | |||
| 869 | dsize = subimage->bytes_per_line * height; | |||
| 870 | if (subimage->format == XYPixmap1) dsize = dsize * subimage->depth; | |||
| 871 | if (((data = Xcalloc (1, dsize)calloc(((1) == 0 ? 1 : (1)), (dsize))) == NULL((void*)0)) && (dsize > 0)) { | |||
| 872 | Xfree(subimage)free((subimage)); | |||
| 873 | return (XImage *) NULL((void*)0); | |||
| 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)((*((ximage)->f.get_pixel))((ximage), (col), (row))); | |||
| 889 | XPutPixel(subimage, (col - x), (row - y), pixel)((*((subimage)->f.put_pixel))((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 | ||||
| 919 | int _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)((*((srcimg)->f.get_pixel))((srcimg), (col), (row))); | |||
| 949 | XPutPixel(dstimg, x + col, y + row, pixel)((*((dstimg)->f.put_pixel))((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 | ||||
| 962 | static 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 == ZPixmap2) && | |||
| 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 == ZPixmap2) && | |||
| 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 == ZPixmap2) && | |||
| 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)((*((ximage)->f.get_pixel))((ximage), (x), (y))); | |||
| 1010 | pixel = pixel + value; | |||
| 1011 | XPutPixel(ximage, x, y, pixel)((*((ximage)->f.put_pixel))((ximage), (x), (y), (pixel))); | |||
| 1012 | } | |||
| 1013 | } | |||
| 1014 | } | |||
| 1015 | return 0; | |||
| 1016 | } | |||
| 1017 |