1 /* $Id: image.c,v 1.19 1997/11/07 03:49:04 brianp Exp $ */ 2 3 /* 4 * Mesa 3-D graphics library 5 * Version: 2.5 6 * Copyright (C) 1995-1997 Brian Paul 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public 19 * License along with this library; if not, write to the Free 20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 */ 22 23 24 /* 25 * $Log: image.c,v $ 26 * Revision 1.19 1997/11/07 03:49:04 brianp 27 * more error checking work (but more to be done) 28 * 29 * Revision 1.18 1997/11/02 20:19:47 brianp 30 * added more error checking to gl_unpack_image3D() 31 * 32 * Revision 1.17 1997/10/16 01:04:51 brianp 33 * added code to normalize color, depth values in gl_unpack_image3d() 34 * 35 * Revision 1.16 1997/09/27 00:15:39 brianp 36 * changed parameters to gl_unpack_image() 37 * 38 * Revision 1.15 1997/08/11 01:23:10 brianp 39 * added a pointer cast 40 * 41 * Revision 1.14 1997/07/24 01:25:18 brianp 42 * changed precompiled header symbol from PCH to PC_HEADER 43 * 44 * Revision 1.13 1997/05/28 03:25:26 brianp 45 * added precompiled header (PCH) support 46 * 47 * Revision 1.12 1997/04/29 01:26:25 brianp 48 * added #include "context.h" 49 * 50 * Revision 1.11 1997/04/20 20:28:49 brianp 51 * replaced abort() with gl_problem() 52 * 53 * Revision 1.10 1997/04/06 17:49:32 brianp 54 * image reference count wasn't always initialized to zero (Christopher Lloyd) 55 * 56 * Revision 1.9 1997/02/09 20:05:03 brianp 57 * new arguments for gl_pixel_addr_in_image() 58 * 59 * Revision 1.8 1997/02/09 18:52:53 brianp 60 * added GL_EXT_texture3D support 61 * 62 * Revision 1.7 1997/01/09 21:25:54 brianp 63 * initialize image reference count to zero 64 * 65 * Revision 1.6 1996/11/13 03:58:31 brianp 66 * fixed undefined "format" variable in gl_unpack_image() 67 * 68 * Revision 1.5 1996/11/10 17:48:03 brianp 69 * check if format is GL_DEPTH_COMPONENT or GL_STENCIL_COMPONENT 70 * 71 * Revision 1.4 1996/11/06 04:23:01 brianp 72 * changed gl_unpack_image() components argument to srcFormat 73 * 74 * Revision 1.3 1996/09/27 01:27:10 brianp 75 * removed unused variables 76 * 77 * Revision 1.2 1996/09/26 22:35:10 brianp 78 * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler 79 * 80 * Revision 1.1 1996/09/13 01:38:16 brianp 81 * Initial revision 82 * 83 */ 84 85 86 #ifdef PC_HEADER 87 #include "all.h" 88 #else 89 #include <assert.h> 90 #include <stdio.h> 91 #include <stdlib.h> 92 #include <string.h> 93 #include "context.h" 94 #include "image.h" 95 #include "macros.h" 96 #include "pixel.h" 97 #include "types.h" 98 #endif 99 100 101 102 /* 103 * Flip the 8 bits in each byte of the given array. 104 */ 105 void gl_flip_bytes( GLubyte *p, GLuint n ) 106 { 107 register GLuint i, a, b; 108 109 for (i=0;i<n;i++) { 110 b = (GLuint) p[i]; 111 a = ((b & 0x01) << 7) | 112 ((b & 0x02) << 5) | 113 ((b & 0x04) << 3) | 114 ((b & 0x08) << 1) | 115 ((b & 0x10) >> 1) | 116 ((b & 0x20) >> 3) | 117 ((b & 0x40) >> 5) | 118 ((b & 0x80) >> 7); 119 p[i] = (GLubyte) a; 120 } 121 } 122 123 124 /* 125 * Flip the order of the 2 bytes in each word in the given array. 126 */ 127 void gl_swap2( GLushort *p, GLuint n ) 128 { 129 register GLuint i; 130 131 for (i=0;i<n;i++) { 132 p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); 133 } 134 } 135 136 137 138 /* 139 * Flip the order of the 4 bytes in each word in the given array. 140 */ 141 void gl_swap4( GLuint *p, GLuint n ) 142 { 143 register GLuint i, a, b; 144 145 for (i=0;i<n;i++) { 146 b = p[i]; 147 a = (b >> 24) 148 | ((b >> 8) & 0xff00) 149 | ((b << 8) & 0xff0000) 150 | ((b << 24) & 0xff000000); 151 p[i] = a; 152 } 153 } 154 155 156 157 158 /* 159 * Return the size, in bytes, of the given GL datatype. 160 * Return 0 if GL_BITMAP. 161 * Return -1 if invalid type enum. 162 */ 163 GLint gl_sizeof_type( GLenum type ) 164 { 165 switch (type) { 166 case GL_BITMAP: 167 return 0; 168 case GL_UNSIGNED_BYTE: 169 return sizeof(GLubyte); 170 case GL_BYTE: 171 return sizeof(GLbyte); 172 case GL_UNSIGNED_SHORT: 173 return sizeof(GLushort); 174 case GL_SHORT: 175 return sizeof(GLshort); 176 case GL_UNSIGNED_INT: 177 return sizeof(GLuint); 178 case GL_INT: 179 return sizeof(GLint); 180 case GL_FLOAT: 181 return sizeof(GLfloat); 182 default: 183 return -1; 184 } 185 } 186 187 188 189 /* 190 * Return the number of components in a GL enum pixel type. 191 * Return -1 if bad format. 192 */ 193 GLint gl_components_in_format( GLenum format ) 194 { 195 switch (format) { 196 case GL_COLOR_INDEX: 197 case GL_STENCIL_INDEX: 198 case GL_DEPTH_COMPONENT: 199 case GL_RED: 200 case GL_GREEN: 201 case GL_BLUE: 202 case GL_ALPHA: 203 case GL_LUMINANCE: 204 return 1; 205 case GL_LUMINANCE_ALPHA: 206 return 2; 207 case GL_RGB: 208 case GL_BGR_EXT: 209 return 3; 210 case GL_RGBA: 211 case GL_BGRA_EXT: 212 return 4; 213 default: 214 return -1; 215 } 216 } 217 218 219 /* 220 * Return the address of a pixel in an image (actually a volume). 221 * Pixel unpacking/packing parameters are observed according to 'packing'. 222 * Input: image - start of image data 223 * width, height - size of image 224 * format - image format 225 * type - pixel component type 226 * packing - GL_TRUE = use packing params 227 * GL_FALSE = use unpacking params. 228 * img - which image in the volume (0 for 2-D images) 229 * row, column - location of pixel in the image 230 * Return: address of pixel at (image,row,column) in image or NULL if error. 231 */ 232 GLvoid *gl_pixel_addr_in_image( struct gl_pixelstore_attrib *packing, 233 const GLvoid *image, GLsizei width, 234 GLsizei height, GLenum format, GLenum type, 235 GLint row) 236 { 237 GLint bytes_per_comp; /* bytes per component */ 238 GLint comp_per_pixel; /* components per pixel */ 239 GLint comps_per_row; /* components per row */ 240 GLint pixels_per_row; /* pixels per row */ 241 GLint alignment; /* 1, 2 or 4 */ 242 GLint skiprows; 243 GLint skippixels; 244 GLubyte *pixel_addr; 245 246 /* Compute bytes per component */ 247 bytes_per_comp = gl_sizeof_type( type ); 248 if (bytes_per_comp<0) { 249 return NULL; 250 } 251 252 /* Compute number of components per pixel */ 253 comp_per_pixel = gl_components_in_format( format ); 254 if (comp_per_pixel<0) { 255 return NULL; 256 } 257 258 alignment = packing->Alignment; 259 if (packing->RowLength>0) { 260 pixels_per_row = packing->RowLength; 261 } 262 else { 263 pixels_per_row = width; 264 } 265 skiprows = packing->SkipRows; 266 skippixels = packing->SkipPixels; 267 268 if (type==GL_BITMAP) { 269 /* BITMAP data */ 270 GLint bytes_per_row; 271 272 bytes_per_row = alignment 273 * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); 274 275 pixel_addr = (GLubyte *) image 276 + (skiprows + row) * bytes_per_row 277 + (skippixels) / 8; 278 } 279 else { 280 /* Non-BITMAP data */ 281 282 if (bytes_per_comp>=alignment) { 283 comps_per_row = comp_per_pixel * pixels_per_row; 284 } 285 else { 286 GLint bytes_per_row = bytes_per_comp * comp_per_pixel 287 * pixels_per_row; 288 289 comps_per_row = alignment / bytes_per_comp 290 * CEILING( bytes_per_row, alignment ); 291 } 292 293 /* Copy/unpack pixel data to buffer */ 294 pixel_addr = (GLubyte *) image 295 + (skiprows + row) * bytes_per_comp * comps_per_row 296 + (skippixels) * bytes_per_comp * comp_per_pixel; 297 } 298 299 return (GLvoid *) pixel_addr; 300 } 301 302 303 304 /* 305 * Unpack a 2-D image from user-supplied address, returning a pointer to 306 * a new gl_image struct. 307 * 308 * Input: width, height - size in pixels 309 * srcFormat - format of incoming pixel data, ignored if 310 * srcType BITMAP. 311 * srcType - GL_UNSIGNED_BYTE .. GL_FLOAT 312 * pixels - pointer to unpacked image in client memory space. 313 */ 314 struct gl_image *gl_unpack_image( GLcontext *ctx, 315 GLint width, GLint height, 316 GLenum srcFormat, GLenum srcType, 317 const GLvoid *pixels ) 318 { 319 GLint components; 320 GLenum destType; 321 322 if (srcType==GL_UNSIGNED_BYTE) { 323 destType = GL_UNSIGNED_BYTE; 324 } 325 else if (srcType==GL_BITMAP) { 326 destType = GL_BITMAP; 327 } 328 else { 329 destType = GL_FLOAT; 330 } 331 332 components = gl_components_in_format( srcFormat ); 333 334 if (components < 0) 335 return NULL; 336 337 if (srcType==GL_BITMAP || destType==GL_BITMAP) { 338 struct gl_image *image; 339 GLint bytes, i, width_in_bytes; 340 GLubyte *buffer, *dst; 341 assert( srcType==GL_BITMAP ); 342 assert( destType==GL_BITMAP ); 343 344 /* Alloc dest storage */ 345 if (width > 0 && height > 0) 346 bytes = ((width+7)/8 * height); 347 else 348 bytes = 0; 349 if (bytes>0 && pixels!=NULL) { 350 buffer = (GLubyte *) malloc( bytes ); 351 if (!buffer) { 352 return NULL; 353 } 354 /* Copy/unpack pixel data to buffer */ 355 width_in_bytes = CEILING( width, 8 ); 356 dst = buffer; 357 for (i=0; i<height; i++) { 358 GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, 359 width, height, 360 GL_COLOR_INDEX, srcType, 361 i); 362 if (!src) { 363 free(buffer); 364 return NULL; 365 } 366 MEMCPY( dst, src, width_in_bytes ); 367 dst += width_in_bytes; 368 } 369 /* Bit flipping */ 370 if (ctx->Unpack.LsbFirst) { 371 gl_flip_bytes( buffer, bytes ); 372 } 373 } 374 else { 375 /* a 'null' bitmap */ 376 buffer = NULL; 377 } 378 379 image = (struct gl_image *) malloc( sizeof(struct gl_image) ); 380 if (image) { 381 image->Width = width; 382 image->Height = height; 383 image->Components = 0; 384 image->Format = GL_COLOR_INDEX; 385 image->Type = GL_BITMAP; 386 image->Data = buffer; 387 image->RefCount = 0; 388 } 389 else { 390 if (buffer) 391 free( buffer ); 392 return NULL; 393 } 394 return image; 395 } 396 else if (srcFormat==GL_DEPTH_COMPONENT) { 397 /* TODO: pack as GLdepth values (GLushort or GLuint) */ 398 399 } 400 else if (srcFormat==GL_STENCIL_INDEX) { 401 /* TODO: pack as GLstencil (GLubyte or GLushort) */ 402 403 } 404 else if (destType==GL_UNSIGNED_BYTE) { 405 struct gl_image *image; 406 GLint width_in_bytes; 407 GLubyte *buffer, *dst; 408 GLint i; 409 assert( srcType==GL_UNSIGNED_BYTE ); 410 411 width_in_bytes = width * components * sizeof(GLubyte); 412 buffer = (GLubyte *) malloc( height * width_in_bytes ); 413 if (!buffer) { 414 return NULL; 415 } 416 /* Copy/unpack pixel data to buffer */ 417 dst = buffer; 418 for (i=0;i<height;i++) { 419 GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( &ctx->Unpack, 420 pixels, width, height, srcFormat, srcType, i); 421 if (!src) { 422 free(buffer); 423 return NULL; 424 } 425 MEMCPY( dst, src, width_in_bytes ); 426 dst += width_in_bytes; 427 } 428 429 if (ctx->Unpack.LsbFirst) { 430 gl_flip_bytes( buffer, height * width_in_bytes ); 431 } 432 433 image = (struct gl_image *) malloc( sizeof(struct gl_image) ); 434 if (image) { 435 image->Width = width; 436 image->Height = height; 437 image->Components = components; 438 image->Format = srcFormat; 439 image->Type = GL_UNSIGNED_BYTE; 440 image->Data = buffer; 441 image->RefCount = 0; 442 } 443 else { 444 free( buffer ); 445 return NULL; 446 } 447 return image; 448 } 449 else if (destType==GL_FLOAT) { 450 struct gl_image *image; 451 GLfloat *buffer, *dst; 452 GLint elems_per_row; 453 GLint i, j; 454 GLboolean normalize; 455 elems_per_row = width * components; 456 buffer = (GLfloat *) malloc( height * elems_per_row * sizeof(GLfloat)); 457 if (!buffer) { 458 return NULL; 459 } 460 461 normalize = (srcFormat != GL_COLOR_INDEX) 462 && (srcFormat != GL_STENCIL_INDEX); 463 464 dst = buffer; 465 /** img_pixels= pixels;*/ 466 for (i=0;i<height;i++) { 467 GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, 468 width, height, 469 srcFormat, srcType, 470 i); 471 if (!src) { 472 free(buffer); 473 return NULL; 474 } 475 476 switch (srcType) { 477 case GL_UNSIGNED_BYTE: 478 if (normalize) { 479 for (j=0;j<elems_per_row;j++) { 480 *dst++ = UBYTE_TO_FLOAT(((GLubyte*)src)[j]); 481 } 482 } 483 else { 484 for (j=0;j<elems_per_row;j++) { 485 *dst++ = (GLfloat) ((GLubyte*)src)[j]; 486 } 487 } 488 break; 489 case GL_BYTE: 490 if (normalize) { 491 for (j=0;j<elems_per_row;j++) { 492 *dst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]); 493 } 494 } 495 else { 496 for (j=0;j<elems_per_row;j++) { 497 *dst++ = (GLfloat) ((GLbyte*)src)[j]; 498 } 499 } 500 break; 501 case GL_UNSIGNED_SHORT: 502 if (ctx->Unpack.SwapBytes) { 503 for (j=0;j<elems_per_row;j++) { 504 GLushort value = ((GLushort*)src)[j]; 505 value = ((value >> 8) & 0xff) | ((value&0xff) << 8); 506 if (normalize) { 507 *dst++ = USHORT_TO_FLOAT(value); 508 } 509 else { 510 *dst++ = (GLfloat) value; 511 } 512 } 513 } 514 else { 515 if (normalize) { 516 for (j=0;j<elems_per_row;j++) { 517 *dst++ = USHORT_TO_FLOAT(((GLushort*)src)[j]); 518 } 519 } 520 else { 521 for (j=0;j<elems_per_row;j++) { 522 *dst++ = (GLfloat) ((GLushort*)src)[j]; 523 } 524 } 525 } 526 break; 527 case GL_SHORT: 528 if (ctx->Unpack.SwapBytes) { 529 for (j=0;j<elems_per_row;j++) { 530 GLshort value = ((GLshort*)src)[j]; 531 value = ((value >> 8) & 0xff) | ((value&0xff) << 8); 532 if (normalize) { 533 *dst++ = SHORT_TO_FLOAT(value); 534 } 535 else { 536 *dst++ = (GLfloat) value; 537 } 538 } 539 } 540 else { 541 if (normalize) { 542 for (j=0;j<elems_per_row;j++) { 543 *dst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]); 544 } 545 } 546 else { 547 for (j=0;j<elems_per_row;j++) { 548 *dst++ = (GLfloat) ((GLshort*)src)[j]; 549 } 550 } 551 } 552 break; 553 case GL_UNSIGNED_INT: 554 if (ctx->Unpack.SwapBytes) { 555 GLuint value; 556 for (j=0;j<elems_per_row;j++) { 557 value = ((GLuint*)src)[j]; 558 value = ((value & 0xff000000) >> 24) 559 | ((value & 0x00ff0000) >> 8) 560 | ((value & 0x0000ff00) << 8) 561 | ((value & 0x000000ff) << 24); 562 if (normalize) { 563 *dst++ = UINT_TO_FLOAT(value); 564 } 565 else { 566 *dst++ = (GLfloat) value; 567 } 568 } 569 } 570 else { 571 if (normalize) { 572 for (j=0;j<elems_per_row;j++) { 573 *dst++ = UINT_TO_FLOAT(((GLuint*)src)[j]); 574 } 575 } 576 else { 577 for (j=0;j<elems_per_row;j++) { 578 *dst++ = (GLfloat) ((GLuint*)src)[j]; 579 } 580 } 581 } 582 break; 583 case GL_INT: 584 if (ctx->Unpack.SwapBytes) { 585 GLint value; 586 for (j=0;j<elems_per_row;j++) { 587 value = ((GLint*)src)[j]; 588 value = ((value & 0xff000000) >> 24) 589 | ((value & 0x00ff0000) >> 8) 590 | ((value & 0x0000ff00) << 8) 591 | ((value & 0x000000ff) << 24); 592 if (normalize) { 593 *dst++ = INT_TO_FLOAT(value); 594 } 595 else { 596 *dst++ = (GLfloat) value; 597 } 598 } 599 } 600 else { 601 if (normalize) { 602 for (j=0;j<elems_per_row;j++) { 603 *dst++ = INT_TO_FLOAT(((GLint*)src)[j]); 604 } 605 } 606 else { 607 for (j=0;j<elems_per_row;j++) { 608 *dst++ = (GLfloat) ((GLint*)src)[j]; 609 } 610 } 611 } 612 break; 613 case GL_FLOAT: 614 if (ctx->Unpack.SwapBytes) { 615 GLint value; 616 for (j=0;j<elems_per_row;j++) { 617 value = ((GLuint*)src)[j]; 618 value = ((value & 0xff000000) >> 24) 619 | ((value & 0x00ff0000) >> 8) 620 | ((value & 0x0000ff00) << 8) 621 | ((value & 0x000000ff) << 24); 622 *dst++ = *((GLfloat*) &value); 623 } 624 } 625 else { 626 MEMCPY( dst, src, elems_per_row*sizeof(GLfloat) ); 627 dst += elems_per_row; 628 } 629 break; 630 default: 631 gl_problem(ctx, "Bad type in gl_unpack_image3D"); 632 return NULL; 633 } /*switch*/ 634 } /* for height */ 635 636 image = (struct gl_image *) malloc( sizeof(struct gl_image) ); 637 if (image) { 638 image->Width = width; 639 image->Height = height; 640 image->Components = components; 641 image->Format = srcFormat; 642 image->Type = GL_FLOAT; 643 image->Data = buffer; 644 image->RefCount = 0; 645 } 646 else { 647 free( buffer ); 648 return NULL; 649 } 650 return image; 651 } 652 else { 653 gl_problem(ctx, "Bad dest type in gl_unpack_image3D"); 654 return NULL; 655 } 656 return NULL; /* never get here */ 657 } 658 659 660 661 void gl_free_image( struct gl_image *image ) 662 { 663 if (image->Data) { 664 free(image->Data); 665 } 666 free(image); 667 } 668