uid issue

This commit is contained in:
KittenPopo
2021-07-24 21:11:47 -07:00
commit c2130ba4e9
13850 changed files with 6241419 additions and 0 deletions

172
public/bitmap/bitmap.h Normal file
View File

@ -0,0 +1,172 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//===========================================================================//
#ifndef BITMAP_H
#define BITMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h"
#include "color.h"
#include "dbg.h"
class CUtlBuffer;
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
//-----------------------------------------------------------------------------
// A Bitmap
//-----------------------------------------------------------------------------
struct Bitmap_t
{
Bitmap_t() { Reset(); }
~Bitmap_t() { Clear(); }
//
// Accessors
//
inline int Width() const { return m_nWidth; }
inline int Height() const { return m_nHeight; }
inline ImageFormat Format() const { return m_ImageFormat; }
inline unsigned char *GetBits() const { return m_pBits; }
inline int Stride() const { return m_nStride; }
inline bool GetOwnsBuffer() const { return m_bOwnsBuffer; }
/// Allocate the buffer. Discards existing data, freeing it if we own it
void Init( int nWidth, int nHeight, ImageFormat imageFormat, int nStride = 0 );
/// Set the bitmap to the specified buffer. Any existing data is discarded/freed
/// as appropriate.
void SetBuffer( int nWidth, int nHeight, ImageFormat imageFormat, unsigned char *pBits, bool bAssumeOwnership, int nStride = 0 );
/// Sets / releases ownershp of the buffer. This does not otherwise alter the
/// state of the bitmap.
void SetOwnsBuffer( bool bOwnsBuffer )
{
Assert( m_pBits );
m_bOwnsBuffer = bOwnsBuffer;
}
/// Free up all memory and reset to default state
void Clear();
/// Return true if we have a valid size and buffer
bool IsValid() const;
/// Get pointer to raw pixel data.
unsigned char *GetPixel( int x, int y );
const unsigned char *GetPixel( int x, int y ) const;
/// Get pixel value at specified coordinates
Color GetColor( int x, int y ) const;
/// Set pixel value at specified coordinates
void SetColor( int x, int y, Color c );
/// Set this bitmap to be a logical copy of the specified
/// bitmap. No memory is allocated or copied, just copying
/// some pointers. We can also optionally transfer ownership
/// of the buffer.
void MakeLogicalCopyOf( Bitmap_t &src, bool bTransferBufferOwnership = false );
/// Set this bitmap to be a cropped rectangle from the given bitmap.
/// The source pointer can be NULL or point to this, which means to do
/// the crop in place.
void Crop( int x0, int y0, int nWidth, int nHeight, const Bitmap_t *pImgSource = NULL );
/// Blit a rectangle of pixel data into this image.
void SetPixelData( const Bitmap_t &src, int nSrcX1, int nSrcY1, int nCopySizeX, int nCopySizeY, int nDestX1, int nDestY1 );
/// Blit the entire source image into this image, at the specified offset.
/// the rectangle is clipped if necessary
void SetPixelData( const Bitmap_t &src, int nDestX1 = 0, int nDestY1 = 0 );
private:
void Reset();
/// Dimensions
int m_nWidth;
int m_nHeight;
/// Size, in bytes, of one pixel
int m_nPixelSize;
/// Image row stride, in bytes
int m_nStride;
// Do we own this buffer?
bool m_bOwnsBuffer;
/// Pixel format
ImageFormat m_ImageFormat;
/// Bitmap data. Must be allocated with malloc/free. Don't use
/// new/delete
unsigned char *m_pBits;
};
inline void Bitmap_t::Reset()
{
m_nWidth = 0;
m_nHeight = 0;
m_ImageFormat = IMAGE_FORMAT_UNKNOWN;
m_pBits = NULL;
m_nPixelSize = 0;
m_bOwnsBuffer = false;
m_nStride = 0;
}
inline unsigned char *Bitmap_t::GetPixel( int x, int y )
{
if ( !m_pBits )
return NULL;
return m_pBits + (y*m_nStride) + x* m_nPixelSize;
}
inline const unsigned char *Bitmap_t::GetPixel( int x, int y ) const
{
if ( !m_pBits )
return NULL;
return m_pBits + (y*m_nStride) + x* m_nPixelSize;
}
//-----------------------------------------------------------------------------
// Loads a bitmap from an arbitrary file: could be a TGA, PSD, or PFM.
// LoadBitmap autodetects which type, and returns it
//-----------------------------------------------------------------------------
enum BitmapFileType_t
{
BITMAP_FILE_TYPE_UNKNOWN = -1,
BITMAP_FILE_TYPE_PSD = 0,
BITMAP_FILE_TYPE_TGA,
BITMAP_FILE_TYPE_PFM,
};
BitmapFileType_t LoadBitmapFile( CUtlBuffer &buf, Bitmap_t *pBitmap );
//-----------------------------------------------------------------------------
// PFM file loading related methods
//-----------------------------------------------------------------------------
bool PFMReadFileR32F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale );
bool PFMReadFileRGB323232F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale );
bool PFMReadFileRGBA32323232F( CUtlBuffer &fileBuffer, Bitmap_t &bitmap, float pfmScale );
bool PFMGetInfo_AndAdvanceToTextureBits( CUtlBuffer &pfmBuffer, int &nWidth, int &nHeight, ImageFormat &imageFormat );
#endif // BITMAP_H

146
public/bitmap/colorformat.h Normal file
View File

@ -0,0 +1,146 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef COLORFORMAT_H
#define COLORFORMAT_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
#include "mathlib/vector.h"
#include "mathlib/vector2d.h"
#include "mathlib/vector4d.h"
#include "mathlib/vertexcolor.h"
enum ColorFormat_t
{
COLOR_FORMAT_UNKNOWN = 0,
COLOR_FORMAT_R32G32B32A32_TYPELESS = 1,
COLOR_FORMAT_R32G32B32A32_FLOAT = 2,
COLOR_FORMAT_R32G32B32A32_UINT = 3,
COLOR_FORMAT_R32G32B32A32_SINT = 4,
COLOR_FORMAT_R32G32B32_TYPELESS = 5,
COLOR_FORMAT_R32G32B32_FLOAT = 6,
COLOR_FORMAT_R32G32B32_UINT = 7,
COLOR_FORMAT_R32G32B32_SINT = 8,
COLOR_FORMAT_R16G16B16A16_TYPELESS = 9,
COLOR_FORMAT_R16G16B16A16_FLOAT = 10,
COLOR_FORMAT_R16G16B16A16_UNORM = 11,
COLOR_FORMAT_R16G16B16A16_UINT = 12,
COLOR_FORMAT_R16G16B16A16_SNORM = 13,
COLOR_FORMAT_R16G16B16A16_SINT = 14,
COLOR_FORMAT_R32G32_TYPELESS = 15,
COLOR_FORMAT_R32G32_FLOAT = 16,
COLOR_FORMAT_R32G32_UINT = 17,
COLOR_FORMAT_R32G32_SINT = 18,
COLOR_FORMAT_R32G8X24_TYPELESS = 19,
COLOR_FORMAT_D32_FLOAT_S8X24_UINT = 20,
COLOR_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
COLOR_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
COLOR_FORMAT_R10G10B10A2_TYPELESS = 23,
COLOR_FORMAT_R10G10B10A2_UNORM = 24,
COLOR_FORMAT_R10G10B10A2_UINT = 25,
COLOR_FORMAT_R11G11B10_FLOAT = 26,
COLOR_FORMAT_R8G8B8A8_TYPELESS = 27,
COLOR_FORMAT_R8G8B8A8_UNORM = 28,
COLOR_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
COLOR_FORMAT_R8G8B8A8_UINT = 30,
COLOR_FORMAT_R8G8B8A8_SNORM = 31,
COLOR_FORMAT_R8G8B8A8_SINT = 32,
COLOR_FORMAT_R16G16_TYPELESS = 33,
COLOR_FORMAT_R16G16_FLOAT = 34,
COLOR_FORMAT_R16G16_UNORM = 35,
COLOR_FORMAT_R16G16_UINT = 36,
COLOR_FORMAT_R16G16_SNORM = 37,
COLOR_FORMAT_R16G16_SINT = 38,
COLOR_FORMAT_R32_TYPELESS = 39,
COLOR_FORMAT_D32_FLOAT = 40,
COLOR_FORMAT_R32_FLOAT = 41,
COLOR_FORMAT_R32_UINT = 42,
COLOR_FORMAT_R32_SINT = 43,
COLOR_FORMAT_R24G8_TYPELESS = 44,
COLOR_FORMAT_D24_UNORM_S8_UINT = 45,
COLOR_FORMAT_R24_UNORM_X8_TYPELESS = 46,
COLOR_FORMAT_X24_TYPELESS_G8_UINT = 47,
COLOR_FORMAT_R8G8_TYPELESS = 48,
COLOR_FORMAT_R8G8_UNORM = 49,
COLOR_FORMAT_R8G8_UINT = 50,
COLOR_FORMAT_R8G8_SNORM = 51,
COLOR_FORMAT_R8G8_SINT = 52,
COLOR_FORMAT_R16_TYPELESS = 53,
COLOR_FORMAT_R16_FLOAT = 54,
COLOR_FORMAT_D16_UNORM = 55,
COLOR_FORMAT_R16_UNORM = 56,
COLOR_FORMAT_R16_UINT = 57,
COLOR_FORMAT_R16_SNORM = 58,
COLOR_FORMAT_R16_SINT = 59,
COLOR_FORMAT_R8_TYPELESS = 60,
COLOR_FORMAT_R8_UNORM = 61,
COLOR_FORMAT_R8_UINT = 62,
COLOR_FORMAT_R8_SNORM = 63,
COLOR_FORMAT_R8_SINT = 64,
COLOR_FORMAT_A8_UNORM = 65,
COLOR_FORMAT_R1_UNORM = 66,
COLOR_FORMAT_R9G9B9E5_SHAREDEXP = 67,
COLOR_FORMAT_R8G8_B8G8_UNORM = 68,
COLOR_FORMAT_G8R8_G8B8_UNORM = 69,
COLOR_FORMAT_BC1_TYPELESS = 70,
COLOR_FORMAT_BC1_UNORM = 71,
COLOR_FORMAT_BC1_UNORM_SRGB = 72,
COLOR_FORMAT_BC2_TYPELESS = 73,
COLOR_FORMAT_BC2_UNORM = 74,
COLOR_FORMAT_BC2_UNORM_SRGB = 75,
COLOR_FORMAT_BC3_TYPELESS = 76,
COLOR_FORMAT_BC3_UNORM = 77,
COLOR_FORMAT_BC3_UNORM_SRGB = 78,
COLOR_FORMAT_BC4_TYPELESS = 79,
COLOR_FORMAT_BC4_UNORM = 80,
COLOR_FORMAT_BC4_SNORM = 81,
COLOR_FORMAT_BC5_TYPELESS = 82,
COLOR_FORMAT_BC5_UNORM = 83,
COLOR_FORMAT_BC5_SNORM = 84,
COLOR_FORMAT_B5G6R5_UNORM = 85,
COLOR_FORMAT_B5G5R5A1_UNORM = 86,
COLOR_FORMAT_B8G8R8A8_UNORM = 87,
COLOR_FORMAT_B8G8R8X8_UNORM = 88,
COLOR_FORMAT_FORCE_UINT = 0xffffffffUL,
};
template < class T > inline ColorFormat_t ComputeColorFormat( T* )
{
return COLOR_FORMAT_UNKNOWN;
}
template <> inline ColorFormat_t ComputeColorFormat( float32* )
{
return COLOR_FORMAT_R32_FLOAT;
}
template <> inline ColorFormat_t ComputeColorFormat( Vector2D* )
{
return COLOR_FORMAT_R32G32_FLOAT;
}
template <> inline ColorFormat_t ComputeColorFormat( Vector* )
{
return COLOR_FORMAT_R32G32B32_FLOAT;
}
template <> inline ColorFormat_t ComputeColorFormat( Vector4D* )
{
return COLOR_FORMAT_R32G32B32A32_FLOAT;
}
template <> inline ColorFormat_t ComputeColorFormat( VertexColor_t* )
{
// FIXME: How to get at SRGB formats?
return COLOR_FORMAT_R8G8B8A8_UNORM;
}
#endif // COLORFORMAT_H

68
public/bitmap/cubemap.h Normal file
View File

@ -0,0 +1,68 @@
//===== Copyright <20> 1996-2007, Valve Corporation, All rights reserved. ======//
//
// Purpose: a class for performing cube-mapped spherical sample lookups.
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef CUBEMAP_H
#define CUBEMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "tier1/utlmemory.h"
#include "mathlib/mathlib.h"
template<class T, int RES> struct CCubeMap
{
T m_Samples[6][RES][RES];
public:
FORCEINLINE void GetCoords( Vector const &vecNormalizedDirection, int &nX, int &nY, int &nFace )
{
// find largest magnitude component
int nLargest = 0;
int nAxis0 = 1;
int nAxis1 = 2;
if ( fabs( vecNormalizedDirection[1] ) > fabs( vecNormalizedDirection[0] ) )
{
nLargest = 1;
nAxis0 = 0;
nAxis1 = 2;
}
if ( fabs( vecNormalizedDirection[2] ) > fabs( vecNormalizedDirection[nLargest] ) )
{
nLargest = 2;
nAxis0 = 0;
nAxis1 = 1;
}
float flZ = vecNormalizedDirection[nLargest];
if ( flZ < 0 )
{
flZ = - flZ;
nLargest += 3;
}
nFace = nLargest;
flZ = 1.0 / flZ;
nX = RemapValClamped( vecNormalizedDirection[nAxis0] * flZ, -1, 1, 0, RES - 1 );
nY = RemapValClamped( vecNormalizedDirection[nAxis1] * flZ, -1, 1, 0, RES - 1 );
}
FORCEINLINE T & GetSample( Vector const &vecNormalizedDirection )
{
int nX, nY, nFace;
GetCoords( vecNormalizedDirection, nX, nY, nFace );
return m_Samples[nFace][nX][nY];
}
};
#endif // CUBEMAP_H

833
public/bitmap/floatbitmap.h Normal file
View File

@ -0,0 +1,833 @@
//======= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Header: $
// $NoKeywords: $
//=============================================================================//
#ifndef FLOATBITMAP_H
#define FLOATBITMAP_H
#ifdef _WIN32
#pragma once
#endif
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "tier1/utlsoacontainer.h"
#include "mathlib/mathlib.h"
#include "bitmap/imageformat.h"
class IThreadPool;
struct PixRGBAF
{
float Red;
float Green;
float Blue;
float Alpha;
};
struct PixRGBA8
{
unsigned char Red;
unsigned char Green;
unsigned char Blue;
unsigned char Alpha;
};
inline PixRGBAF PixRGBA8_to_F( PixRGBA8 const &x )
{
PixRGBAF f;
f.Red = x.Red / float( 255.0f );
f.Green = x.Green / float( 255.0f );
f.Blue = x.Blue / float( 255.0f );
f.Alpha = x.Alpha / float( 255.0f );
return f;
}
inline PixRGBA8 PixRGBAF_to_8( PixRGBAF const &f )
{
PixRGBA8 x;
x.Red = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Red ) );
x.Green = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Green ) );
x.Blue = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Blue ) );
x.Alpha = ( unsigned char )MAX( 0, MIN( 255.0,255.0*f.Alpha ) );
return x;
}
#define SPFLAGS_MAXGRADIENT 1
// bit flag options for ComputeSelfShadowedBumpmapFromHeightInAlphaChannel:
#define SSBUMP_OPTION_NONDIRECTIONAL 1 // generate ambient occlusion only
#define SSBUMP_MOD2X_DETAIL_TEXTURE 2 // scale so that a flat unshadowed
// value is 0.5, and bake rgb luminance
// in.
// attributes for csoaa container
enum FBMAttribute_t
{
FBM_ATTR_RED = 0,
FBM_ATTR_GREEN = 1,
FBM_ATTR_BLUE = 2,
FBM_ATTR_ALPHA = 3,
FBM_ATTR_COUNT
};
enum FBMAttributeMask_t
{
FBM_ATTR_RED_MASK = ( 1 << FBM_ATTR_RED ),
FBM_ATTR_GREEN_MASK = ( 1 << FBM_ATTR_GREEN ),
FBM_ATTR_BLUE_MASK = ( 1 << FBM_ATTR_BLUE ),
FBM_ATTR_ALPHA_MASK = ( 1 << FBM_ATTR_ALPHA ),
FBM_ATTR_RGB_MASK = FBM_ATTR_RED_MASK | FBM_ATTR_GREEN_MASK | FBM_ATTR_BLUE_MASK,
FBM_ATTR_RGBA_MASK = FBM_ATTR_RED_MASK | FBM_ATTR_GREEN_MASK | FBM_ATTR_BLUE_MASK | FBM_ATTR_ALPHA_MASK,
};
enum DownsampleFlags_t
{
DOWNSAMPLE_CLAMPS = 0x1,
DOWNSAMPLE_CLAMPT = 0x2,
DOWNSAMPLE_CLAMPU = 0x4,
DOWNSAMPLE_ALPHATEST = 0x10,
};
struct DownsampleInfo_t
{
int m_nFlags; // see DownsampleFlags_t
float m_flAlphaThreshhold;
float m_flAlphaHiFreqThreshhold;
};
//-----------------------------------------------------------------------------
// Float bitmap
//-----------------------------------------------------------------------------
class FloatBitMap_t : public CSOAContainer
{
typedef CSOAContainer BaseClass;
public:
FloatBitMap_t();
FloatBitMap_t( int nWidth, int nHeight, int nDepth = 1, int nAttributeMask = FBM_ATTR_RGBA_MASK ); // make one and allocate space
FloatBitMap_t( const char *pFilename ); // read one from a file (tga or pfm)
FloatBitMap_t( const FloatBitMap_t *pOrig );
// Initialize, shutdown
void Init( int nWidth, int nHeight, int nDepth = 1, int nAttributeMask = FBM_ATTR_RGBA_MASK );
void Shutdown();
// Computes the attribute mask
int GetAttributeMask() const;
// Does the bitmap have data for a particular component?
bool HasAttributeData( FBMAttribute_t a ) const;
// Compute valid attribute list
int ComputeValidAttributeList( int pIndex[4] ) const;
// Methods to initialize bitmap data
bool LoadFromPFM( const char *pFilename ); // load from floating point pixmap (.pfm) file
bool LoadFromPSD( const char *pFilename ); // load from psd file
void InitializeWithRandomPixelsFromAnotherFloatBM( const FloatBitMap_t &other );
void Clear( float r, float g, float b, float alpha ); // set all pixels to speicifed values (0..1 nominal)
void LoadFromBuffer( const void *pBuffer, size_t nBufSize, ImageFormat fmt, float flGamma ); // Assumes dimensions match the bitmap size
void LoadFromFloatBitmap( const FloatBitMap_t *pOrig );
// Methods to write bitmap data to files
bool WriteTGAFile( const char *pFilename ) const;
bool WritePFM( const char *pFilename ); // save to floating point pixmap (.pfm) file
void WriteToBuffer( void *pBuffer, size_t nBufSize, ImageFormat fmt, float flGamma ) const; // Assumes dimensions match the bitmap size
// Methods to read + write constant values
const float &ConstantValue( int comp ) const;
// Methods to read + write individual pixels
float &Pixel( int x, int y, int z, int comp ) const;
float &PixelWrapped( int x, int y, int z, int comp ) const;
float &PixelClamped( int x, int y, int z, int comp ) const;
float &Alpha( int x, int y, int z ) const;
// look up a pixel value with bilinear interpolation
float InterpolatedPixel( float x, float y, int comp ) const;
float InterpolatedPixel( float x, float y, float z, int comp ) const;
PixRGBAF PixelRGBAF( int x, int y, int z ) const;
void WritePixelRGBAF(int x, int y, int z, PixRGBAF value) const;
void WritePixel(int x, int y, int z, int comp, float value);
// Method to slam a particular channel to always be the same value
void SetChannel( int comp, float flValue );
// paste, performing boundary matching. Alpha channel can be used to make
// brush shape irregular
void SmartPaste( const FloatBitMap_t &brush, int xofs, int yofs, uint32 flags );
// force to be tileable using poisson formula
void MakeTileable( void );
void ReSize( int NewXSize, int NewYSize );
// Makes the image be a sub-range of the current image
void Crop( int x, int y, int z, int nWidth, int nHeight, int nDepth );
// find the bounds of the area that has non-zero alpha.
void GetAlphaBounds( int &minx, int &miny, int &maxx, int &maxy );
// Solve the poisson equation for an image. The alpha channel of the image controls which
// pixels are "modifiable", and can be used to set boundary conditions. Alpha=0 means the pixel
// is locked. deltas are in the order [(x,y)-(x,y-1),(x,y)-(x-1,y),(x,y)-(x+1,y),(x,y)-(x,y+1)
void Poisson( FloatBitMap_t * deltas[4],
int n_iters,
uint32 flags // SPF_xxx
);
void QuarterSize( FloatBitMap_t *pBitmap ); // get a new one downsampled
void QuarterSizeBlocky( FloatBitMap_t *pBitmap ); // get a new one downsampled
void QuarterSizeWithGaussian( FloatBitMap_t *pBitmap ); // downsample 2x using a gaussian
// Downsample using nice filter (NOTE: Dest bitmap needs to have been initialized w/ final size)
void DownsampleNiceFiltered( const DownsampleInfo_t& info, FloatBitMap_t *pBitmap );
void RaiseToPower( float pow );
void ScaleGradients( void );
void Logize( void ); // pix=log(1+pix)
void UnLogize( void ); // pix=exp(pix)-1
// compress to 8 bits converts the hdr texture to an 8 bit texture, encoding a scale factor
// in the alpha channel. upon return, the original pixel can be (approximately) recovered
// by the formula rgb*alpha*overbright.
// this function performs special numerical optimization on the texture to minimize the error
// when using bilinear filtering to read the texture.
void CompressTo8Bits( float overbright );
// decompress a bitmap converted by CompressTo8Bits
void Uncompress( float overbright );
Vector AverageColor( void ); // average rgb value of all pixels
float BrightestColor( void ); // highest vector magnitude
void ScaleRGB( float scale_factor ); // for all pixels, r,g,b*=scale_factor
// given a bitmap with height stored in the alpha channel, generate vector positions and normals
void ComputeVertexPositionsAndNormals( float flHeightScale, Vector ** ppPosOut, Vector ** ppNormalOut ) const;
// generate a normal map with height stored in alpha. uses hl2 tangent basis to support baked
// self shadowing. the bump scale maps the height of a pixel relative to the edges of the
// pixel. This function may take a while - many millions of rays may be traced. applications
// using this method need to link w/ raytrace.lib
FloatBitMap_t * ComputeSelfShadowedBumpmapFromHeightInAlphaChannel(
float bump_scale, int nrays_to_trace_per_pixel = 100,
uint32 nOptionFlags = 0 // SSBUMP_OPTION_XXX
) const;
// generate a conventional normal map from a source with height stored in alpha.
FloatBitMap_t *ComputeBumpmapFromHeightInAlphaChannel( float bump_scale ) const ;
// bilateral (edge preserving) smoothing filter. edge_threshold_value defines the difference in
// values over which filtering will not occur. Each channel is filtered independently. large
// radii will run slow, since the bilateral filter is neither separable, nor is it a
// convolution that can be done via fft.
void TileableBilateralFilter( int radius_in_pixels, float edge_threshold_value );
// Sets a thread pool for all float bitmap work to be done on
static void SetThreadPool( IThreadPool* pPool );
protected:
void QuarterSize2D( FloatBitMap_t *pDest, int nStart, int nCount );
void QuarterSize3D( FloatBitMap_t *pDest, int nStart, int nCount );
void QuarterSizeBlocky2D( FloatBitMap_t *pDest, int nStart, int nCount );
void QuarterSizeBlocky3D( FloatBitMap_t *pDest, int nStart, int nCount );
template< class T > void LoadFromBufferRGBFloat( const T *pBuffer, int nPixelCount );
template< class T > void LoadFromBufferRGB( const T *pBuffer, int nPixelCount, const float *pGammaTable );
template< class T > void LoadFromBufferRGBAFloat( const T *pBuffer, int nPixelCount );
template< class T > void LoadFromBufferRGBA( const T *pBuffer, int nPixelCount, const float *pGammaTable );
template< class T > void LoadFromBufferUV( const T *pBuffer, int nPixelCount );
template< class T > void LoadFromBufferUVWQ( const T *pBuffer, int nPixelCount );
template< class T > void LoadFromBufferUVLX( const T *pBuffer, int nPixelCount );
template< class T > void WriteToBufferRGB( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const;
template< class T > void WriteToBufferRGBFloat( T *pBuffer, int nPixelCount ) const;
template< class T > void WriteToBufferRGBA( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const;
template< class T > void WriteToBufferRGBAFloat( T *pBuffer, int nPixelCount ) const;
template< class T > void WriteToBufferUV( T *pBuffer, int nPixelCount ) const;
template< class T > void WriteToBufferUVWQ( T *pBuffer, int nPixelCount ) const;
template< class T > void WriteToBufferUVLX( T *pBuffer, int nPixelCount ) const;
static int CoordWrap( int nC, int nLimit );
static IThreadPool *sm_pFBMThreadPool;
};
//-----------------------------------------------------------------------------
// Inline methods
//-----------------------------------------------------------------------------
inline FloatBitMap_t::FloatBitMap_t(void)
{
}
inline void FloatBitMap_t::Init( int nXSize, int nYSize, int nZSize, int nAttributeMask )
{
PurgeData();
SetAttributeType( FBM_ATTR_RED, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_RED_MASK ) != 0 );
SetAttributeType( FBM_ATTR_GREEN, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_GREEN_MASK ) != 0 );
SetAttributeType( FBM_ATTR_BLUE, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_BLUE_MASK ) != 0 );
SetAttributeType( FBM_ATTR_ALPHA, ATTRDATATYPE_FLOAT, ( nAttributeMask & FBM_ATTR_ALPHA_MASK ) != 0 );
AllocateData( nXSize, nYSize, nZSize );
// Default alpha to white. All others default to 0.0 by default
if ( ( nAttributeMask & FBM_ATTR_ALPHA_MASK ) == 0 )
{
FillAttr( FBM_ATTR_ALPHA, 1.0f );
}
}
//-----------------------------------------------------------------------------
// Computes the attribute mask
//-----------------------------------------------------------------------------
inline int FloatBitMap_t::GetAttributeMask() const
{
int nMask = 0;
if ( HasAllocatedMemory( FBM_ATTR_RED ) )
nMask |= FBM_ATTR_RED_MASK;
if ( HasAllocatedMemory( FBM_ATTR_GREEN ) )
nMask |= FBM_ATTR_GREEN_MASK;
if ( HasAllocatedMemory( FBM_ATTR_BLUE ) )
nMask |= FBM_ATTR_BLUE_MASK;
if ( HasAllocatedMemory( FBM_ATTR_ALPHA ) )
nMask |= FBM_ATTR_ALPHA_MASK;
return nMask;
}
//-----------------------------------------------------------------------------
// Compute valid attribute list
//-----------------------------------------------------------------------------
inline int FloatBitMap_t::ComputeValidAttributeList( int pIndex[4] ) const
{
int nCount = 0;
if ( HasAllocatedMemory( FBM_ATTR_RED ) )
pIndex[ nCount++ ] = FBM_ATTR_RED;
if ( HasAllocatedMemory( FBM_ATTR_GREEN ) )
pIndex[ nCount++ ] = FBM_ATTR_GREEN;
if ( HasAllocatedMemory( FBM_ATTR_BLUE ) )
pIndex[ nCount++ ] = FBM_ATTR_BLUE;
if ( HasAllocatedMemory( FBM_ATTR_ALPHA ) )
pIndex[ nCount++ ] = FBM_ATTR_ALPHA;
return nCount;
}
//-----------------------------------------------------------------------------
// Does the bitmap have data for a particular component?
//-----------------------------------------------------------------------------
inline bool FloatBitMap_t::HasAttributeData( FBMAttribute_t a ) const
{
return HasAllocatedMemory( a );
}
inline int FloatBitMap_t::CoordWrap( int nC, int nLimit )
{
if ( nC >= nLimit )
{
nC %= nLimit;
}
else if ( nC < 0 )
{
nC += nLimit * ( ( -nC + nLimit-1 ) / nLimit );
}
return nC;
}
inline float &FloatBitMap_t::Pixel(int x, int y, int z, int comp) const
{
Assert( (x >= 0 ) && (x < NumCols() ) );
Assert( (y >= 0) && (y < NumRows() ) );
Assert( (z >= 0) && (z < NumSlices() ) );
float *pData = ElementPointer<float>( comp, x, y, z );
return *pData;
}
inline const float &FloatBitMap_t::ConstantValue( int comp ) const
{
Assert( !HasAllocatedMemory( comp ) );
return Pixel( 0, 0, 0, comp );
}
inline float &FloatBitMap_t::PixelWrapped(int x, int y, int z, int comp) const
{
// like Pixel except wraps around to other side
x = CoordWrap( x, NumCols() );
y = CoordWrap( y, NumRows() );
z = CoordWrap( z, NumSlices() );
return Pixel( x, y, z, comp );
}
inline float &FloatBitMap_t::PixelClamped(int x, int y, int z, int comp) const
{
// like Pixel except wraps around to other side
x = clamp( x, 0, NumCols() - 1 );
y = clamp( y, 0, NumRows() - 1 );
z = clamp( z, 0, NumSlices() - 1 );
return Pixel( x, y, z, comp );
}
inline float &FloatBitMap_t::Alpha( int x, int y, int z ) const
{
Assert( ( x >= 0 ) && ( x < NumCols() ) );
Assert( ( y >= 0 ) && ( y < NumRows() ) );
Assert( ( z >= 0 ) && ( z < NumSlices() ) );
return Pixel( x, y, z, FBM_ATTR_ALPHA );
}
inline PixRGBAF FloatBitMap_t::PixelRGBAF( int x, int y, int z ) const
{
Assert( ( x >= 0 ) && ( x < NumCols() ) );
Assert( ( y >= 0 ) && ( y < NumRows() ) );
Assert( ( z >= 0 ) && ( z < NumSlices() ) );
PixRGBAF RetPix;
RetPix.Red = Pixel( x, y, z, FBM_ATTR_RED );
RetPix.Green = Pixel( x, y, z, FBM_ATTR_GREEN );
RetPix.Blue = Pixel( x, y, z, FBM_ATTR_BLUE );
RetPix.Alpha = Pixel( x, y, z, FBM_ATTR_ALPHA );
return RetPix;
}
inline void FloatBitMap_t::WritePixelRGBAF( int x, int y, int z, PixRGBAF value ) const
{
Pixel( x, y, z, FBM_ATTR_RED ) = value.Red;
Pixel( x, y, z, FBM_ATTR_GREEN ) = value.Green;
Pixel( x, y, z, FBM_ATTR_BLUE ) = value.Blue;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = value.Alpha;
}
inline void FloatBitMap_t::WritePixel(int x, int y, int z, int comp, float value)
{
Pixel( x, y, z, comp ) = value;
}
//-----------------------------------------------------------------------------
// Loads an array of image data into a buffer
//-----------------------------------------------------------------------------
template< class T > void FloatBitMap_t::LoadFromBufferRGBFloat( const T *pBuffer, int nPixelCount )
{
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = pBuffer[x].r;
Pixel( x, y, z, FBM_ATTR_GREEN ) = pBuffer[x].g;
Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].b;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::LoadFromBufferRGB( const T *pBuffer, int nPixelCount, const float *pGammaTable )
{
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = pGammaTable[ pBuffer[x].RTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_GREEN ) = pGammaTable[ pBuffer[x].GTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_BLUE ) = pGammaTable[ pBuffer[x].BTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::LoadFromBufferRGBAFloat( const T *pBuffer, int nPixelCount )
{
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = pBuffer[x].r;
Pixel( x, y, z, FBM_ATTR_GREEN ) = pBuffer[x].g;
Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].b;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = pBuffer[x].a;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::LoadFromBufferRGBA( const T *pBuffer, int nPixelCount, const float *pGammaTable )
{
float flOO1023 = 1.0f / 1023.0f;
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = pGammaTable[ pBuffer[x].RTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_GREEN ) = pGammaTable[ pBuffer[x].GTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_BLUE ) = pGammaTable[ pBuffer[x].BTo10Bit( ) ];
Pixel( x, y, z, FBM_ATTR_ALPHA ) = pBuffer[x].ATo10Bit( ) * flOO1023;
}
pBuffer += NumCols();
}
}
}
//-----------------------------------------------------------------------------
// Loads from UV buffers
//-----------------------------------------------------------------------------
template< class T > void FloatBitMap_t::LoadFromBufferUV( const T *pBuffer, int nPixelCount )
{
float fl2O255 = 2.0f / 255.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * fl2O255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * fl2O255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_BLUE ) = 0.0f;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::LoadFromBufferUVWQ( const T *pBuffer, int nPixelCount )
{
float fl2O255 = 2.0f / 255.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * fl2O255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * fl2O255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_BLUE ) = ( pBuffer[x].w + 128 ) * fl2O255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = ( pBuffer[x].q + 128 ) * fl2O255 - 1.0f;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::LoadFromBufferUVLX( const T *pBuffer, int nPixelCount )
{
float flOO255 = 1.0f / 255.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
Pixel( x, y, z, FBM_ATTR_RED ) = ( pBuffer[x].u + 128 ) * 2.0f * flOO255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_GREEN ) = ( pBuffer[x].v + 128 ) * 2.0f * flOO255 - 1.0f;
Pixel( x, y, z, FBM_ATTR_BLUE ) = pBuffer[x].l * flOO255;
Pixel( x, y, z, FBM_ATTR_ALPHA ) = 1.0f;
}
pBuffer += NumCols();
}
}
}
//-----------------------------------------------------------------------------
// Writes an array of image data into a buffer
//-----------------------------------------------------------------------------
template< class T > void FloatBitMap_t::WriteToBufferRGBFloat( T *pBuffer, int nPixelCount ) const
{
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
pBuffer[x].r = Pixel( x, y, z, FBM_ATTR_RED );
pBuffer[x].g = Pixel( x, y, z, FBM_ATTR_GREEN );
pBuffer[x].b = Pixel( x, y, z, FBM_ATTR_BLUE );
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::WriteToBufferRGB( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const
{
int c;
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_RED ) + 0.5f );
pBuffer[x].RFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_GREEN ) + 0.5f );
pBuffer[x].GFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) + 0.5f );
pBuffer[x].BFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::WriteToBufferRGBAFloat( T *pBuffer, int nPixelCount ) const
{
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
pBuffer[x].r = Pixel( x, y, z, FBM_ATTR_RED );
pBuffer[x].g = Pixel( x, y, z, FBM_ATTR_GREEN );
pBuffer[x].b = Pixel( x, y, z, FBM_ATTR_BLUE );
pBuffer[x].a = Pixel( x, y, z, FBM_ATTR_ALPHA );
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::WriteToBufferRGBA( T *pBuffer, int nPixelCount, const uint16 *pInvGammaTable ) const
{
int c;
Assert( nPixelCount == NumCols() * NumRows() * NumSlices() );
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_RED ) + 0.5f );
pBuffer[x].RFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_GREEN ) + 0.5f );
pBuffer[x].GFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) + 0.5f );
pBuffer[x].BFrom10Bit( pInvGammaTable[ clamp( c, 0, 1023 ) ] );
c = ( int )( 1023.0f * Pixel( x, y, z, FBM_ATTR_ALPHA ) + 0.5f );
pBuffer[x].AFrom10Bit( clamp( c, 0, 1023 ) );
}
pBuffer += NumCols();
}
}
}
//-----------------------------------------------------------------------------
// Writes to UV buffers
//-----------------------------------------------------------------------------
template< class T > void FloatBitMap_t::WriteToBufferUV( T *pBuffer, int nPixelCount ) const
{
int c;
float fl255O2 = 255.0f / 2.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
pBuffer[x].u = clamp( c, 0, 255 ) - 128;
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
pBuffer[x].v = clamp( c, 0, 255 ) - 128;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::WriteToBufferUVWQ( T *pBuffer, int nPixelCount ) const
{
int c;
float fl255O2 = 255.0f / 2.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
pBuffer[x].u = clamp( c, 0, 255 ) - 128;
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
pBuffer[x].v = clamp( c, 0, 255 ) - 128;
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_BLUE ) + 1.0f ) );
pBuffer[x].w = clamp( c, 0, 255 ) - 128;
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_ALPHA ) + 1.0f ) );
pBuffer[x].q = clamp( c, 0, 255 ) - 128;
}
pBuffer += NumCols();
}
}
}
template< class T > void FloatBitMap_t::WriteToBufferUVLX( T *pBuffer, int nPixelCount ) const
{
int c;
float fl255O2 = 255.0f / 2.0f;
for( int z = 0; z < NumSlices(); ++z )
{
for( int y = 0; y < NumRows(); ++y )
{
for( int x = 0; x < NumCols(); ++x )
{
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_RED ) + 1.0f ) );
pBuffer[x].u = clamp( c, 0, 255 ) - 128;
c = ( int )( fl255O2 * ( Pixel( x, y, z, FBM_ATTR_GREEN ) + 1.0f ) );
pBuffer[x].v = clamp( c, 0, 255 ) - 128;
c = ( int )( 255.0f * Pixel( x, y, z, FBM_ATTR_BLUE ) );
pBuffer[x].l = clamp( c, 0, 255 );
pBuffer[x].x = 255;
}
pBuffer += NumCols();
}
}
}
// a FloatCubeMap_t holds the floating point bitmaps for 6 faces of a cube map
class FloatCubeMap_t
{
public:
FloatBitMap_t face_maps[6];
FloatCubeMap_t(int xfsize, int yfsize)
{
// make an empty one with face dimensions xfsize x yfsize
for(int f=0;f<6;f++)
{
face_maps[f].Init(xfsize,yfsize);
}
}
// load basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
FloatCubeMap_t(const char *basename);
// save basenamebk,pfm, basenamedn.pfm, basenameft.pfm, ...
void WritePFMs(const char *basename);
Vector AverageColor(void)
{
Vector ret(0,0,0);
int nfaces = 0;
for( int f = 0;f < 6;f ++ )
if ( face_maps[f].NumElements() )
{
nfaces++;
ret += face_maps[f].AverageColor();
}
if ( nfaces )
ret *= ( 1.0 / nfaces );
return ret;
}
float BrightestColor( void )
{
float ret = 0.0;
for( int f = 0;f < 6;f ++ )
if ( face_maps[f].NumElements() )
{
ret = MAX( ret, face_maps[f].BrightestColor() );
}
return ret;
}
// generate the N-order spherical harmonic coeffcients to approxiamte this cubemap.
// for order N, this will fill in 1 + 2 * N + N^2 vectors ( 0 = 0, 1 = 4, 2 = 9 .. )
// vectors are used to hold the r,g,b coeffs
void CalculateSphericalHarmonicApproximation( int nOrder, Vector *flCoeffs );
// inverse of above
void GenerateFromSphericalHarmonics( int nOrder, Vector const *flCoeffs );
// resample a cubemap to one of possibly a lower resolution, using a given phong exponent.
// dot-product weighting will be used for the filtering operation.
void Resample(FloatCubeMap_t &dest, float flPhongExponent);
// returns the normalized direciton vector through a given pixel of a given face
Vector PixelDirection(int face, int x, int y);
// returns the direction vector throught the center of a cubemap face
Vector FaceNormal( int nFaceNumber );
};
// Image Pyramid class.
#define MAX_IMAGE_PYRAMID_LEVELS 16 // up to 64kx64k
enum ImagePyramidMode_t
{
PYRAMID_MODE_GAUSSIAN,
};
class FloatImagePyramid_t
{
public:
int m_nLevels;
FloatBitMap_t *m_pLevels[MAX_IMAGE_PYRAMID_LEVELS]; // level 0 is highest res
FloatImagePyramid_t(void)
{
m_nLevels = 0;
memset( m_pLevels, 0, sizeof( m_pLevels ));
}
// build one. clones data from src for level 0.
FloatImagePyramid_t(const FloatBitMap_t &src, ImagePyramidMode_t mode);
// read or write a Pixel from a given level. All coordinates are specified in the same domain as the base level.
float &Pixel(int x, int y, int component, int level) const;
FloatBitMap_t *Level(int lvl) const
{
Assert( lvl < m_nLevels );
return m_pLevels[lvl];
}
// rebuild all levels above the specified level
void ReconstructLowerResolutionLevels(int starting_level);
~FloatImagePyramid_t(void);
void WriteTGAs(const char *basename) const; // outputs name_00.tga, name_01.tga,...
};
#endif

679
public/bitmap/imageformat.h Normal file
View File

@ -0,0 +1,679 @@
//===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef IMAGEFORMAT_H
#define IMAGEFORMAT_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
#include "tier0/platform.h"
#include "tier0/dbg.h"
#include "bitmap/imageformat_declarations.h"
//-----------------------------------------------------------------------------
// Color structures
//-----------------------------------------------------------------------------
#pragma warning ( disable : 4293 )
template< int nBitCount > FORCEINLINE int ConvertTo10Bit( int x )
{
switch ( nBitCount )
{
case 1:
return ( x & 0x1 ) ? 0x3FF : 0;
case 2:
return ( x << 8 ) | ( x << 6 ) | ( x << 4 ) | ( x << 2 ) | x;
case 3:
return ( x << 7 ) | ( x << 4 ) | ( x << 1 ) | ( x >> 2 );
case 4:
return ( x << 6 ) | ( x << 2 ) | ( x >> 2 );
default:
#if defined(POSIX) || defined(_PS3)
return ( x << ( 10 - nBitCount ) ) | ( x >> MAX( 0, MIN( 32, ( nBitCount - ( 10 - nBitCount ) ) ) ) );
#else // !_PS3
return ( x << ( 10 - nBitCount ) ) | ( x >> ( nBitCount - ( 10 - nBitCount ) ) );
#endif
}
}
#pragma warning ( default : 4293 )
template< int nBitCount > FORCEINLINE int ConvertFrom10Bit( int x )
{
return ( x >> ( 10 - nBitCount ) );
}
struct R32F_t
{
float32 r;
};
struct RG3232F_t
{
float32 r;
float32 g;
};
struct RGB323232F_t
{
float32 r;
float32 g;
float32 b;
};
struct RGBA32323232F_t
{
float32 r;
float32 g;
float32 b;
float32 a;
};
struct RGBA1010102_t
{
uint32 r : 10;
uint32 g : 10;
uint32 b : 10;
uint32 a : 2;
inline int RTo10Bit( ) const { return ConvertTo10Bit<10>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<10>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<10>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<2>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<10>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<10>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<10>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<10>( a10 ); }
};
struct BGRA1010102_t
{
uint32 b : 10;
uint32 g : 10;
uint32 r : 10;
uint32 a : 2;
inline int RTo10Bit( ) const { return ConvertTo10Bit<10>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<10>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<10>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<2>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<10>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<10>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<10>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<10>( a10 ); }
};
struct BGRA8888_t
{
uint8 b; // change the order of names to change the
uint8 g; // order of the output ARGB or BGRA, etc...
uint8 r; // Last one is MSB, 1st is LSB.
uint8 a;
inline BGRA8888_t& operator=( const BGRA8888_t& in )
{
*( unsigned int * )this = *( unsigned int * )&in;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<8>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<8>( a10 ); }
};
struct ABGR8888_t
{
uint8 a;
uint8 b; // change the order of names to change the
uint8 g; // order of the output ARGB or BGRA, etc...
uint8 r; // Last one is MSB, 1st is LSB.
inline ABGR8888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
a = in.a;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<8>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<8>( a10 ); }
};
struct RGBA8888_t
{
uint8 r; // change the order of names to change the
uint8 g; // order of the output ARGB or BGRA, etc...
uint8 b; // Last one is MSB, 1st is LSB.
uint8 a;
inline RGBA8888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
a = in.a;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<8>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<8>( a10 ); }
};
struct RGB888_t
{
uint8 r;
uint8 g;
uint8 b;
inline RGB888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
return *this;
}
inline bool operator==( const RGB888_t& in ) const
{
return ( r == in.r ) && ( g == in.g ) && ( b == in.b );
}
inline bool operator!=( const RGB888_t& in ) const
{
return ( r != in.r ) || ( g != in.g ) || ( b != in.b );
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
};
struct BGR888_t
{
uint8 b;
uint8 g;
uint8 r;
inline BGR888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
};
struct BGRX8888_t
{
uint8 b;
uint8 g;
uint8 r;
uint8 x;
inline BGRX8888_t& operator=( const BGRA8888_t& in )
{
r = in.r;
g = in.g;
b = in.b;
x = 255;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<8>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<8>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<8>( b ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<8>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<8>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<8>( b10 ); }
};
// 360 uses this structure for x86 dxt decoding
#if defined( _X360 )
#pragma bitfield_order( push, lsb_to_msb )
#elif defined( _PS3 )
#pragma ms_struct on
#pragma reverse_bitfields on
#endif
struct BGR565_t
{
uint16 b : 5; // order of names changes
uint16 g : 6; // byte order of output to 32 bit
uint16 r : 5;
inline BGR565_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 2;
b = in.b >> 3;
return *this;
}
inline BGR565_t &Set( int red, int green, int blue )
{
r = red >> 3;
g = green >> 2;
b = blue >> 3;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<5>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<6>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<5>( b ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<5>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<6>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<5>( b10 ); }
};
#if defined( _X360 )
#pragma bitfield_order( pop )
#elif defined( _PS3 )
#pragma ms_struct off
#pragma reverse_bitfields off
#endif
struct BGRA5551_t
{
uint16 b : 5; // order of names changes
uint16 g : 5; // byte order of output to 32 bit
uint16 r : 5;
uint16 a : 1;
inline BGRA5551_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 3;
b = in.b >> 3;
a = in.a >> 7;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<5>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<5>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<5>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<1>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<5>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<5>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<5>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<1>( a10 ); }
};
struct BGRA4444_t
{
uint16 b : 4; // order of names changes
uint16 g : 4; // byte order of output to 32 bit
uint16 r : 4;
uint16 a : 4;
inline BGRA4444_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 4;
g = in.g >> 4;
b = in.b >> 4;
a = in.a >> 4;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<4>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<4>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<4>( b ); }
inline int ATo10Bit( ) const { return ConvertTo10Bit<4>( a ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<4>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<4>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<4>( b10 ); }
inline void AFrom10Bit( int a10 ) { a = ConvertFrom10Bit<4>( a10 ); }
};
struct RGBX5551_t
{
uint16 r : 5;
uint16 g : 5;
uint16 b : 5;
uint16 x : 1;
inline RGBX5551_t& operator=( const BGRA8888_t& in )
{
r = in.r >> 3;
g = in.g >> 3;
b = in.b >> 3;
return *this;
}
inline int RTo10Bit( ) const { return ConvertTo10Bit<5>( r ); }
inline int GTo10Bit( ) const { return ConvertTo10Bit<5>( g ); }
inline int BTo10Bit( ) const { return ConvertTo10Bit<5>( b ); }
inline void RFrom10Bit( int r10 ) { r = ConvertFrom10Bit<5>( r10 ); }
inline void GFrom10Bit( int g10 ) { g = ConvertFrom10Bit<5>( g10 ); }
inline void BFrom10Bit( int b10 ) { b = ConvertFrom10Bit<5>( b10 ); }
};
struct UV88_t
{
int8 u;
int8 v;
};
struct UVWQ8888_t
{
int8 u;
int8 v;
int8 w;
int8 q;
};
struct UVLX8888_t
{
int8 u;
int8 v;
uint8 l;
uint8 x;
};
//-----------------------------------------------------------------------------
// some important constants
//-----------------------------------------------------------------------------
#define ARTWORK_GAMMA ( 2.2f )
#define IMAGE_MAX_DIM ( 2048 )
//-----------------------------------------------------------------------------
// information about each image format
//-----------------------------------------------------------------------------
struct ImageFormatInfo_t
{
const char* m_pName;
uint8 m_nNumBytes;
uint8 m_nNumRedBits;
uint8 m_nNumGreenBits;
uint8 m_nNumBlueBits;
uint8 m_nNumAlphaBits;
uint8 m_nNumDepthBits;
uint8 m_nNumStencilBits;
bool m_bIsCompressed:1;
bool m_bIsFloat:1;
bool m_bIsDepthFormat : 1;
};
//-----------------------------------------------------------------------------
// Computes nice filters for a compression ratio
//-----------------------------------------------------------------------------
struct KernelInfo_t
{
float *m_pKernel;
float *m_pInvKernel;
int m_nWidth;
int m_nHeight;
int m_nDepth;
int m_nDiameter;
};
//-----------------------------------------------------------------------------
// Indicates the target console type that a given operation is for.
// (e.g. you may be running on the PC but you're generating textures
// for X360 or PS3, so IsPC, IsX360, etc. do not work)
//-----------------------------------------------------------------------------
enum VtfConsoleFormatType_t
{
VTF_CONSOLE_360,
VTF_CONSOLE_PS3
};
//-----------------------------------------------------------------------------
// Various methods related to pixelmaps and color formats
//-----------------------------------------------------------------------------
namespace ImageLoader
{
bool GetInfo( const char *fileName, int *width, int *height, enum ImageFormat *imageFormat, float *sourceGamma );
// Generates a nice filter kernel
void ComputeNiceFilterKernel( float flWRatio, float flHRatio, float flDRatio, KernelInfo_t *pKernel );
void CleanupNiceFilterKernel( KernelInfo_t *pKernel );
// adjustedheight received the height adjusted for compression (/4 for dxt)
int GetMemRequired( int width, int height, int depth, ImageFormat imageFormat, bool mipmap, int *pAdjustedHeightOut = NULL );
int GetMemRequired( int width, int height, int depth, int nMipmapCount, ImageFormat imageFormat, int *pAdjustedHeightOut = NULL );
// This version is for mipmaps which are stored biggest level to smallest level in memory
int GetMipMapLevelByteOffset( int width, int height, ImageFormat imageFormat, int skipMipLevels, int nDepth = 1 );
// This version is for mipmaps which are stored smallest level to largest level in memory
int GetMipMapLevelByteOffsetReverse( int nWidth, int nHeight, int nDepth, int nTotalMipCount, ImageFormat imageFormat, int nMipLevel );
void GetMipMapLevelDimensions( int *width, int *height, int skipMipLevels );
void GetMipMapLevelDimensions( int &nWidth, int &nHeight, int &nDepth, int nMipLevel );
int GetNumMipMapLevels( int width, int height, int depth = 1 );
bool Load( unsigned char *imageData, const char *fileName, int width, int height, ImageFormat imageFormat, float targetGamma, bool mipmap );
bool Load( unsigned char *imageData, FILE *fp, int width, int height,
enum ImageFormat imageFormat, float targetGamma, bool mipmap );
// convert from any image format to any other image format.
// return false if the conversion cannot be performed.
// Strides denote the number of bytes per each line,
// by default assumes width * # of bytes per pixel
bool ConvertImageFormat( const unsigned char *src, enum ImageFormat srcImageFormat,
unsigned char *dst, enum ImageFormat dstImageFormat,
int width, int height, int srcStride = 0, int dstStride = 0 );
// must be used in conjunction with ConvertImageFormat() to pre-swap and post-swap
void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, VtfConsoleFormatType_t targetConsole, int width = 0, int stride = 0 );
void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, VtfConsoleFormatType_t targetConsole, int width = 0, int stride = 0 );
void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width = 0, int stride = 0 );
bool IsFormatValidForConversion( ImageFormat fmt );
//-----------------------------------------------------------------------------
// convert back and forth from D3D format to ImageFormat, regardless of
// whether it's supported or not
// FIXME: Move into shaderapidx8/rendersystemdx9
//-----------------------------------------------------------------------------
ImageFormat D3DFormatToImageFormat( D3DFORMAT format );
D3DFORMAT ImageFormatToD3DFormat( ImageFormat format );
// Flags for ResampleRGBA8888
enum
{
RESAMPLE_NORMALMAP = 0x1,
RESAMPLE_ALPHATEST = 0x2,
RESAMPLE_NICE_FILTER = 0x4,
RESAMPLE_CLAMPS = 0x8,
RESAMPLE_CLAMPT = 0x10,
RESAMPLE_CLAMPU = 0x20,
};
struct ResampleInfo_t
{
ResampleInfo_t() : m_nFlags(0), m_flAlphaThreshhold(0.4f), m_flAlphaHiFreqThreshhold(0.4f), m_nSrcDepth(1), m_nDestDepth(1)
{
m_flColorScale[0] = 1.0f, m_flColorScale[1] = 1.0f, m_flColorScale[2] = 1.0f, m_flColorScale[3] = 1.0f;
m_flColorGoal[0] = 0.0f, m_flColorGoal[1] = 0.0f, m_flColorGoal[2] = 0.0f, m_flColorGoal[3] = 0.0f;
}
unsigned char *m_pSrc;
unsigned char *m_pDest;
int m_nSrcWidth;
int m_nSrcHeight;
int m_nSrcDepth;
int m_nDestWidth;
int m_nDestHeight;
int m_nDestDepth;
float m_flSrcGamma;
float m_flDestGamma;
float m_flColorScale[4]; // Color scale factors RGBA
float m_flColorGoal[4]; // Color goal values RGBA DestColor = ColorGoal + scale * (SrcColor - ColorGoal)
float m_flAlphaThreshhold;
float m_flAlphaHiFreqThreshhold;
int m_nFlags;
};
bool ResampleRGBA8888( const ResampleInfo_t &info );
bool ResampleRGBA16161616( const ResampleInfo_t &info );
bool ResampleRGB323232F( const ResampleInfo_t &info );
bool ResampleRGBA32323232F( const ResampleInfo_t &info );
void ConvertNormalMapRGBA8888ToDUDVMapUVLX8888( const unsigned char *src, int width, int height, unsigned char *dst_ );
void ConvertNormalMapRGBA8888ToDUDVMapUVWQ8888( const unsigned char *src, int width, int height, unsigned char *dst_ );
void ConvertNormalMapRGBA8888ToDUDVMapUV88( const unsigned char *src, int width, int height, unsigned char *dst_ );
void ConvertNormalMapARGB8888ToDXT5GA( const unsigned char *src, unsigned char *dst, int width, int height );
void ConvertIA88ImageToNormalMapRGBA8888( const unsigned char *src, int width,
int height, unsigned char *dst,
float bumpScale );
void NormalizeNormalMapRGBA8888( unsigned char *src, int numTexels );
//-----------------------------------------------------------------------------
// Gamma correction
//-----------------------------------------------------------------------------
void GammaCorrectRGBA8888( unsigned char *src, unsigned char* dst,
int width, int height, int depth, float srcGamma, float dstGamma );
//-----------------------------------------------------------------------------
// Makes a gamma table
//-----------------------------------------------------------------------------
void ConstructGammaTable( unsigned char* pTable, float srcGamma, float dstGamma );
//-----------------------------------------------------------------------------
// Gamma corrects using a previously constructed gamma table
//-----------------------------------------------------------------------------
void GammaCorrectRGBA8888( unsigned char* pSrc, unsigned char* pDst,
int width, int height, int depth, unsigned char* pGammaTable );
//-----------------------------------------------------------------------------
// Generates a number of mipmap levels
//-----------------------------------------------------------------------------
void GenerateMipmapLevels( unsigned char* pSrc, unsigned char* pDst, int width,
int height, int depth, ImageFormat imageFormat, float srcGamma, float dstGamma,
int numLevels = 0 );
//-----------------------------------------------------------------------------
// operations on square images (src and dst can be the same)
//-----------------------------------------------------------------------------
bool RotateImageLeft( const unsigned char *src, unsigned char *dst,
int widthHeight, ImageFormat imageFormat );
bool RotateImage180( const unsigned char *src, unsigned char *dst,
int widthHeight, ImageFormat imageFormat );
bool FlipImageVertically( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
bool FlipImageHorizontally( void *pSrc, void *pDst, int nWidth, int nHeight, ImageFormat imageFormat, int nDstStride = 0 );
bool SwapAxes( unsigned char *src,
int widthHeight, ImageFormat imageFormat );
//-----------------------------------------------------------------------------
// Returns info about each image format
//-----------------------------------------------------------------------------
const ImageFormatInfo_t &ImageFormatInfo( ImageFormat fmt );
//-----------------------------------------------------------------------------
// Gets the name of the image format
//-----------------------------------------------------------------------------
inline char const* GetName( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_pName;
}
//-----------------------------------------------------------------------------
// Gets the size of the image format in bytes. Be careful - compressed formats will return 0
//-----------------------------------------------------------------------------
inline int SizeInBytes( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_nNumBytes;
}
/// return the byte size of a given w/h. Works with compressed formats
inline int SizeInBytes( ImageFormat fmt, int nWidth, int nHeight )
{
ImageFormatInfo_t const &info = ImageFormatInfo( fmt );
if ( info.m_bIsCompressed )
{
// !!BUG!! hardcoded 4x4 block size, dxt1, dxt5
int nNumBytesPerBlock = 8;
if ( fmt == IMAGE_FORMAT_DXT5 )
{
nNumBytesPerBlock = 16;
}
return nNumBytesPerBlock * ( ( nWidth + 3 ) / 4 ) * ( ( nHeight +3 )/ 4 );
}
else
{
return info.m_nNumBytes * nWidth * nHeight;
}
}
//-----------------------------------------------------------------------------
// Does the image format support transparency?
//-----------------------------------------------------------------------------
inline bool IsTransparent( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_nNumAlphaBits > 0;
}
//-----------------------------------------------------------------------------
// Is the image format compressed?
//-----------------------------------------------------------------------------
inline bool IsCompressed( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_bIsCompressed;
}
//-----------------------------------------------------------------------------
// Is the image format compressed?
//-----------------------------------------------------------------------------
inline bool IsDepthFormat( ImageFormat fmt )
{
return ImageFormatInfo(fmt).m_bIsDepthFormat;
}
//-----------------------------------------------------------------------------
// Is any channel > 8 bits?
//-----------------------------------------------------------------------------
inline bool HasChannelLargerThan8Bits( ImageFormat fmt )
{
ImageFormatInfo_t info = ImageFormatInfo(fmt);
return ( info.m_nNumRedBits > 8 || info.m_nNumGreenBits > 8 || info.m_nNumBlueBits > 8 || info.m_nNumAlphaBits > 8 );
}
inline bool IsFloatFormat( ImageFormat fmt )
{
return ( fmt == IMAGE_FORMAT_RGBA16161616F ) ||
( fmt == IMAGE_FORMAT_RG1616F ) ||
( fmt == IMAGE_FORMAT_R32F ) ||
( fmt == IMAGE_FORMAT_RG3232F ) ||
( fmt == IMAGE_FORMAT_RGB323232F ) ||
( fmt == IMAGE_FORMAT_RGBA32323232F );
}
inline bool IsRuntimeCompressed( ImageFormat fmt )
{
return ( fmt == IMAGE_FORMAT_DXT1_RUNTIME ) || ( fmt == IMAGE_FORMAT_DXT5_RUNTIME );
}
} // end namespace ImageLoader
#endif // IMAGEFORMAT_H

View File

@ -0,0 +1,189 @@
//========== Copyright <20> Valve Corporation, All rights reserved. ========
#ifndef IMAGEFORMAT_DECLARATIONS_HDR
#define IMAGEFORMAT_DECLARATIONS_HDR
enum NormalDecodeMode_t
{
NORMAL_DECODE_NONE = 0,
NORMAL_DECODE_ATI2N = 1,
NORMAL_DECODE_ATI2N_ALPHA = 2
};
// Forward declaration
#ifdef _WIN32
typedef enum _D3DFORMAT D3DFORMAT;
typedef enum DXGI_FORMAT;
#endif
//-----------------------------------------------------------------------------
// The various image format types
//-----------------------------------------------------------------------------
// don't bitch that inline functions aren't used!!!!
#ifndef SPU
#pragma warning(disable : 4514)
#endif
enum ImageFormat
{
IMAGE_FORMAT_DEFAULT = -2, // Use this image format if you want to perform tool operations on the texture
IMAGE_FORMAT_UNKNOWN = -1,
IMAGE_FORMAT_RGBA8888 = 0,
IMAGE_FORMAT_ABGR8888,
IMAGE_FORMAT_RGB888,
IMAGE_FORMAT_BGR888,
IMAGE_FORMAT_RGB565,
IMAGE_FORMAT_I8,
IMAGE_FORMAT_IA88,
IMAGE_FORMAT_P8,
IMAGE_FORMAT_A8,
IMAGE_FORMAT_RGB888_BLUESCREEN,
IMAGE_FORMAT_BGR888_BLUESCREEN,
IMAGE_FORMAT_ARGB8888,
IMAGE_FORMAT_BGRA8888,
IMAGE_FORMAT_DXT1,
IMAGE_FORMAT_DXT3,
IMAGE_FORMAT_DXT5,
IMAGE_FORMAT_BGRX8888,
IMAGE_FORMAT_BGR565,
IMAGE_FORMAT_BGRX5551,
IMAGE_FORMAT_BGRA4444,
IMAGE_FORMAT_DXT1_ONEBITALPHA,
IMAGE_FORMAT_BGRA5551,
IMAGE_FORMAT_UV88,
IMAGE_FORMAT_UVWQ8888,
IMAGE_FORMAT_RGBA16161616F,
IMAGE_FORMAT_RGBA16161616,
IMAGE_FORMAT_UVLX8888,
IMAGE_FORMAT_R32F, // Single-channel 32-bit floating point
IMAGE_FORMAT_RGB323232F, // NOTE: D3D9 does not have this format
IMAGE_FORMAT_RGBA32323232F,
IMAGE_FORMAT_RG1616F,
IMAGE_FORMAT_RG3232F,
IMAGE_FORMAT_RGBX8888,
IMAGE_FORMAT_NULL, // Dummy format which takes no video memory
// Compressed normal map formats
IMAGE_FORMAT_ATI2N, // One-surface ATI2N / DXN format
IMAGE_FORMAT_ATI1N, // Two-surface ATI1N format
IMAGE_FORMAT_RGBA1010102, // 10 bit-per component render targets
IMAGE_FORMAT_BGRA1010102,
IMAGE_FORMAT_R16F, // 16 bit FP format
// Depth-stencil texture formats
IMAGE_FORMAT_D16,
IMAGE_FORMAT_D15S1,
IMAGE_FORMAT_D32,
IMAGE_FORMAT_D24S8,
IMAGE_FORMAT_LINEAR_D24S8,
IMAGE_FORMAT_D24X8,
IMAGE_FORMAT_D24X4S4,
IMAGE_FORMAT_D24FS8,
IMAGE_FORMAT_D16_SHADOW, // Specific formats for shadow mapping
IMAGE_FORMAT_D24X8_SHADOW, // Specific formats for shadow mapping
// supporting these specific formats as non-tiled for procedural cpu access (360-specific)
IMAGE_FORMAT_LINEAR_BGRX8888,
IMAGE_FORMAT_LINEAR_RGBA8888,
IMAGE_FORMAT_LINEAR_ABGR8888,
IMAGE_FORMAT_LINEAR_ARGB8888,
IMAGE_FORMAT_LINEAR_BGRA8888,
IMAGE_FORMAT_LINEAR_RGB888,
IMAGE_FORMAT_LINEAR_BGR888,
IMAGE_FORMAT_LINEAR_BGRX5551,
IMAGE_FORMAT_LINEAR_I8,
IMAGE_FORMAT_LINEAR_RGBA16161616,
IMAGE_FORMAT_LINEAR_A8,
IMAGE_FORMAT_LINEAR_DXT1,
IMAGE_FORMAT_LINEAR_DXT3,
IMAGE_FORMAT_LINEAR_DXT5,
IMAGE_FORMAT_LE_BGRX8888,
IMAGE_FORMAT_LE_BGRA8888,
// these are used for runtime conversion to DXT1/5
IMAGE_FORMAT_DXT1_RUNTIME,
IMAGE_FORMAT_DXT5_RUNTIME,
// special depth format
IMAGE_FORMAT_INTZ,
NUM_IMAGE_FORMATS
};
#if defined( DX_TO_GL_ABSTRACTION ) || defined( _PS3 )
typedef enum _D3DFORMAT
{
D3DFMT_INDEX16,
D3DFMT_D16,
D3DFMT_D24S8,
D3DFMT_A8R8G8B8,
D3DFMT_A4R4G4B4,
D3DFMT_X8R8G8B8,
D3DFMT_R5G6R5,
D3DFMT_X1R5G5B5,
D3DFMT_A1R5G5B5,
D3DFMT_L8,
D3DFMT_A8L8,
D3DFMT_A,
D3DFMT_DXT1,
D3DFMT_DXT3,
D3DFMT_DXT5,
D3DFMT_V8U8,
D3DFMT_Q8W8V8U8,
D3DFMT_X8L8V8U8,
D3DFMT_A16B16G16R16F,
D3DFMT_A16B16G16R16,
D3DFMT_R32F,
D3DFMT_A32B32G32R32F,
D3DFMT_R8G8B8,
D3DFMT_D24X4S4,
D3DFMT_A8,
D3DFMT_R5G6B5,
D3DFMT_D15S1,
D3DFMT_D24X8,
D3DFMT_VERTEXDATA,
D3DFMT_INDEX32,
// new d3d format enums for Source main engine (i.e Portal2, AS, Dota)
D3DFMT_D24FS8,
D3DFMT_A8B8G8R8,
D3DFMT_P8,
D3DFMT_G16R16F,
D3DFMT_G32R32F,
D3DFMT_X8B8G8R8,
D3DFMT_A2B10G10R10,
D3DFMT_A2R10G10B10,
D3DFMT_R16F,
D3DFMT_D32,
// adding fake D3D format names for the vendor specific ones (eases debugging/logging)
// NV shadow depth tex
D3DFMT_NV_INTZ = 0x5a544e49, // MAKEFOURCC('I','N','T','Z')
D3DFMT_NV_RAWZ = 0x5a574152, // MAKEFOURCC('R','A','W','Z')
// NV null tex
D3DFMT_NV_NULL = 0x4c4c554e, // MAKEFOURCC('N','U','L','L')
// ATI shadow depth tex
D3DFMT_ATI_D16 = 0x36314644, // MAKEFOURCC('D','F','1','6')
D3DFMT_ATI_D24S8 = 0x34324644, // MAKEFOURCC('D','F','2','4')
// ATI 1N and 2N compressed tex
D3DFMT_ATI_2N = 0x32495441, // MAKEFOURCC('A', 'T', 'I', '2')
D3DFMT_ATI_1N = 0x31495441, // MAKEFOURCC('A', 'T', 'I', '1')
D3DFMT_UNKNOWN
} D3DFORMAT;
#endif
#endif

105
public/bitmap/psd.h Normal file
View File

@ -0,0 +1,105 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Methods relating to saving + loading PSD files (photoshop)
//
// $NoKeywords: $
//===========================================================================//
#ifndef PSD_H
#define PSD_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h" //ImageFormat enum definition
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
struct Bitmap_t;
class PSDImageResources
{
public:
enum Resource {
eResFileInfo = 0x0404
};
struct ResElement {
Resource m_eType;
// unsigned char m_pReserved[4];
unsigned short m_numBytes;
unsigned char const *m_pvData;
};
public:
explicit PSDImageResources( unsigned int numBytes, unsigned char const *pvBuffer ) : m_numBytes( numBytes ), m_pvBuffer( pvBuffer ) {}
public:
ResElement FindElement( Resource eType ) const;
protected:
unsigned int m_numBytes;
unsigned char const * m_pvBuffer;
};
class PSDResFileInfo
{
public:
enum ResFileInfo {
eTitle = 0x05,
eAuthor = 0x50,
eAuthorTitle = 0x55,
eDescription = 0x78,
eDescriptionWriter = 0x7A,
eKeywords = 0x19,
eCopyrightNotice = 0x74
};
struct ResFileInfoElement {
ResFileInfo m_eType;
unsigned short m_numBytes;
unsigned char const *m_pvData;
};
public:
explicit PSDResFileInfo( PSDImageResources::ResElement res ) : m_res( res ) {}
public:
ResFileInfoElement FindElement( ResFileInfo eType ) const;
protected:
PSDImageResources::ResElement m_res;
};
//-----------------------------------------------------------------------------
// Is a file a PSD file?
//-----------------------------------------------------------------------------
bool IsPSDFile( const char *pFileName, const char *pPathID );
bool IsPSDFile( CUtlBuffer &buf );
//-----------------------------------------------------------------------------
// Returns information about the PSD file
//-----------------------------------------------------------------------------
bool PSDGetInfo( const char *pFileName, const char *pPathID, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma );
bool PSDGetInfo( CUtlBuffer &buf, int *pWidth, int *pHeight, ImageFormat *pImageFormat, float *pSourceGamma );
//-----------------------------------------------------------------------------
// Get PSD file image resources, pointers refer into the utlbuffer
//-----------------------------------------------------------------------------
PSDImageResources PSDGetImageResources( CUtlBuffer &buf );
//-----------------------------------------------------------------------------
// Reads the PSD file into the specified buffer
//-----------------------------------------------------------------------------
bool PSDReadFileRGBA8888( CUtlBuffer &buf, Bitmap_t &bitmap );
bool PSDReadFileRGBA8888( const char *pFileName, const char *pPathID, Bitmap_t &bitmap );
#endif // PSD_H

136
public/bitmap/psheet.h Normal file
View File

@ -0,0 +1,136 @@
//===== Copyright <20> 1996-2006, Valve Corporation, All rights reserved. ======//
//
// Purpose: sheet definitions for particles and other sprite functions
//
//===========================================================================//
#ifndef PSHEET_H
#define PSHEET_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlobjectreference.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "tier1/utlvector.h"
class CUtlBuffer;
// classes for keeping a dictionary of sheet files in memory. A sheet is a bunch of frames packewd
// within one texture. Each sheet has 1 or more frame sequences stored for it.
// for fast lookups to retrieve sequence data, we store the sequence information discretized into
// a fixed # of frames. If this discretenesss is a visual problem, you can lerp the blend values to get it
// perfect.
#define SEQUENCE_SAMPLE_COUNT 512
#define MAX_IMAGES_PER_FRAME_ON_DISK 4
#define MAX_IMAGES_PER_FRAME_IN_MEMORY 2
struct SequenceSampleTextureCoords_t
{
float m_fLeft_U0;
float m_fTop_V0;
float m_fRight_U0;
float m_fBottom_V0;
float m_fLeft_U1;
float m_fTop_V1;
float m_fRight_U1;
float m_fBottom_V1;
};
struct SheetSequenceSample_t
{
// coordinates of two rectangles (old and next frame coords)
SequenceSampleTextureCoords_t m_TextureCoordData[MAX_IMAGES_PER_FRAME_IN_MEMORY];
float m_fBlendFactor;
void CopyFirstFrameToOthers(void)
{
// for old format files only supporting one image per frame
for(int i=1; i < MAX_IMAGES_PER_FRAME_IN_MEMORY; i++)
{
m_TextureCoordData[i] = m_TextureCoordData[0];
}
}
};
enum SheetSequenceFlags_t
{
SEQ_FLAG_CLAMP = 0x1, // as opposed to loop
SEQ_FLAG_NO_ALPHA = 0x2, // packed as sequence-rgb (alpha channel should be ignored)
SEQ_FLAG_NO_COLOR = 0x4, // packed as sequence-a (color channels should be ignored)
};
class CSheet
{
public:
// read form a .sht file. This is the usual thing to do
CSheet( CUtlBuffer &buf );
CSheet( void );
~CSheet( void );
const SheetSequenceSample_t *GetSampleForSequence( float flAge, float flAgeScale, int nSequence, bool bForceLoop );
// references for smart ptrs
CUtlReferenceList<CSheet> m_References;
struct SheetInfo_t
{
SheetSequenceSample_t *m_pSamples;
uint8 m_SeqFlags;
bool m_bSequenceIsCopyOfAnotherSequence;
int16 m_nNumFrames;
float m_flFrameSpan;
};
CUtlVector< SheetInfo_t > m_SheetInfo;
};
//////////////////////////////////////////////////////////////////////////
class IMesh;
class IMaterial;
// A heavier-weight version of CSheet with more bells and whistles
class CSheetExtended
{
public:
explicit CSheetExtended( IMaterial* pMaterial );
~CSheetExtended();
int GetSheetSequenceCount();
int GetNthSequenceIndex( int nSequenceNumber );
const SheetSequenceSample_t *GetSampleForSequence( float flAge, float flAgeScale, int nSequence, bool bForceLoop );
float GetSequenceTimeSpan( int nSequenceIndex );
void DrawSheet( IMesh *pMesh, const Vector &vCenter, float flRadius, int nSheetSequence, float flAge, float flSheetPreviewSpeed, bool bLoopSheetPreview, int nSecondarySequence=-1, bool bOverrideSpriteCard=false );
bool ValidSheetData();
bool SequenceHasAlphaData( int nSequenceIndex );
bool SequenceHasColorData( int nSequenceIndex );
// Helper
static bool IsMaterialSeparateAlphaColorMaterial( IMaterial* pMat );
static bool IsMaterialDualSequence( IMaterial* pMat );
private:
void LoadFromBuffer( CUtlBuffer& buf );
void LoadFromMaterial( IMaterial* pMaterial );
// TEMP: Store in a CSheet for now - eventually we'll want more data
CSheet* m_pSheetData;
CMaterialReference m_Material;
};
#endif // PSHEET_H

624
public/bitmap/stb_dxt.h Normal file
View File

@ -0,0 +1,624 @@
// stb_dxt.h - v1.04 - DXT1/DXT5 compressor - public domain
// original by fabian "ryg" giesen - ported to C by stb
// use '#define STB_DXT_IMPLEMENTATION' before including to create the implementation
//
// USAGE:
// call stb_compress_dxt_block() for every block (you must pad)
// source should be a 4x4 block of RGBA data in row-major order;
// A is ignored if you specify alpha=0; you can turn on dithering
// and "high quality" using mode.
//
// version history:
// v1.04 - (ryg) default to no rounding bias for lerped colors (as per S3TC/DX10 spec);
// single color match fix (allow for inexact color interpolation);
// optimal DXT5 index finder; "high quality" mode that runs multiple refinement steps.
// v1.03 - (stb) endianness support
// v1.02 - (stb) fix alpha encoding bug
// v1.01 - (stb) fix bug converting to RGB that messed up quality, thanks ryg & cbloom
// v1.00 - (stb) first release
#ifndef STB_INCLUDE_STB_DXT_H
#define STB_INCLUDE_STB_DXT_H
// compression mode (bitflags)
#define STB_DXT_NORMAL 0
#define STB_DXT_DITHER 1 // use dithering. dubious win. never use for normal maps and the like!
#define STB_DXT_HIGHQUAL 2 // high quality mode, does two refinement steps instead of 1. ~30-40% slower.
void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode);
#define STB_COMPRESS_DXT_BLOCK
#ifdef STB_DXT_IMPLEMENTATION
// configuration options for DXT encoder. set them in the project/makefile or just define
// them at the top.
// STB_DXT_USE_ROUNDING_BIAS
// use a rounding bias during color interpolation. this is closer to what "ideal"
// interpolation would do but doesn't match the S3TC/DX10 spec. old versions (pre-1.03)
// implicitly had this turned on.
//
// in case you're targeting a specific type of hardware (e.g. console programmers):
// NVidia and Intel GPUs (as of 2010) as well as DX9 ref use DXT decoders that are closer
// to STB_DXT_USE_ROUNDING_BIAS. AMD/ATI, S3 and DX10 ref are closer to rounding with no bias.
// you also see "(a*5 + b*3) / 8" on some old GPU designs.
// #define STB_DXT_USE_ROUNDING_BIAS
#include <stdlib.h>
#include <math.h>
#include <string.h> // memset
static unsigned char stb__Expand5[32];
static unsigned char stb__Expand6[64];
static unsigned char stb__OMatch5[256][2];
static unsigned char stb__OMatch6[256][2];
static unsigned char stb__QuantRBTab[256+16];
static unsigned char stb__QuantGTab[256+16];
static int stb__Mul8Bit(int a, int b)
{
int t = a*b + 128;
return (t + (t >> 8)) >> 8;
}
static void stb__From16Bit(unsigned char *out, unsigned short v)
{
int rv = (v & 0xf800) >> 11;
int gv = (v & 0x07e0) >> 5;
int bv = (v & 0x001f) >> 0;
out[0] = stb__Expand5[rv];
out[1] = stb__Expand6[gv];
out[2] = stb__Expand5[bv];
out[3] = 0;
}
static unsigned short stb__As16Bit(int r, int g, int b)
{
return (stb__Mul8Bit(r,31) << 11) + (stb__Mul8Bit(g,63) << 5) + stb__Mul8Bit(b,31);
}
// linear interpolation at 1/3 point between a and b, using desired rounding type
static int stb__Lerp13(int a, int b)
{
#ifdef STB_DXT_USE_ROUNDING_BIAS
// with rounding bias
return a + stb__Mul8Bit(b-a, 0x55);
#else
// without rounding bias
// replace "/ 3" by "* 0xaaab) >> 17" if your compiler sucks or you really need every ounce of speed.
return (2*a + b) / 3;
#endif
}
// lerp RGB color
static void stb__Lerp13RGB(unsigned char *out, unsigned char *p1, unsigned char *p2)
{
out[0] = stb__Lerp13(p1[0], p2[0]);
out[1] = stb__Lerp13(p1[1], p2[1]);
out[2] = stb__Lerp13(p1[2], p2[2]);
}
/****************************************************************************/
// compute table to reproduce constant colors as accurately as possible
static void stb__PrepareOptTable(unsigned char *Table,const unsigned char *expand,int size)
{
int i,mn,mx;
for (i=0;i<256;i++) {
int bestErr = 256;
for (mn=0;mn<size;mn++) {
for (mx=0;mx<size;mx++) {
int mine = expand[mn];
int maxe = expand[mx];
int err = abs(stb__Lerp13(maxe, mine) - i);
// DX10 spec says that interpolation must be within 3% of "correct" result,
// add this as error term. (normally we'd expect a random distribution of
// +-1.5% error, but nowhere in the spec does it say that the error has to be
// unbiased - better safe than sorry).
err += abs(maxe - mine) * 3 / 100;
if(err < bestErr)
{
Table[i*2+0] = mx;
Table[i*2+1] = mn;
bestErr = err;
}
}
}
}
}
static void stb__EvalColors(unsigned char *color,unsigned short c0,unsigned short c1)
{
stb__From16Bit(color+ 0, c0);
stb__From16Bit(color+ 4, c1);
stb__Lerp13RGB(color+ 8, color+0, color+4);
stb__Lerp13RGB(color+12, color+4, color+0);
}
// Block dithering function. Simply dithers a block to 565 RGB.
// (Floyd-Steinberg)
static void stb__DitherBlock(unsigned char *dest, unsigned char *block)
{
int err[8],*ep1 = err,*ep2 = err+4, *et;
int ch,y;
// process channels seperately
for (ch=0; ch<3; ++ch) {
unsigned char *bp = block+ch, *dp = dest+ch;
unsigned char *quant = (ch == 1) ? stb__QuantGTab+8 : stb__QuantRBTab+8;
memset(err, 0, sizeof(err));
for(y=0; y<4; ++y) {
dp[ 0] = quant[bp[ 0] + ((3*ep2[1] + 5*ep2[0]) >> 4)];
ep1[0] = bp[ 0] - dp[ 0];
dp[ 4] = quant[bp[ 4] + ((7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]) >> 4)];
ep1[1] = bp[ 4] - dp[ 4];
dp[ 8] = quant[bp[ 8] + ((7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]) >> 4)];
ep1[2] = bp[ 8] - dp[ 8];
dp[12] = quant[bp[12] + ((7*ep1[2] + 5*ep2[3] + ep2[2]) >> 4)];
ep1[3] = bp[12] - dp[12];
bp += 16;
dp += 16;
et = ep1, ep1 = ep2, ep2 = et; // swap
}
}
}
// The color matching function
static unsigned int stb__MatchColorsBlock(unsigned char *block, unsigned char *color,int dither)
{
unsigned int mask = 0;
int dirr = color[0*4+0] - color[1*4+0];
int dirg = color[0*4+1] - color[1*4+1];
int dirb = color[0*4+2] - color[1*4+2];
int dots[16];
int stops[4];
int i;
int c0Point, halfPoint, c3Point;
for(i=0;i<16;i++)
dots[i] = block[i*4+0]*dirr + block[i*4+1]*dirg + block[i*4+2]*dirb;
for(i=0;i<4;i++)
stops[i] = color[i*4+0]*dirr + color[i*4+1]*dirg + color[i*4+2]*dirb;
// think of the colors as arranged on a line; project point onto that line, then choose
// next color out of available ones. we compute the crossover points for "best color in top
// half"/"best in bottom half" and then the same inside that subinterval.
//
// relying on this 1d approximation isn't always optimal in terms of euclidean distance,
// but it's very close and a lot faster.
// http://cbloomrants.blogspot.com/2008/12/12-08-08-dxtc-summary.html
c0Point = (stops[1] + stops[3]) >> 1;
halfPoint = (stops[3] + stops[2]) >> 1;
c3Point = (stops[2] + stops[0]) >> 1;
if(!dither) {
// the version without dithering is straightforward
for (i=15;i>=0;i--) {
int dot = dots[i];
mask <<= 2;
if(dot < halfPoint)
mask |= (dot < c0Point) ? 1 : 3;
else
mask |= (dot < c3Point) ? 2 : 0;
}
} else {
// with floyd-steinberg dithering
int err[8],*ep1 = err,*ep2 = err+4;
int *dp = dots, y;
c0Point <<= 4;
halfPoint <<= 4;
c3Point <<= 4;
for(i=0;i<8;i++)
err[i] = 0;
for(y=0;y<4;y++)
{
int dot,lmask,step;
dot = (dp[0] << 4) + (3*ep2[1] + 5*ep2[0]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[0] = dp[0] - stops[step];
lmask = step;
dot = (dp[1] << 4) + (7*ep1[0] + 3*ep2[2] + 5*ep2[1] + ep2[0]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[1] = dp[1] - stops[step];
lmask |= step<<2;
dot = (dp[2] << 4) + (7*ep1[1] + 3*ep2[3] + 5*ep2[2] + ep2[1]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[2] = dp[2] - stops[step];
lmask |= step<<4;
dot = (dp[3] << 4) + (7*ep1[2] + 5*ep2[3] + ep2[2]);
if(dot < halfPoint)
step = (dot < c0Point) ? 1 : 3;
else
step = (dot < c3Point) ? 2 : 0;
ep1[3] = dp[3] - stops[step];
lmask |= step<<6;
dp += 4;
mask |= lmask << (y*8);
{ int *et = ep1; ep1 = ep2; ep2 = et; } // swap
}
}
return mask;
}
// The color optimization function. (Clever code, part 1)
static void stb__OptimizeColorsBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16)
{
int mind = 0x7fffffff,maxd = -0x7fffffff;
unsigned char *minp, *maxp;
double magn;
int v_r,v_g,v_b;
static const int nIterPower = 4;
float covf[6],vfr,vfg,vfb;
// determine color distribution
int cov[6];
int mu[3],min[3],max[3];
int ch,i,iter;
for(ch=0;ch<3;ch++)
{
const unsigned char *bp = ((const unsigned char *) block) + ch;
int muv,minv,maxv;
muv = minv = maxv = bp[0];
for(i=4;i<64;i+=4)
{
muv += bp[i];
if (bp[i] < minv) minv = bp[i];
else if (bp[i] > maxv) maxv = bp[i];
}
mu[ch] = (muv + 8) >> 4;
min[ch] = minv;
max[ch] = maxv;
}
// determine covariance matrix
for (i=0;i<6;i++)
cov[i] = 0;
for (i=0;i<16;i++)
{
int r = block[i*4+0] - mu[0];
int g = block[i*4+1] - mu[1];
int b = block[i*4+2] - mu[2];
cov[0] += r*r;
cov[1] += r*g;
cov[2] += r*b;
cov[3] += g*g;
cov[4] += g*b;
cov[5] += b*b;
}
// convert covariance matrix to float, find principal axis via power iter
for(i=0;i<6;i++)
covf[i] = cov[i] / 255.0f;
vfr = (float) (max[0] - min[0]);
vfg = (float) (max[1] - min[1]);
vfb = (float) (max[2] - min[2]);
for(iter=0;iter<nIterPower;iter++)
{
float r = vfr*covf[0] + vfg*covf[1] + vfb*covf[2];
float g = vfr*covf[1] + vfg*covf[3] + vfb*covf[4];
float b = vfr*covf[2] + vfg*covf[4] + vfb*covf[5];
vfr = r;
vfg = g;
vfb = b;
}
magn = fabs(vfr);
if (fabs(vfg) > magn) magn = fabs(vfg);
if (fabs(vfb) > magn) magn = fabs(vfb);
if(magn < 4.0f) { // too small, default to luminance
v_r = 299; // JPEG YCbCr luma coefs, scaled by 1000.
v_g = 587;
v_b = 114;
} else {
magn = 512.0 / magn;
v_r = (int) (vfr * magn);
v_g = (int) (vfg * magn);
v_b = (int) (vfb * magn);
}
// Pick colors at extreme points
for(i=0;i<16;i++)
{
int dot = block[i*4+0]*v_r + block[i*4+1]*v_g + block[i*4+2]*v_b;
if (dot < mind) {
mind = dot;
minp = block+i*4;
}
if (dot > maxd) {
maxd = dot;
maxp = block+i*4;
}
}
*pmax16 = stb__As16Bit(maxp[0],maxp[1],maxp[2]);
*pmin16 = stb__As16Bit(minp[0],minp[1],minp[2]);
}
static int stb__sclamp(float y, int p0, int p1)
{
int x = (int) y;
if (x < p0) return p0;
if (x > p1) return p1;
return x;
}
// The refinement function. (Clever code, part 2)
// Tries to optimize colors to suit block contents better.
// (By solving a least squares system via normal equations+Cramer's rule)
static int stb__RefineBlock(unsigned char *block, unsigned short *pmax16, unsigned short *pmin16, unsigned int mask)
{
static const int w1Tab[4] = { 3,0,2,1 };
static const int prods[4] = { 0x090000,0x000900,0x040102,0x010402 };
// ^some magic to save a lot of multiplies in the accumulating loop...
// (precomputed products of weights for least squares system, accumulated inside one 32-bit register)
float frb,fg;
unsigned short oldMin, oldMax, min16, max16;
int i, akku = 0, xx,xy,yy;
int At1_r,At1_g,At1_b;
int At2_r,At2_g,At2_b;
unsigned int cm = mask;
oldMin = *pmin16;
oldMax = *pmax16;
if((mask ^ (mask<<2)) < 4) // all pixels have the same index?
{
// yes, linear system would be singular; solve using optimal
// single-color match on average color
int r = 8, g = 8, b = 8;
for (i=0;i<16;++i) {
r += block[i*4+0];
g += block[i*4+1];
b += block[i*4+2];
}
r >>= 4; g >>= 4; b >>= 4;
max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
} else {
At1_r = At1_g = At1_b = 0;
At2_r = At2_g = At2_b = 0;
for (i=0;i<16;++i,cm>>=2) {
int step = cm&3;
int w1 = w1Tab[step];
int r = block[i*4+0];
int g = block[i*4+1];
int b = block[i*4+2];
akku += prods[step];
At1_r += w1*r;
At1_g += w1*g;
At1_b += w1*b;
At2_r += r;
At2_g += g;
At2_b += b;
}
At2_r = 3*At2_r - At1_r;
At2_g = 3*At2_g - At1_g;
At2_b = 3*At2_b - At1_b;
// extract solutions and decide solvability
xx = akku >> 16;
yy = (akku >> 8) & 0xff;
xy = (akku >> 0) & 0xff;
frb = 3.0f * 31.0f / 255.0f / (xx*yy - xy*xy);
fg = frb * 63.0f / 31.0f;
// solve.
max16 = stb__sclamp((At1_r*yy - At2_r*xy)*frb+0.5f,0,31) << 11;
max16 |= stb__sclamp((At1_g*yy - At2_g*xy)*fg +0.5f,0,63) << 5;
max16 |= stb__sclamp((At1_b*yy - At2_b*xy)*frb+0.5f,0,31) << 0;
min16 = stb__sclamp((At2_r*xx - At1_r*xy)*frb+0.5f,0,31) << 11;
min16 |= stb__sclamp((At2_g*xx - At1_g*xy)*fg +0.5f,0,63) << 5;
min16 |= stb__sclamp((At2_b*xx - At1_b*xy)*frb+0.5f,0,31) << 0;
}
*pmin16 = min16;
*pmax16 = max16;
return oldMin != min16 || oldMax != max16;
}
// Color block compression
static void stb__CompressColorBlock(unsigned char *dest, unsigned char *block, int mode)
{
unsigned int mask;
int i;
int dither;
int refinecount;
unsigned short max16, min16;
unsigned char dblock[16*4],color[4*4];
dither = mode & STB_DXT_DITHER;
refinecount = (mode & STB_DXT_HIGHQUAL) ? 2 : 1;
// check if block is constant
for (i=1;i<16;i++)
if (((unsigned int *) block)[i] != ((unsigned int *) block)[0])
break;
if(i == 16) { // constant color
int r = block[0], g = block[1], b = block[2];
mask = 0xaaaaaaaa;
max16 = (stb__OMatch5[r][0]<<11) | (stb__OMatch6[g][0]<<5) | stb__OMatch5[b][0];
min16 = (stb__OMatch5[r][1]<<11) | (stb__OMatch6[g][1]<<5) | stb__OMatch5[b][1];
} else {
// first step: compute dithered version for PCA if desired
if(dither)
stb__DitherBlock(dblock,block);
// second step: pca+map along principal axis
stb__OptimizeColorsBlock(dither ? dblock : block,&max16,&min16);
if (max16 != min16) {
stb__EvalColors(color,max16,min16);
mask = stb__MatchColorsBlock(block,color,dither);
} else
mask = 0;
// third step: refine (multiple times if requested)
for (i=0;i<refinecount;i++) {
unsigned int lastmask = mask;
if (stb__RefineBlock(dither ? dblock : block,&max16,&min16,mask)) {
if (max16 != min16) {
stb__EvalColors(color,max16,min16);
mask = stb__MatchColorsBlock(block,color,dither);
} else {
mask = 0;
break;
}
}
if(mask == lastmask)
break;
}
}
// write the color block
if(max16 < min16)
{
unsigned short t = min16;
min16 = max16;
max16 = t;
mask ^= 0x55555555;
}
dest[0] = (unsigned char) (max16);
dest[1] = (unsigned char) (max16 >> 8);
dest[2] = (unsigned char) (min16);
dest[3] = (unsigned char) (min16 >> 8);
dest[4] = (unsigned char) (mask);
dest[5] = (unsigned char) (mask >> 8);
dest[6] = (unsigned char) (mask >> 16);
dest[7] = (unsigned char) (mask >> 24);
}
// Alpha block compression (this is easy for a change)
static void stb__CompressAlphaBlock(unsigned char *dest,unsigned char *src,int mode)
{
int i,dist,bias,dist4,dist2,bits,mask;
// find min/max color
int mn,mx;
mn = mx = src[3];
for (i=1;i<16;i++)
{
if (src[i*4+3] < mn) mn = src[i*4+3];
else if (src[i*4+3] > mx) mx = src[i*4+3];
}
// encode them
((unsigned char *)dest)[0] = mx;
((unsigned char *)dest)[1] = mn;
dest += 2;
// determine bias and emit color indices
// given the choice of mx/mn, these indices are optimal:
// http://fgiesen.wordpress.com/2009/12/15/dxt5-alpha-block-index-determination/
dist = mx-mn;
dist4 = dist*4;
dist2 = dist*2;
bias = (dist < 8) ? (dist - 1) : (dist/2 + 2);
bias -= mn * 7;
bits = 0,mask=0;
for (i=0;i<16;i++) {
int a = src[i*4+3]*7 + bias;
int ind,t;
// select index. this is a "linear scale" lerp factor between 0 (val=min) and 7 (val=max).
t = (a >= dist4) ? -1 : 0; ind = t & 4; a -= dist4 & t;
t = (a >= dist2) ? -1 : 0; ind += t & 2; a -= dist2 & t;
ind += (a >= dist);
// turn linear scale into DXT index (0/1 are extremal pts)
ind = -ind & 7;
ind ^= (2 > ind);
// write index
mask |= ind << bits;
if((bits += 3) >= 8) {
*dest++ = mask;
mask >>= 8;
bits -= 8;
}
}
}
static void stb__InitDXT()
{
int i;
for(i=0;i<32;i++)
stb__Expand5[i] = (i<<3)|(i>>2);
for(i=0;i<64;i++)
stb__Expand6[i] = (i<<2)|(i>>4);
for(i=0;i<256+16;i++)
{
int v = i-8 < 0 ? 0 : i-8 > 255 ? 255 : i-8;
stb__QuantRBTab[i] = stb__Expand5[stb__Mul8Bit(v,31)];
stb__QuantGTab[i] = stb__Expand6[stb__Mul8Bit(v,63)];
}
stb__PrepareOptTable(&stb__OMatch5[0][0],stb__Expand5,32);
stb__PrepareOptTable(&stb__OMatch6[0][0],stb__Expand6,64);
}
void stb_compress_dxt_block(unsigned char *dest, const unsigned char *src, int alpha, int mode)
{
static int init=1;
if (init) {
stb__InitDXT();
init=0;
}
if (alpha) {
stb__CompressAlphaBlock(dest,(unsigned char*) src,mode);
dest += 8;
}
stb__CompressColorBlock(dest,(unsigned char*) src,mode);
}
#endif // STB_DXT_IMPLEMENTATION
#endif // STB_INCLUDE_STB_DXT_H

5099
public/bitmap/stb_image.c Normal file

File diff suppressed because it is too large Load Diff

80
public/bitmap/stb_image.h Normal file
View File

@ -0,0 +1,80 @@
/* stbi-1.29 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
when you control the images you're loading
no warranty implied; use at your own risk
QUICK NOTES:
Primarily of interest to game developers and other people who can
avoid problematic images and only need the trivial interface
JPEG baseline (no JPEG progressive)
PNG 8-bit only
TGA (not sure what subset, if a subset)
BMP non-1bpp, non-RLE
PSD (composited view only, no extra channels)
GIF (*comp always reports as 4-channel)
HDR (radiance rgbE format)
PIC (Softimage PIC)
- decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
- supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
Latest revisions:
1.29 (2010-08-16) various warning fixes from Aurelien Pocheville
1.28 (2010-08-01) fix bug in GIF palette transparency (SpartanJ)
1.27 (2010-08-01) cast-to-uint8 to fix warnings (Laurent Gomila)
allow trailing 0s at end of image data (Laurent Gomila)
1.26 (2010-07-24) fix bug in file buffering for PNG reported by SpartanJ
1.25 (2010-07-17) refix trans_data warning (Won Chun)
1.24 (2010-07-12) perf improvements reading from files
minor perf improvements for jpeg
deprecated type-specific functions in hope of feedback
attempt to fix trans_data warning (Won Chun)
1.23 fixed bug in iPhone support
1.22 (2010-07-10) removed image *writing* support to stb_image_write.h
stbi_info support from Jetro Lauha
GIF support from Jean-Marc Lienher
iPhone PNG-extensions from James Brown
warning-fixes from Nicolas Schulz and Janez Zemva
1.21 fix use of 'uint8' in header (reported by jon blow)
1.20 added support for Softimage PIC, by Tom Seddon
See end of file for full revision history.
TODO:
stbi_info support for BMP,PSD,HDR,PIC
rewrite stbi_info and load_file variations to share file handling code
(current system allows individual functions to be called directly,
since each does all the work, but I doubt anyone uses this in practice)
============================ Contributors =========================
Image formats Optimizations & bugfixes
Sean Barrett (jpeg, png, bmp) Fabian "ryg" Giesen
Nicolas Schulz (hdr, psd)
Jonathan Dummer (tga) Bug fixes & warning fixes
Jean-Marc Lienher (gif) Marc LeBlanc
Tom Seddon (pic) Christpher Lloyd
Thatcher Ulrich (psd) Dave Moore
Won Chun
the Horde3D community
Extensions, features Janez Zemva
Jetro Lauha (stbi_info) Jonathan Blow
James "moose2000" Brown (iPhone PNG) Laurent Gomila
Aruelien Pocheville
If your name should be here but isn't, let Sean know.
*/
#ifndef STBI_INCLUDE_STB_IMAGE_H
#define STBI_INCLUDE_STB_IMAGE_H
// To get a header file for this, either cut and paste the header,
// or create stb_image.h, #define STBI_HEADER_FILE_ONLY, and
// then include stb_image.c from it.
#define STBI_HEADER_FILE_ONLY
#include "stb_image.c"

View File

@ -0,0 +1,72 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TEXTUREPACKER_H
#define TEXTUREPACKER_H
#ifdef _WIN32
#pragma once
#endif
#include "utlntree.h"
#define DEFAULT_TEXTURE_PAGE_WIDTH 1024
#define DEFAULT_TEXTURE_PAGE_WIDTH 1024
//-----------------------------------------------------------------------------
// Purpose: manages texture packing of textures as they are added.
//-----------------------------------------------------------------------------
class CTexturePacker
{
public:
struct TreeEntry_t
{
Rect_t rc;
bool bInUse;
};
CTexturePacker( int texWidth = DEFAULT_TEXTURE_PAGE_WIDTH, int texHeight = DEFAULT_TEXTURE_PAGE_WIDTH, int pixelGap = 0 );
~CTexturePacker();
// Use -1 if you want to insert at the root.
int InsertRect( const Rect_t& texRect, int nodeIndex = -1 );
bool RemoveRect( int nodeIndex );
const TreeEntry_t &GetEntry( int i )
{
return m_Tree[i];
}
int GetPageWidth()
{
return m_PageWidth;
}
int GetPageHeight()
{
return m_PageHeight;
}
// clears the tree
void Clear();
private:
bool IsLeaf( int nodeIndex );
bool IsLeftChild( int nodeIndexParent, int nodeIndexChild );
bool IsRightChild( int nodeIndexParent, int nodeIndexChild );
// Pixel gap between textures.
int m_PixelGap;
int m_PageWidth;
int m_PageHeight;
CUtlNTree< TreeEntry_t > m_Tree;
};
#endif // TEXTUREPACKER_H

45
public/bitmap/tgaloader.h Normal file
View File

@ -0,0 +1,45 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//===========================================================================//
#ifndef TGALOADER_H
#define TGALOADER_H
#ifdef _WIN32
#pragma once
#endif
#include "bitmap/imageformat.h"
#include "tier1/utlmemory.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class CUtlBuffer;
namespace TGALoader
{
int TGAHeaderSize();
bool GetInfo( const char *fileName, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma );
bool GetInfo( CUtlBuffer &buf, int *width, int *height, ImageFormat *imageFormat, float *sourceGamma );
bool Load( unsigned char *imageData, const char *fileName, int width, int height,
ImageFormat imageFormat, float targetGamma, bool mipmap );
bool Load( unsigned char *imageData, CUtlBuffer &buf, int width, int height,
ImageFormat imageFormat, float targetGamma, bool mipmap );
bool LoadRGBA8888( const char *pFileName, CUtlMemory<unsigned char> &outputData, int &outWidth, int &outHeight );
bool LoadRGBA8888( CUtlBuffer &buf, CUtlMemory<unsigned char> &outputData, int &outWidth, int &outHeight );
} // end namespace TGALoader
#endif // TGALOADER_H

35
public/bitmap/tgawriter.h Normal file
View File

@ -0,0 +1,35 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef TGAWRITER_H
#define TGAWRITER_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
#include "bitmap/imageformat.h" //ImageFormat enum definition
class CUtlBuffer;
namespace TGAWriter
{
bool WriteToBuffer( unsigned char *pImageData, CUtlBuffer &buffer, int width, int height, ImageFormat srcFormat, ImageFormat dstFormat );
// Write out a simple tga file from a memory buffer.
bool WriteTGAFile( const char *fileName, int width, int height, enum ImageFormat srcFormat, uint8 const *srcData, int nStride );
// Routines for writing to files without allocating any memory in the TGA writer
// Useful for very large files such as posters, which are rendered as sub-rects
bool WriteDummyFileNoAlloc( const char *fileName, int width, int height, ImageFormat dstFormat );
bool WriteRectNoAlloc( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nStride, ImageFormat srcFormat );
bool WriteRectNoAllocFeather( unsigned char *pImageData, const char *fileName, int nXOrigin, int nYOrigin, int width, int height, int nGuardBandWidth, int nGuardBandHeight, int nStride, enum ImageFormat srcFormat );
} // end namespace TGAWriter
#endif // TGAWRITER_H