|
|
#include <stdio.h>
: R$ T' z7 l3 y. @7 _4 t$ f0 y#include <stdlib.h># q$ G3 K" l* T2 T! D3 g
#include <string.h>8 G5 o/ o2 k& m
#include <windows.h>: m: [: u; X$ @! H) W
#include <GL/gl.h>$ D0 a7 i e7 M; l
, i& I& {; x3 \$ H- L' W
class tgaImageFile, v6 {9 k6 @' e2 B! p1 ?' r2 }' Q- @
{
1 q3 \8 B2 [$ C9 I" @public:2 i: a+ e) A3 Q" I" f
, b/ c: S% ~' \: p3 S, C x4 d+ ltgaImageFile(void) :
4 L) `4 g' c8 u" z8 Q% |m_texFormat(-1),
8 q8 L4 e4 [$ a+ nm_nImageWidth(0),; l/ o, M; A7 f/ d
m_nImageHeight(0),' n2 t5 L7 k: i! n+ G1 k! r
m_nImageBits(0),( X, w# J# _3 Q7 @
m_nImageData(NULL) {}( }; j z; u: P4 p3 b
1 O4 F2 @$ K# |. Z3 o4 U/ C& m
~tgaImageFile(void);
$ M6 N) B9 E5 ?
) H5 |1 e g0 t! U2 C) G5 [enum TGALoadError" a5 G, f" W6 @" z2 K$ N- L
{8 J# N P! O2 r Y7 N7 t) O6 F
TGA_NO_ERROR = 1, // No error8 x6 w( N! P" W4 H
TGA_FILE_NOT_FOUND, // File was not found ' P8 q& {- s# X/ L" t5 B
TGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed& m' q: V5 g0 j) O! s" B3 E7 ?
TGA_BAD_DIMENSION, // Dimension is not a power of 2 . O& _1 T7 O1 v3 r& d- u
TGA_BAD_BITS, // Image bits is not 8, 24 or 32
7 ~0 l7 m5 t' `- ^- p: dTGA_BAD_DATA // Image data could not be loaded
5 g+ |3 K0 v* }$ L% e };
8 Z4 x( C; y/ s) m! t
5 x! g: e% k5 t& `: ?3 t2 j$ H1 YtgaImageFile::TGALoadError load( char *name );
/ b; i( I4 X& f' G2 [2 Q* [1 ~
Z7 a9 @3 d( t1 H) ~7 D! `GLenum m_texFormat;
+ _/ H1 C# o) ]/ Z; m! }' B! ?int m_nImageWidth;/ r4 z' ^; W& x
int m_nImageHeight;7 b8 K9 X* ? n/ N8 e. t
int m_nImageBits;6 O# y( }3 k% X6 \5 u' L) ?+ L
unsigned char * m_nImageData;% o3 C: p8 O8 a- a# [
0 a6 g u% z9 W- G: l
private:/ Q3 j7 {7 \$ @7 e! ?8 p. w- `: t
2 @. Q9 h* n5 ^! N; Q. ^0 ?, D" i
bool checkSize(int x);
0 ?+ G) p1 ]) f0 N+ iint returnError(FILE *s, int error);9 g" ^$ E7 x" l0 {
unsigned char *getRGBA(FILE *s, int size);
! G4 E8 B2 Y; W5 ^) Uunsigned char *getRGB(FILE *s, int size);6 _7 t m" t7 @/ F& l, u. X5 \
unsigned char *getGray(FILE *s, int size);
, D$ @) F! f2 f7 [};2 u+ G' c# s7 k: H& h
* T# z* E$ _) P1 V% W; u0 CtgaImageFile::~tgaImageFile( void )* R& p8 q! g1 ^% B8 s
{
! n* V' }; N' u% v% T* G9 E: wif( m_nImageData != NULL )/ s( j# H$ g4 _8 W0 g# q
{& a& Z& ?) l& B/ E, }" n
free( m_nImageData ); x$ k5 u S; P4 A( O. J
m_nImageData = NULL;
: ?0 ~( f! m7 s: B. S. j}
( B g E$ z$ R! r1 d' e}
0 m' r+ M% X, p9 H/ Z2 F' H- E
+ G* A! G/ t0 j' |9 e9 e4 }+ Sbool tgaImageFile::checkSize( int x )2 N0 s' P8 E# r& o% N+ b+ ~
{4 f$ w; s, q. y& Q# q
// Make sure its a power of 2.4 |) }) a( y7 ]. j0 T* U. c! ?
if( x == 2 || x == 4 || . x% s. k- E$ y3 |1 n6 u$ c; _* P
x == 8 || x == 16 ||
$ b8 D* A2 T* z I/ E: l& Wx == 32 || x == 64 ||+ ? X5 j9 x& F$ k
x == 128 || x == 256 ||
( `5 [5 Q1 F K- ~$ Px == 512 )
& w( l! H O H8 W9 c+ ^3 m+ |6 hreturn true;# E; v) ~4 V' y; a: X
4 Q$ \# V, j; _0 }8 Q2 \
return false;$ L. ~6 j* M! ?' m' R- m; g
}
% v# j6 l8 `5 [. g# v& o0 e; m2 U& ~* X5 v1 G
int tgaImageFile::returnError( FILE *s, int error )
4 P) r, K; ]+ }( g& ]; p{
8 }0 d% E4 v% c// Called when there is an error loading the .tga texture file.
7 i4 e& N. x+ X, W0 nfclose( s );7 ~+ O9 M1 j5 s
return error;
+ \3 _- A. h1 p" P/ s} H# a5 g) d" Z) X4 F5 Z+ U
w; G; V; Z8 a, Gunsigned char *tgaImageFile::getRGBA( FILE *s, int size )$ F; y9 g% [- N& O% _
{2 d# B9 D& \( u* ~
// Read in RGBA data for a 32bit image. 9 l9 x8 h2 L! y$ |) h8 Q1 P3 W
unsigned char *rgba;' ^9 N& _; B( F! [5 }) s ]
unsigned char temp;$ e: I1 `+ ~5 P( X: O
int bread;* m" @. o8 K) T+ j; l2 r
int i;" [1 I) d# Y8 _2 i3 u
2 n; O- u! x4 v5 S+ xrgba = (unsigned char *)malloc( size * 4 );
$ p9 B% w8 F' V4 j7 v& l* d7 B& e" q/ O' K/ C
if( rgba == NULL )+ d0 G2 }7 X/ B0 Z# T
return 0;# F; N' X, b. x3 i2 w' G
8 s3 {: W( E% h/ I! ~
bread = fread( rgba, sizeof (unsigned char), size * 4, s ); - K% W& k& X5 f5 ^( p8 P' z1 ~
2 r, |7 P! r) l1 N( b# v* m// TGA is stored in BGRA, make it RGBA
: |) Q+ O5 \+ r3 yif( bread != size * 4 )( x- ?( l' `' q0 i# f2 a$ n/ b
{
+ U( j/ }2 O. H% N7 ~) E# rfree( rgba );% Y; H+ @* P: D7 P
return 0;3 [" y% M) z. p* Q/ k4 K5 |
}- J5 g- [( I( F( s% K) P- {7 ~4 w
" ~4 R- ^8 s* g8 {
for( i = 0; i < size * 4; i += 4 )
6 P+ g; Q$ j1 O{, B. H( o+ ^9 t
temp = rgba[i];& O8 ]* m" k7 \* v3 n9 \
rgba[i] = rgba[i + 2];; Z3 u0 f, p# J& @
rgba[i + 2] = temp; E+ E; Y; B/ c
}' D9 ?- c3 {: ?2 `
2 t' E4 b3 I" D+ B" D
m_texFormat = GL_RGBA;8 l2 p4 N9 v. ?# ~. K
return rgba;% w+ C+ u6 n/ [& m
}
2 Q% H* h! d0 ~& {0 z6 S2 T' x& ]# y0 U/ X
unsigned char *tgaImageFile::getRGB( FILE *s, int size )
. `" q# ~, m& d1 l' j/ O# L{+ L% R" c2 V; ?; n$ B
// Read in RGB data for a 24bit image.
3 y% ]0 X7 m2 }# bunsigned char *rgb;( S6 R* C/ Q% o1 O% e- b! w: ~
unsigned char temp;) G* C- ?* y2 O) M
int bread;
! q2 d3 t9 H L1 C; D& [, Wint i;4 R% u% m9 I% a5 u: |" E+ U
- y q% R/ Y8 V. A' y# h+ U" e, C# g: Rrgb = (unsigned char*)malloc( size * 3 );6 Y0 }0 m8 k: @( o7 y' A
4 @* G5 B) ~( x/ s2 H9 e. _. c. R
if( rgb == NULL )0 W. n# j8 b7 V- W
return 0;
# u- t) f/ q ~7 R% o
4 u* j' r) {9 }3 m% ]bread = fread( rgb, sizeof (unsigned char), size * 3, s );
$ \) W$ R5 n$ r3 M/ J, T6 Z: W' m
" r$ ]; y# g _$ `if(bread != size * 3)
( {. r0 g% D6 \{; x; N( b1 k$ l7 ]+ d& w, `
free( rgb );" K4 T- V- z( [/ X
return 0;
3 m" p4 ?8 \/ j& W5 W! t}$ U V4 X0 \, K$ T: G
9 z8 w* |' Z- N
// TGA is stored in BGR, make it RGB
r6 _5 q9 e* c6 T* Afor( i = 0; i < size * 3; i += 3 )
2 q; o7 c1 i4 [* a{
9 M! L) K0 I& s$ Ttemp = rgb[i];: T# L) u2 e6 N& G* h
rgb[i] = rgb[i + 2];+ ~9 g c% ~% Z! M s. ^3 o* l0 e( e
rgb[i + 2] = temp;
+ r+ Q' o" b, q# o& H: \1 I5 N}
* V- @9 V' X6 |4 o3 k$ J; @; _6 P0 E7 P! z; q+ n/ P' S
m_texFormat = GL_RGB;) I+ `# S+ x, m3 w- c
( i. r$ b) f4 P. w2 {' ~
return rgb;% E- u/ e3 b* x5 @0 g' l
}! O P, b: M, E7 A
4 I: U% g9 F) W5 Q( sunsigned char *tgaImageFile::getGray( FILE *s, int size )8 F3 W1 L6 `+ e% x, U% d/ o6 c
{
6 N; h# x7 K8 O) J! L7 g1 j// Gets the grayscale image data. Used as an alpha channel.5 `9 C2 C5 e3 s/ z& B. k( H6 j
unsigned char *grayData;9 o$ y5 X. u6 ]$ A4 d! \
int bread;
* z! C0 ~# h. u7 p3 v2 o
8 Y* Q# Y( P B0 H | ggrayData = (unsigned char*)malloc( size );3 s, W! X" W* S0 ~ f: L9 A
7 K! v* P% j L0 X& l
if( grayData == NULL )) P6 s6 I% [0 x& V9 {2 _
return 0;+ t- I% J& S' f- C
3 r; \8 D( l0 B2 h- l$ Y6 Cbread = fread( grayData, sizeof (unsigned char), size, s );; W" Y9 e Y% y: L7 J! n, ?* _# m
4 u [. }7 y4 ?3 i4 e
if( bread != size )
+ K, S6 q i! _8 q$ p: |{
$ |; P9 ]/ r: @0 Nfree( grayData );4 T: r% t n/ u4 _5 F. k! a
return 0;2 C3 L1 a* Q d0 z
}( X8 W1 K$ X6 g1 I, u' f* K$ M4 E
0 B2 E" \( `2 V% g& ]- W' [
m_texFormat = GL_ALPHA;
j5 O6 Q& k+ k, v6 D: A7 K# z
% L& r. x0 D6 Q3 v4 breturn grayData;
3 ~' K7 y: O1 K( P8 h$ |}1 t4 y& s& x: }* R. f0 m
6 K# \9 n* Q1 R5 o: Y
tgaImageFile::TGALoadError tgaImageFile::load( char *name )( V8 s7 c0 c. m9 l2 B% J$ u
{
( O" F* E: q* L0 g1 B// Loads up a targa file. Supported types are 8, 24 and 32
, g- K0 W9 p0 |0 Z// uncompressed images.
1 c7 D( R0 \, c* Gunsigned char type[4];
. s& H! H! S {* S# hunsigned char info[7];+ [, U9 k$ t' ^ n/ V6 ]- Q3 |
FILE *s = NULL;
" n7 |7 T4 J; z4 l* \int size = 0;
, S) O. S, d! {" j a6 J7 ] l, a
" F. Z! G3 |1 V( ^5 L' ]if( !(s = fopen( name, "rb" )) )- v1 L: r# \. G% C( a
return TGA_FILE_NOT_FOUND;
+ }* G# L+ O1 L7 w6 S8 X8 }" @! a: f2 w
fread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored8 H% W9 [2 k4 M5 P! a; T4 _& x
fseek( s, 12, SEEK_SET); // Seek past the header and useless info8 P6 S! G4 ^2 V5 r. p, R; @
fread( &info, sizeof (char), 6, s );
' l. K- p2 Q2 t# g$ s& W4 p& y
5 q' \0 R8 p* i% D: H7 Rif( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
+ y m& D7 P4 W) q0 QreturnError( s, TGA_BAD_IMAGE_TYPE );
, N5 O) m" q5 f+ U5 `; d
. p. a% @5 c, t+ J7 |m_nImageWidth = info[0] + info[1] * 256;
) B7 M0 m9 Z3 K, \( Tm_nImageHeight = info[2] + info[3] * 256;6 |$ m+ V+ H1 H0 r, K
m_nImageBits = info[4]; # f7 Y& a3 j, _% Z" d& c
! L s/ e: C3 g) Q
size = m_nImageWidth * m_nImageHeight;
& F# W0 V4 q. @" T- i) u* ` \
! E# B: D* {9 R$ H. M// Make sure dimension is a power of 2 r6 ?6 f" {& K* x3 y* F
if( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight))
" C' f! n( U( L0 q. hreturnError( s, TGA_BAD_DIMENSION);
* Q8 {" N/ u: m9 b( T" J( R+ P) X) j* t; P8 \" G
// Make sure we are loading a supported type " t( p# p' f! B+ `# U: \' L* C8 h
if( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 )
- [. E9 P, u7 g' ereturnError( s, TGA_BAD_BITS );
" I$ P' K' }! y+ k" L3 @5 l, l6 n3 E& K" \* K3 [% K
if( m_nImageBits == 32 )
6 O4 v0 O0 G: ]m_nImageData = getRGBA( s, size );7 B0 ?4 m2 r. Q
else if( m_nImageBits == 24 )9 T) M# G5 {$ l5 i; r& A
m_nImageData = getRGB( s, size ); * m: b, h# m9 T. a( A" a
else if( m_nImageBits == 8 )& x9 G) E0 z4 U1 s+ K. h7 e" U) T% z
m_nImageData = getGray( s, size );4 A$ F& d9 C3 E0 C p
) V" O$ t' \4 Y// No image data
0 S o+ P @3 s" [1 h1 x; b; ^if( m_nImageData == NULL )
- ]( f" ]2 z( q& OreturnError( s, TGA_BAD_DATA );
" B. M" k' Z" D: w
! v, e5 m0 H' b9 r) Afclose( s );8 b2 q4 g: D; p, W
# |3 y" k; M9 i9 f' c* O
return TGA_NO_ERROR;
% c( B; t1 _. }! G! P; Y3 U8 B0 c}
" J! R3 |+ U9 }9 ~: S: s
/ S5 n; S" [9 r1 g$ X ?( }3 b2 N+ k) N
6 `/ z: k3 _# T调用举例:
$ c/ j( ]( R' F6 S. [" l N//( T: g" G/ K" a3 x; m- {
// For the billboard poly, load a texture of a steel sphere. We'll use a
* u) [1 n& ?2 l' T9 w( C I2 {3 q// .tga file for this image so we can use an alpha channel.3 s; c& `5 |5 M+ j2 n% Z
//
6 d& F) ~( D6 y/ F
4 \- T$ E0 S$ k( k b; z( ntgaImageFile tgaImage; t X( ^! r m/ L- B6 D! l, \. z
tgaImage.load( "steel_sphere.tga" );
" u5 d/ a& G& `- r+ @ U( K/ A
$ U7 `5 b3 k ?' a1 HglGenTextures( 1, &g_sphereTextureID );
& C8 E3 Q. y: s/ u4 B! w# T/ j5 r2 N! F' |5 | n; H. a4 E7 w& Q
glBindTexture( GL_TEXTURE_2D, g_sphereTextureID );. |& h# Z$ ]2 L$ {# t
) m$ ^ @8 Q9 Z
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );6 k% V X0 H4 f( S1 g0 I
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );/ a- V8 @ `% J( c( c9 x
0 D, G* F- T4 d+ Q9 m/ ]
glTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat,
+ R6 d+ M3 C! ~. }tgaImage.m_nImageWidth, tgaImage.m_nImageHeight,
7 c& W0 n7 b- \& G0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE, 6 H, N! T7 G2 T# J8 t3 | _
tgaImage.m_nImageData );[/i][/i][/i][/i] |
|