home *** CD-ROM | disk | FTP | other *** search
- """Image-handling routines
-
- ### Unresolved:
-
- Following methods are not yet resolved due to my not being sure how the
- function should be wrapped:
-
- glCompressedTexImage3D
- glCompressedTexImage2D
- glCompressedTexImage1D
- glCompressedTexSubImage3D
- glCompressedTexSubImage2D
- glCompressedTexSubImage1D
- """
- from OpenGL.raw import GL as simple
- from OpenGL import images, arrays, wrapper, platform
- import ctypes
-
- def asInt( value ):
- if isinstance( value, float ):
- return int(round(value,0))
- return value
-
- ## update the image tables with standard image types...
- #images.FORMAT_BITS.update( {
- # simple.GL_BITMAP : 1, # must be GL_UNSIGNED_BYTE
- #
- # simple.GL_RED : 8,
- # simple.GL_GREEN : 8,
- # simple.GL_BLUE : 8,
- # simple.GL_ALPHA : 8,
- # simple.GL_LUMINANCE : 8,
- # simple.GL_LUMINANCE_ALPHA : 8,
- # simple.GL_COLOR_INDEX : 8,
- # simple.GL_STENCIL_INDEX : 8,
- # simple.GL_DEPTH_COMPONENT : 8,
- # simple.GL_RGB : 24,
- # simple.GL_BGR : 24,
- #
- # simple.GL_RGBA : 32,
- # simple.GL_BGRA : 32,
- # simple.GL_ABGR_EXT : 32,
- # simple.GL_CMYK_EXT : 32,
- #
- # simple.GL_CMYKA_EXT : 40,
- #
- # simple.GL_YCRCB_422_SGIX : 8, # must be GL_UNSIGNED_BYTE
- # simple.GL_YCRCB_444_SGIX : 8, # must be GL_UNSIGNED_SHORT
- #
- # simple.GL_FORMAT_SUBSAMPLE_24_24_OML : 32, # must be GL_UNSIGNED_INT_10_10_10_2
- # simple.GL_FORMAT_SUBSAMPLE_244_244_OML : 32, # must be GL_UNSIGNED_INT_10_10_10_2
- #} )
- images.COMPONENT_COUNTS.update( {
- simple.GL_BITMAP : 1, # must be GL_UNSIGNED_BYTE
-
- simple.GL_RED : 1,
- simple.GL_GREEN : 1,
- simple.GL_BLUE : 1,
- simple.GL_ALPHA : 1,
- simple.GL_LUMINANCE : 1,
- simple.GL_LUMINANCE_ALPHA : 2,
- simple.GL_COLOR_INDEX : 1,
- simple.GL_STENCIL_INDEX : 1,
- simple.GL_DEPTH_COMPONENT : 1,
- simple.GL_RGB : 3,
- simple.GL_BGR : 3,
-
- simple.GL_RGBA : 4,
- simple.GL_BGRA : 4,
- simple.GL_ABGR_EXT : 4,
- simple.GL_CMYK_EXT : 4,
-
- simple.GL_CMYKA_EXT : 5,
-
- simple.GL_YCRCB_422_SGIX : 1, # must be GL_UNSIGNED_BYTE
- simple.GL_YCRCB_444_SGIX : 1, # must be GL_UNSIGNED_SHORT
-
- simple.GL_FORMAT_SUBSAMPLE_24_24_OML : 1, # must be GL_UNSIGNED_INT_10_10_10_2
- simple.GL_FORMAT_SUBSAMPLE_244_244_OML : 1, # must be GL_UNSIGNED_INT_10_10_10_2
- } )
-
- #images.TYPE_TO_BITS.update( {
- # simple.GL_UNSIGNED_BYTE_3_3_2 : 8,
- # simple.GL_UNSIGNED_BYTE_2_3_3_REV : 8,
- # simple.GL_UNSIGNED_SHORT_4_4_4_4 : 16,
- # simple.GL_UNSIGNED_SHORT_4_4_4_4_REV : 16,
- # simple.GL_UNSIGNED_SHORT_5_5_5_1 : 16,
- # simple.GL_UNSIGNED_SHORT_1_5_5_5_REV : 16,
- # simple.GL_UNSIGNED_SHORT_5_6_5 : 16,
- # simple.GL_UNSIGNED_SHORT_5_6_5_REV : 16,
- # simple.GL_UNSIGNED_INT_8_8_8_8 : 32,
- # simple.GL_UNSIGNED_INT_8_8_8_8_REV : 32,
- # simple.GL_UNSIGNED_INT_10_10_10_2 : 32,
- # simple.GL_UNSIGNED_INT_2_10_10_10_REV : 32,
- # simple.GL_UNSIGNED_BYTE : ctypes.sizeof(simple.GLubyte) * 8,
- # simple.GL_BYTE: ctypes.sizeof(simple.GLbyte) * 8,
- # simple.GL_UNSIGNED_SHORT : ctypes.sizeof(simple.GLushort) * 8,
- # simple.GL_SHORT : ctypes.sizeof(simple.GLshort) * 8,
- # simple.GL_UNSIGNED_INT : ctypes.sizeof(simple.GLuint) * 8,
- # simple.GL_INT : ctypes.sizeof(simple.GLint) * 8,
- # simple.GL_FLOAT : ctypes.sizeof(simple.GLfloat) * 8,
- # simple.GL_DOUBLE : ctypes.sizeof(simple.GLdouble) * 8,
- #} )
- images.TYPE_TO_ARRAYTYPE.update( {
- simple.GL_UNSIGNED_BYTE_3_3_2 : simple.GL_UNSIGNED_BYTE,
- simple.GL_UNSIGNED_BYTE_2_3_3_REV : simple.GL_UNSIGNED_BYTE,
- simple.GL_UNSIGNED_SHORT_4_4_4_4 : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_SHORT_4_4_4_4_REV : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_SHORT_5_5_5_1 : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_SHORT_1_5_5_5_REV : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_SHORT_5_6_5 : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_SHORT_5_6_5_REV : simple.GL_UNSIGNED_SHORT,
- simple.GL_UNSIGNED_INT_8_8_8_8 : simple.GL_UNSIGNED_INT,
- simple.GL_UNSIGNED_INT_8_8_8_8_REV : simple.GL_UNSIGNED_INT,
- simple.GL_UNSIGNED_INT_10_10_10_2 : simple.GL_UNSIGNED_INT,
- simple.GL_UNSIGNED_INT_2_10_10_10_REV : simple.GL_UNSIGNED_INT,
- simple.GL_UNSIGNED_BYTE : simple.GL_UNSIGNED_BYTE,
- simple.GL_BYTE: simple.GL_BYTE,
- simple.GL_UNSIGNED_SHORT : simple.GL_UNSIGNED_SHORT,
- simple.GL_SHORT : simple.GL_SHORT,
- simple.GL_UNSIGNED_INT : simple.GL_UNSIGNED_INT,
- simple.GL_INT : simple.GL_INT,
- simple.GL_FLOAT : simple.GL_FLOAT,
- simple.GL_DOUBLE : simple.GL_DOUBLE,
- } )
- images.RANK_PACKINGS.update( {
- 4: [
- (simple.glPixelStorei,simple.GL_PACK_SKIP_VOLUMES_SGIS, 0),
- (simple.glPixelStorei,simple.GL_PACK_IMAGE_DEPTH_SGIS, 0),
- ],
- 3: [
- (simple.glPixelStorei,simple.GL_PACK_SKIP_IMAGES, 0),
- (simple.glPixelStorei,simple.GL_PACK_IMAGE_HEIGHT, 0),
- ],
- 2: [
- (simple.glPixelStorei,simple.GL_PACK_ROW_LENGTH, 0),
- (simple.glPixelStorei,simple.GL_PACK_SKIP_ROWS, 0),
- (simple.glPixelStorei,simple.GL_PACK_ALIGNMENT, 1),
- ],
- 1: [
- (simple.glPixelStorei,simple.GL_PACK_SKIP_PIXELS, 0),
- ],
- } )
-
-
- __all__ = (
- 'glReadPixels',
- 'glReadPixelsb',
- 'glReadPixelsd',
- 'glReadPixelsf',
- 'glReadPixelsi',
- 'glReadPixelss',
- 'glReadPixelsub',
- 'glReadPixelsui',
- 'glReadPixelsus',
-
- 'glGetTexImage',
-
- 'glDrawPixels',
- 'glDrawPixelsb',
- 'glDrawPixelsf',
- 'glDrawPixelsi',
- 'glDrawPixelss',
- 'glDrawPixelsub',
- 'glDrawPixelsui',
- 'glDrawPixelsus',
-
-
- 'glTexSubImage2D',
- 'glTexSubImage1D',
- #'glTexSubImage3D',
-
- 'glTexImage1D',
- 'glTexImage2D',
- #'glTexImage3D',
-
- 'glGetTexImageb',
- 'glGetTexImaged',
- 'glGetTexImagef',
- 'glGetTexImagei',
- 'glGetTexImages',
- 'glGetTexImageub',
- 'glGetTexImageui',
- 'glGetTexImageus',
- 'glTexImage1Db',
- 'glTexImage2Db',
- #'glTexImage3Db',
- 'glTexSubImage1Db',
- 'glTexSubImage2Db',
- #'glTexSubImage3Db',
- 'glTexImage1Df',
- 'glTexImage2Df',
- #'glTexImage3Df',
- 'glTexSubImage1Df',
- 'glTexSubImage2Df',
- #'glTexSubImage3Df',
- 'glTexImage1Di',
- 'glTexImage2Di',
- #'glTexImage3Di',
- 'glTexSubImage1Di',
- 'glTexSubImage2Di',
- #'glTexSubImage3Di',
- 'glTexImage1Ds',
- 'glTexImage2Ds',
- #'glTexImage3Ds',
- 'glTexSubImage1Ds',
- 'glTexSubImage2Ds',
- #'glTexSubImage3Ds',
- 'glTexImage1Dub',
- 'glTexImage2Dub',
- #'glTexImage3Dub',
- 'glTexSubImage1Dub',
- 'glTexSubImage2Dub',
- #'glTexSubImage3Dub',
- 'glTexImage1Dui',
- 'glTexImage2Dui',
- #'glTexImage3Dui',
- 'glTexSubImage1Dui',
- 'glTexSubImage2Dui',
- #'glTexSubImage3Dui',
- 'glTexImage1Dus',
- 'glTexImage2Dus',
- #'glTexImage3Dus',
- 'glTexSubImage1Dus',
- 'glTexSubImage2Dus',
- #'glTexSubImage3Dus',
-
- #'glColorTable',
- #'glGetColorTable',
- #'glColorSubTable',
-
- #'glConvolutionFilter1D',
- #'glConvolutionFilter2D',
- #'glGetConvolutionFilter',
- #'glSeparableFilter2D',
- #'glGetSeparableFilter',
-
- #'glGetMinmax',
- )
-
- for suffix,type in [
- ('b',simple.GL_BYTE),
- ('d',simple.GL_DOUBLE),
- ('f',simple.GL_FLOAT),
- ('i',simple.GL_INT),
- ('s',simple.GL_SHORT),
- ('ub',simple.GL_UNSIGNED_BYTE),
- ('ui',simple.GL_UNSIGNED_INT),
- ('us',simple.GL_UNSIGNED_SHORT),
- ]:
- def glReadPixels( x,y,width,height,format,type=type ):
- """Read specified pixels from the current display buffer
-
- This typed version returns data in your specified default
- array data-type format
- """
- x,y,width,height = asInt(x),asInt(y),asInt(width),asInt(height)
- array = images.SetupPixelRead( format, (width,height), type )
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE.get(type,type) ]
- imageData = arrayType.dataPointer(array)
- simple.glReadPixels(
- x,y,
- width, height,
- format,type,
- ctypes.c_void_p( imageData )
- )
- return array
- globals()["glReadPixels%s"%(suffix,)] = glReadPixels
- def glGetTexImage( target, level,format,type=type ):
- """Get a texture-level as an image"""
- from OpenGL.GL import glget
- dims = [glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_WIDTH )]
- if target != simple.GL_TEXTURE_1D:
- dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_HEIGHT ) )
- if target != simple.GL_TEXTURE_2D:
- dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_DEPTH ) )
- array = images.SetupPixelRead( format, tuple(dims), type )
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE.get(type,type) ]
- simple.glGetTexImage(
- target, level, format, type, ctypes.c_void_p( arrayType.dataPointer(array))
- )
- return array
- globals()["glGetTexImage%s"%(suffix,)] = glGetTexImage
- ## def glGetTexSubImage( target, level,format,type ):
- ## """Get a texture-level as an image"""
- ## from OpenGL.GL import glget
- ## dims = [glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_WIDTH )]
- ## if target != simple.GL_TEXTURE_1D:
- ## dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_HEIGHT ) )
- ## if target != simple.GL_TEXTURE_2D:
- ## dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_DEPTH ) )
- ## array = images.SetupPixelRead( format, tuple(dims), type )
- ## arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE.get(type,type) ]
- ## simple.glGetTexImage(
- ## target, level, format, type, ctypes.c_void_p( arrayType.dataPointer(array))
- ## )
- ## return array
- ## "%s = glGetTexImage"%(suffix)
- del suffix,type
- # Now the real glReadPixels...
- def glReadPixels( x,y,width,height,format,type, outputType=str ):
- """Read specified pixels from the current display buffer
-
- x,y,width,height -- location and dimensions of the image to read
- from the buffer
- format -- pixel format for the resulting data
- type -- data-format for the resulting data
- outputType -- default (str) provides string output of the
- results iff OpenGL.UNSIGNED_BYTE_IMAGES_AS_STRING is True
- and type == GL_UNSIGNED_BYTE. Any other value will cause
- output in the default array output format.
-
- returns the pixel data array in the format defined by the
- format, type and outputType
- """
- x,y,width,height = asInt(x),asInt(y),asInt(width),asInt(height)
- array = images.SetupPixelRead( format, (width,height), type )
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE.get(type,type) ]
- imageData = arrayType.dataPointer(array)
- simple.glReadPixels(
- x,y,width,height,
- format,type,
- ctypes.c_void_p( imageData )
- )
- if outputType is str:
- return images.returnFormat( array, type )
- else:
- return array
-
- def glGetTexImage( target, level,format,type, outputType=str ):
- """Get a texture-level as an image
-
- target -- enum constant for the texture engine to be read
- level -- the mip-map level to read
- format -- image format to read out the data
- type -- data-type into which to read the data
-
- outputType -- default (str) provides string output of the
- results iff OpenGL.UNSIGNED_BYTE_IMAGES_AS_STRING is True
- and type == GL_UNSIGNED_BYTE. Any other value will cause
- output in the default array output format.
-
- returns the pixel data array in the format defined by the
- format, type and outputType
- """
- from OpenGL.GL import glget
- dims = [glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_WIDTH )]
- if target != simple.GL_TEXTURE_1D:
- dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_HEIGHT ) )
- if target != simple.GL_TEXTURE_2D:
- dims.append( glget.glGetTexLevelParameteriv( target, level, simple.GL_TEXTURE_DEPTH ) )
- array = images.SetupPixelRead( format, tuple(dims), type )
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE.get(type,type) ]
- simple.glGetTexImage(
- target, level, format, type, ctypes.c_void_p( arrayType.dataPointer(array))
- )
- if outputType is str:
- return images.returnFormat( array, type )
- else:
- return array
-
-
- INT_DIMENSION_NAMES = [
- 'width','height','depth','x','y','z',
- 'xoffset','yoffset','zoffset',
- 'start', 'count',
- ]
- def asWrapper( value ):
- if not isinstance( value, wrapper.Wrapper ):
- return wrapper.wrapper( value )
- return value
-
- def asIntConverter( value, *args ):
- if isinstance( value, float ):
- return int(round(value,0))
- return value
-
- def setDimensionsAsInts( baseOperation ):
- """Set arguments with names in INT_DIMENSION_NAMES to asInt processing"""
- baseOperation = asWrapper( baseOperation )
- argNames = getattr( baseOperation, 'pyConverterNames', baseOperation.argNames )
- for i,argName in enumerate(argNames):
- if argName in INT_DIMENSION_NAMES:
- baseOperation.setPyConverter( argName, asIntConverter )
- return baseOperation
-
-
-
- class ImageInputConverter( object ):
- def __init__( self, rank, pixelsName=None, typeName='type' ):
- self.rank = rank
- self.typeName = typeName
- self.pixelsName = pixelsName
- def finalise( self, wrapper ):
- """Get our pixel index from the wrapper"""
- self.typeIndex = wrapper.pyArgIndex( self.typeName )
- self.pixelsIndex = wrapper.pyArgIndex( self.pixelsName )
- def __call__( self, arg, baseOperation, pyArgs ):
- """pyConverter for the pixels argument"""
- images.setupDefaultTransferMode()
- images.rankPacking( self.rank )
- type = pyArgs[ self.typeIndex ]
- try:
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ images.TYPE_TO_ARRAYTYPE[ type ] ]
- except TypeError, err:
- import pdb
- pdb.set_trace()
- return arrayType.asArray( arg )
- def cResolver( self, array ):
- return ctypes.c_void_p( arrays.ArrayDatatype.dataPointer( array ) )
-
- class TypedImageInputConverter( ImageInputConverter ):
- def __init__( self, rank, pixelsName, arrayType, typeName=None ):
- self.rank = rank
- self.arrayType = arrayType
- self.pixelsName = pixelsName
- self.typeName = typeName
- def __call__( self, arg, baseOperation, pyArgs ):
- """The pyConverter for the pixels"""
- images.setupDefaultTransferMode()
- images.rankPacking( self.rank )
- return self.arrayType.asArray( arg )
- def finalise( self, wrapper ):
- """Get our pixel index from the wrapper"""
- self.pixelsIndex = wrapper.pyArgIndex( self.pixelsName )
- def width( self, pyArgs, index, wrappedOperation ):
- """Extract the width from the pixels argument"""
- return self.arrayType.dimensions( pyArgs[self.pixelsIndex] )[0]
- def height( self, pyArgs, index, wrappedOperation ):
- """Extract the height from the pixels argument"""
- return self.arrayType.dimensions( pyArgs[self.pixelsIndex] )[1]
- def depth( self, pyArgs, index, wrappedOperation ):
- """Extract the depth from the pixels argument"""
- return self.arrayType.dimensions( pyArgs[self.pixelsIndex] )[2]
- def type( self, pyArgs, index, wrappedOperation ):
- """Provide the item-type argument from our stored value
-
- This is used for pre-bound processing where we want to provide
- the type by implication...
- """
- return self.typeName
-
- class CompressedImageConverter( object ):
- def finalise( self, wrapper ):
- """Get our pixel index from the wrapper"""
- self.dataIndex = wrapper.pyArgIndex( 'data' )
- def __call__( self, pyArgs, index, wrappedOperation ):
- """Create a data-size measurement for our image"""
- arg = pyArgs[ self.dataIndex ]
- return arrays.ArrayType.arrayByteCount( arg )
-
-
-
- DIMENSION_NAMES = (
- 'width','height','depth'
- )
- PIXEL_NAMES = (
- 'pixels', 'row', 'column',
- )
- DATA_SIZE_NAMES = (
- 'imageSize',
- )
-
- def setImageInput(
- baseOperation, arrayType=None, dimNames=DIMENSION_NAMES,
- pixelName="pixels", typeName=None
- ):
- """Determine how to convert "pixels" into an image-compatible argument"""
- baseOperation = asWrapper( baseOperation )
- # rank is the count of width,height,depth arguments...
- rank = len([
- # rank is the number of dims we want, not the number we give...
- argName for argName in baseOperation.argNames
- if argName in dimNames
- ]) + 1
- if arrayType:
- converter = TypedImageInputConverter( rank, pixelName, arrayType, typeName=typeName )
- for i,argName in enumerate(baseOperation.argNames):
- if argName in dimNames:
- baseOperation.setPyConverter( argName )
- baseOperation.setCConverter( argName, getattr(converter,argName) )
- elif argName == 'type' and typeName is not None:
- baseOperation.setPyConverter( argName )
- baseOperation.setCConverter( argName, converter.type )
- else:
- converter = ImageInputConverter( rank, pixelsName=pixelName, typeName=typeName or 'type' )
- for argName in baseOperation.argNames:
- if argName in DATA_SIZE_NAMES:
- baseOperation.setPyConverter( argName )
- baseOperation.setCConverter( argName, converter.imageDataSize )
- baseOperation.setPyConverter(
- pixelName, converter,
- )
- baseOperation.setCResolver(
- pixelName, converter.cResolver
- )
- return baseOperation
-
- glDrawPixels = setDimensionsAsInts(
- setImageInput(
- simple.glDrawPixels
- )
- )
- glTexSubImage2D = setDimensionsAsInts(
- setImageInput(
- simple.glTexSubImage2D
- )
- )
- glTexSubImage1D = setDimensionsAsInts(
- setImageInput(
- simple.glTexSubImage1D
- )
- )
- glTexImage2D = setDimensionsAsInts(
- setImageInput(
- simple.glTexImage2D
- )
- )
- glTexImage1D = setDimensionsAsInts(
- setImageInput(
- simple.glTexImage1D
- )
- )
-
- def typedImageFunction( suffix, arrayConstant, baseFunction ):
- """Produce a typed version of the given image function"""
- if baseFunction:
- arrayType = arrays.GL_CONSTANT_TO_ARRAY_TYPE[ arrayConstant ]
- function = setDimensionsAsInts(
- setImageInput(
- baseFunction,
- arrayType,
- typeName = arrayConstant,
- )
- )
- functionName = baseFunction.__name__
- functionName = '%(functionName)s%(suffix)s'%locals()
- return functionName, function
- else:
- return baseFunction.__name__, baseFunction
-
- def _setDataSize( baseFunction, argument='imageSize' ):
- """Set the data-size value to come from the data field"""
- if baseFunction:
- converter = CompressedImageConverter()
- return asWrapper( baseFunction ).setPyConverter(
- argument
- ).setCConverter( argument, converter )
- else:
- return baseFunction
-
- def compressedImageFunction( baseFunction ):
- """Set the imageSize and dimensions-as-ints converters for baseFunction"""
- if baseFunction:
- return setDimensionsAsInts(
- _setDataSize(
- baseFunction, argument='imageSize'
- )
- )
- else:
- return baseFunction
-
- for suffix,arrayConstant in [
- ('b', simple.GL_BYTE),
- ('f', simple.GL_FLOAT),
- ('i', simple.GL_INT),
- ('s', simple.GL_SHORT),
- ('ub', simple.GL_UNSIGNED_BYTE),
- ('ui', simple.GL_UNSIGNED_INT),
- ('us', simple.GL_UNSIGNED_SHORT),
- ]:
- for functionName in (
- 'glTexImage1D','glTexImage2D',
- 'glTexSubImage1D','glTexSubImage2D',
- 'glDrawPixels',
- #'glTexSubImage3D','glTexImage3D', # extension/1.2 standard
- ):
- functionName, function = typedImageFunction(
- suffix, arrayConstant, getattr(simple,functionName),
- )
- globals()[functionName] = function
- del function, functionName
- del suffix,arrayConstant
-
-