This is image.c in view mode; [Download] [Up]
/* $Id: image.c,v 1.13 1997/05/28 03:25:26 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.3 * Copyright (C) 1995-1997 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: image.c,v $ * Revision 1.13 1997/05/28 03:25:26 brianp * added precompiled header (PCH) support * * Revision 1.12 1997/04/29 01:26:25 brianp * added #include "context.h" * * Revision 1.11 1997/04/20 20:28:49 brianp * replaced abort() with gl_problem() * * Revision 1.10 1997/04/06 17:49:32 brianp * image reference count wasn't always initialized to zero (Christopher Lloyd) * * Revision 1.9 1997/02/09 20:05:03 brianp * new arguments for gl_pixel_addr_in_image() * * Revision 1.8 1997/02/09 18:52:53 brianp * added GL_EXT_texture3D support * * Revision 1.7 1997/01/09 21:25:54 brianp * initialize image reference count to zero * * Revision 1.6 1996/11/13 03:58:31 brianp * fixed undefined "format" variable in gl_unpack_image() * * Revision 1.5 1996/11/10 17:48:03 brianp * check if format is GL_DEPTH_COMPONENT or GL_STENCIL_COMPONENT * * Revision 1.4 1996/11/06 04:23:01 brianp * changed gl_unpack_image() components argument to srcFormat * * Revision 1.3 1996/09/27 01:27:10 brianp * removed unused variables * * Revision 1.2 1996/09/26 22:35:10 brianp * fixed a few compiler warnings from IRIX 6 -n32 and -64 compiler * * Revision 1.1 1996/09/13 01:38:16 brianp * Initial revision * */ #ifdef PCH #include "all.h" #else #include <assert.h> #include <stdlib.h> #include <string.h> #include "context.h" #include "image.h" #include "macros.h" #include "pixel.h" #include "types.h" #endif /* * Flip the 8 bits in each byte of the given array. */ void gl_flip_bytes( GLubyte *p, GLuint n ) { register GLuint i, a, b; for (i=0;i<n;i++) { b = (GLuint) p[i]; a = ((b & 0x01) << 7) | ((b & 0x02) << 5) | ((b & 0x04) << 3) | ((b & 0x08) << 1) | ((b & 0x10) >> 1) | ((b & 0x20) >> 3) | ((b & 0x40) >> 5) | ((b & 0x80) >> 7); p[i] = (GLubyte) a; } } /* * Flip the order of the 2 bytes in each word in the given array. */ void gl_swap2( GLushort *p, GLuint n ) { register GLuint i; for (i=0;i<n;i++) { p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00); } } /* * Flip the order of the 4 bytes in each word in the given array. */ void gl_swap4( GLuint *p, GLuint n ) { register GLuint i, a, b; for (i=0;i<n;i++) { b = p[i]; a = (b >> 24) | ((b >> 8) & 0xff00) | ((b << 8) & 0xff0000) | ((b << 24) & 0xff000000); p[i] = a; } } /* * Return the size, in bytes, of the given GL datatype. * Return 0 if GL_BITMAP. * Return -1 if invalid type enum. */ GLint gl_sizeof_type( GLenum type ) { switch (type) { case GL_BITMAP: return 0; case GL_UNSIGNED_BYTE: return sizeof(GLubyte); case GL_BYTE: return sizeof(GLbyte); case GL_UNSIGNED_SHORT: return sizeof(GLushort); case GL_SHORT: return sizeof(GLshort); case GL_UNSIGNED_INT: return sizeof(GLuint); case GL_INT: return sizeof(GLint); case GL_FLOAT: return sizeof(GLfloat); default: return -1; } } /* * Return the number of components in a GL enum pixel type. * Return -1 if bad format. */ GLint gl_components_in_format( GLenum format ) { switch (format) { case GL_COLOR_INDEX: case GL_STENCIL_INDEX: case GL_DEPTH_COMPONENT: case GL_RED: case GL_GREEN: case GL_BLUE: case GL_ALPHA: case GL_LUMINANCE: return 1; case GL_LUMINANCE_ALPHA: return 2; case GL_RGB: return 3; case GL_RGBA: return 4; default: return -1; } } /* * Return the address of a pixel in an image (actually a volume). * Pixel unpacking/packing parameters are observed according to 'packing'. * Input: image - start of image data * width, height - size of image * format - image format * type - pixel component type * packing - GL_TRUE = use packing params * GL_FALSE = use unpacking params. * img - which image in the volume (0 for 2-D images) * row, column - location of pixel in the image * Return: address of pixel at (image,row,column) in image or NULL if error. */ GLvoid *gl_pixel_addr_in_image( struct gl_pixelstore_attrib *packing, const GLvoid *image, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint img, GLint row, GLint column ) { GLint bytes_per_comp; /* bytes per component */ GLint comp_per_pixel; /* components per pixel */ GLint comps_per_row; /* components per row */ GLint pixels_per_row; /* pixels per row */ GLint bytes_per_image; GLint rows_per_image; GLint alignment; /* 1, 2 or 4 */ GLint skiprows; GLint skippixels; GLint skipimages; /* for 3-D */ GLubyte *pixel_addr; /* Compute bytes per component */ bytes_per_comp = gl_sizeof_type( type ); if (bytes_per_comp<0) { return NULL; } /* Compute number of components per pixel */ comp_per_pixel = gl_components_in_format( format ); if (comp_per_pixel<0) { return NULL; } alignment = packing->Alignment; if (packing->RowLength>0) { pixels_per_row = packing->RowLength; } else { pixels_per_row = width; } if (packing->ImageHeight>0) { rows_per_image = packing->ImageHeight; } else { rows_per_image = height; } skiprows = packing->SkipRows; skippixels = packing->SkipPixels; skipimages = packing->SkipImages; if (type==GL_BITMAP) { /* BITMAP data */ GLint bytes_per_row; bytes_per_row = alignment * CEILING( comp_per_pixel*pixels_per_row, 8*alignment ); bytes_per_image = bytes_per_row * rows_per_image; pixel_addr = (GLubyte *) image + (skipimages + img) * bytes_per_image + (skiprows + row) * bytes_per_row + (skippixels + column) / 8; } else { /* Non-BITMAP data */ if (bytes_per_comp>=alignment) { comps_per_row = comp_per_pixel * pixels_per_row; } else { GLint bytes_per_row = bytes_per_comp * comp_per_pixel * pixels_per_row; comps_per_row = alignment / bytes_per_comp * CEILING( bytes_per_row, alignment ); } bytes_per_image = bytes_per_comp * comps_per_row * rows_per_image; /* Copy/unpack pixel data to buffer */ pixel_addr = (GLubyte *) image + (skipimages + img) * bytes_per_image + (skiprows + row) * bytes_per_comp * comps_per_row + (skippixels + column) * bytes_per_comp * comp_per_pixel; } return (GLvoid *) pixel_addr; } /* * Unpack a 2-D image from user-supplied address, returning a pointer to * a new gl_image struct. * This function is always called by a higher-level unpack function such * as gl_unpack_texsubimage() or gl_unpack_bitmap(). * * Input: width, height - size in pixels * srcFormat - format of incoming pixel data, ignored * if srcType and destType is BITMAP. * srcType - GL_UNSIGNED_BYTE .. GL_FLOAT * destType - store image as GL_UNSIGNED_BYTE, GL_FLOAT, or GL_BITMAP. * if GL_UNSIGNED_BYTE, srctype must be GL_UNSIGNED_BYTE. * if GL_BITMAP, srctype must be GL_BITMAP. * interleave - if TRUE, srctype and destType must be GL_UNSIGNED_BYTE * pixels - pointer to unpacked image. */ struct gl_image *gl_unpack_image( GLcontext *ctx, GLint width, GLint height, GLenum srcFormat, GLenum srcType, GLenum destType, const GLvoid *pixels, GLboolean interleave ) { return gl_unpack_image3D(ctx, width, height, 1, srcFormat, srcType, destType, pixels, interleave); } /* * Unpack a 2-D/3-D image from user-supplied address, returning a pointer to * a new gl_image struct. * This function is always called by a higher-level unpack function such * as gl_unpack_texsubimage() or gl_unpack_bitmap(). * * Input: width, height, depth - size in pixels * srcFormat - format of incoming pixel data, ignored * if srcType and destType is BITMAP. * srcType - GL_UNSIGNED_BYTE .. GL_FLOAT * destType - store image as GL_UNSIGNED_BYTE, GL_FLOAT, or GL_BITMAP. * if GL_UNSIGNED_BYTE, srctype must be GL_UNSIGNED_BYTE. * if GL_BITMAP, srctype must be GL_BITMAP. * interleave - if TRUE, srctype and destType must be GL_UNSIGNED_BYTE * pixels - pointer to unpacked image. */ struct gl_image *gl_unpack_image3D( GLcontext *ctx, GLint width, GLint height, GLint depth, GLenum srcFormat, GLenum srcType, GLenum destType, const GLvoid *pixels, GLboolean interleave ) { GLint components; components = gl_components_in_format( srcFormat ); if (srcType==GL_BITMAP || destType==GL_BITMAP) { struct gl_image *image; GLint bytes, i, width_in_bytes, d; GLubyte *buffer, *dst; assert( srcType==GL_BITMAP ); assert( destType==GL_BITMAP ); /* Alloc dest storage */ bytes = ((width+7)/8 * height) * depth; if (bytes>0 && pixels!=NULL) { buffer = (GLubyte *) malloc( bytes ); if (!buffer) { return NULL; } /* Copy/unpack pixel data to buffer */ width_in_bytes = CEILING( width, 8 ); dst = buffer; for (d=0; d<depth; d++) { for (i=0; i<height; i++) { GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height, GL_COLOR_INDEX, srcType, d, i, 0 ); if (!src) { free(buffer); return NULL; } MEMCPY( dst, src, width_in_bytes ); dst += width_in_bytes; } } /* Bit flipping */ if (ctx->Unpack.LsbFirst) { gl_flip_bytes( buffer, bytes ); } } else { /* a 'null' bitmap */ buffer = NULL; } image = (struct gl_image *) malloc( sizeof(struct gl_image) ); if (image) { image->Width = width; image->Height = height; image->Depth = depth; image->Components = 0; image->Format = GL_COLOR_INDEX; image->Type = GL_BITMAP; image->Interleaved = GL_FALSE; image->Data = buffer; image->RefCount = 0; } else { free( buffer ); return NULL; } return image; } else if (srcFormat==GL_DEPTH_COMPONENT) { /* TODO: pack as GLdepth values (GLushort or GLuint) */ } else if (srcFormat==GL_STENCIL_INDEX) { /* TODO: pack as GLstencil (GLubyte or GLushort) */ } else if (destType==GL_UNSIGNED_BYTE) { struct gl_image *image; GLint width_in_bytes; GLubyte *buffer, *dst; GLint i, d; assert( srcType==GL_UNSIGNED_BYTE ); width_in_bytes = width * components * sizeof(GLubyte); buffer = malloc( height * width_in_bytes * depth ); if (!buffer) { return NULL; } /* Copy/unpack pixel data to buffer */ dst = buffer; for (d=0; d<depth; d++ ) { for (i=0;i<height;i++) { GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height, srcFormat, srcType, d, i, 0 ); if (!src) { free(buffer); return NULL; } if (interleave) { GLint j, k; for (j=0;j<width;j++) { for (k=0;k<components;k++) { dst[k*width+j] = src[j*components+k]; } } } else { MEMCPY( dst, src, width_in_bytes ); } dst += width_in_bytes; } } if (ctx->Unpack.LsbFirst) { gl_flip_bytes( buffer, height * width_in_bytes * depth ); } image = (struct gl_image *) malloc( sizeof(struct gl_image) ); if (image) { image->Width = width; image->Height = height; image->Depth = depth; image->Components = components; image->Format = srcFormat; image->Type = GL_UNSIGNED_BYTE; image->Interleaved = interleave; image->Data = buffer; image->RefCount = 0; } else { free( buffer ); return NULL; } return image; } else if (destType==GL_FLOAT) { struct gl_image *image; GLfloat *buffer, *dst; GLint elems_per_row; GLint i, j, d; elems_per_row = width * components; buffer = (GLfloat *) malloc( height * elems_per_row * sizeof(GLfloat) * depth); if (!buffer) { return NULL; } dst = buffer; /** img_pixels= pixels;*/ for (d=0; d<depth; d++) { for (i=0;i<height;i++) { GLvoid *src = gl_pixel_addr_in_image( &ctx->Unpack, pixels, width, height, srcFormat, srcType, d, i, 0 ); if (!src) { free(buffer); return NULL; } switch (srcType) { case GL_UNSIGNED_BYTE: for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLubyte*)src)[j]; } break; case GL_BYTE: for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLbyte*)src)[j]; } break; case GL_UNSIGNED_SHORT: if (ctx->Unpack.SwapBytes) { for (j=0;j<elems_per_row;j++) { GLushort value = ((GLushort*)src)[j]; value = ((value >> 8) & 0xff) | ((value&0xff) << 8); *dst++ = (GLfloat) value; } } else { for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLushort*)src)[j]; } } break; case GL_SHORT: if (ctx->Unpack.SwapBytes) { for (j=0;j<elems_per_row;j++) { GLshort value = ((GLshort*)src)[j]; value = ((value >> 8) & 0xff) | ((value&0xff) << 8); *dst++ = (GLfloat) value; } } else { for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLshort*)src)[j]; } } break; case GL_UNSIGNED_INT: if (ctx->Unpack.SwapBytes) { GLuint value; for (j=0;j<elems_per_row;j++) { value = ((GLuint*)src)[j]; value = ((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8) | ((value & 0x0000ff00) << 8) | ((value & 0x000000ff) << 24); *dst++ = (GLfloat) value; } } else { for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLuint*)src)[j]; } } break; case GL_INT: if (ctx->Unpack.SwapBytes) { GLint value; for (j=0;j<elems_per_row;j++) { value = ((GLint*)src)[j]; value = ((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8) | ((value & 0x0000ff00) << 8) | ((value & 0x000000ff) << 24); *dst++ = (GLfloat) value; } } else { for (j=0;j<elems_per_row;j++) { *dst++ = (GLfloat) ((GLint*)src)[j]; } } break; case GL_FLOAT: if (ctx->Unpack.SwapBytes) { GLint value; for (j=0;j<elems_per_row;j++) { value = ((GLuint*)src)[j]; value = ((value & 0xff000000) >> 24) | ((value & 0x00ff0000) >> 8) | ((value & 0x0000ff00) << 8) | ((value & 0x000000ff) << 24); *dst++ = *((GLfloat*) &value); } } else { MEMCPY( dst, src, elems_per_row*sizeof(GLfloat) ); dst += elems_per_row; } break; default: gl_problem(ctx, "Bad type in gl_unpack_image3D"); return NULL; } /*switch*/ } /* for height */ } /*for*/ image = (struct gl_image *) malloc( sizeof(struct gl_image) ); if (image) { image->Width = width; image->Height = height; image->Depth = depth; image->Components = components; image->Format = srcFormat; image->Type = GL_FLOAT; image->Interleaved = GL_FALSE; image->Data = buffer; image->RefCount = 0; } else { free( buffer ); return NULL; } return image; } else { gl_problem(ctx, "Bad dest type in gl_unpack_image3D"); return NULL; } return NULL; /* never get here */ } void gl_free_image( struct gl_image *image ) { if (image->Data) { free(image->Data); } free(image); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.