|
|
#include <stdio.h>7 B/ @7 m* U: \
#include <stdlib.h>* s/ I2 F. y" \6 s
#include <string.h>% s9 ^3 F1 z% ^
#include <windows.h>
4 B, f8 X4 O7 j* F& G. y# ?#include <GL/gl.h>
* ^; d- Z" h' D' l# ^7 R" U3 G6 {. B' x
class tgaImageFile
) f0 L3 x' k7 T* b{
3 v4 f3 k7 A4 V% M! |9 ]- i/ K' Cpublic:3 y+ a3 N, h3 |$ H( Y, w
6 x* }8 L. \9 E- l( j2 z1 N: WtgaImageFile(void) : 3 A2 t) {6 @6 z) t7 L
m_texFormat(-1),
) [- f) p& \0 m4 l7 nm_nImageWidth(0),1 ?" W( B$ [# d. K
m_nImageHeight(0),4 q( } j9 t& h; |7 i
m_nImageBits(0),4 _0 Q5 @. {: L
m_nImageData(NULL) {}! h0 I: k Y8 G; {1 O
L: T, K; w/ M, I/ N& u! L& H~tgaImageFile(void);
& U( [' G% T( |; N# ?
0 b5 T; K* n! v/ r1 V. f. Lenum TGALoadError3 }7 E0 }+ ]' U% Z
{
% a% t7 H% z$ ~6 Z6 z& p# D9 [TGA_NO_ERROR = 1, // No error/ o I6 K* J5 l2 C( [
TGA_FILE_NOT_FOUND, // File was not found
$ c8 I' Y/ s* r) g. ATGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed
7 ]% r$ P' k. q0 Q2 NTGA_BAD_DIMENSION, // Dimension is not a power of 2 # F2 R' t) h' N. I
TGA_BAD_BITS, // Image bits is not 8, 24 or 32
0 K( M. N1 ] ETGA_BAD_DATA // Image data could not be loaded % Z+ B! c8 m6 v+ O% a/ t
};
0 }9 C) ^2 `8 g4 I" ~
3 f- S* u7 X; W9 }# ^: X% }tgaImageFile::TGALoadError load( char *name );$ F/ H. h' R+ T+ L6 O1 `& D
& X: D9 b E$ U
GLenum m_texFormat;5 ?7 y2 X- ]) U( D
int m_nImageWidth;3 Q7 D% {! V$ W6 B/ Y* |, C
int m_nImageHeight;
* L" s' ~2 t- B; eint m_nImageBits;5 P9 h1 z8 p; ]5 R# {
unsigned char * m_nImageData;
5 P6 F4 w, m2 p, W3 _( X
8 x6 n9 v5 `- z. {6 Y4 p2 O4 ^private:' N/ x! ?* V: j% d
M* {5 z6 Y E1 W6 p! K& |
bool checkSize(int x);
/ y3 B' J/ m( b$ Oint returnError(FILE *s, int error);; F4 l* F7 i! D
unsigned char *getRGBA(FILE *s, int size);# d4 c8 l( r1 C* Y; ]1 I
unsigned char *getRGB(FILE *s, int size);
' R6 ^( @; }" A5 aunsigned char *getGray(FILE *s, int size);! L, q( }( T6 Z7 {, p2 a+ B- ~3 ]
};* f% j! E* o7 H: O+ h
: C; u6 X8 T+ U F2 i% H
tgaImageFile::~tgaImageFile( void )
" @$ l3 T# |7 Y, n# Q5 f9 t/ S{
* g i+ p9 |# e7 ]' Q5 W# a1 o' @- nif( m_nImageData != NULL )
" l5 h: m" b. o+ y0 G$ E{
% v& j. X0 i5 Z: e3 V6 Y+ j+ B7 Nfree( m_nImageData );
9 J- i0 E4 G* D% W2 ?m_nImageData = NULL;+ z+ \2 ~3 ]+ M* [/ s& P
}
( F/ B2 b$ M1 K0 F}# X7 ]) E/ M/ K/ \0 Q" m
* e5 @" c/ R' k3 D% v7 P+ r
bool tgaImageFile::checkSize( int x )
/ T( f/ b: ]+ N- f{, r- D$ p# c8 H' y& i. Q6 T' }
// Make sure its a power of 2.
0 [6 J2 y; [$ y/ c1 T) g( B5 o/ eif( x == 2 || x == 4 || ; O4 V- w2 x$ f; J
x == 8 || x == 16 || $ q2 a2 ~# @2 g3 V
x == 32 || x == 64 ||
# q m# y; ^% q+ X4 ]. Xx == 128 || x == 256 ||
& l4 {9 ^/ Z; `9 }% \8 Dx == 512 )9 C. E, z: A# F8 _0 {+ y+ C, z
return true;* l/ I$ t. d$ W4 C) n8 D1 _5 }
( n% ^& K9 |( i1 U! u- G: _# ureturn false;! V; V7 _' a1 }6 k6 O8 O. k
}
! d- v$ v6 H0 b. `
$ Y9 o" y& }9 e* v- P$ pint tgaImageFile::returnError( FILE *s, int error )
( ^; n8 `) }0 y& f- ~. v+ @{( h) a/ z( _& _' k( @# t" k2 R
// Called when there is an error loading the .tga texture file.
_: @: \# R; _! ]' lfclose( s );* N3 p9 z! ], H% Q& ]7 \
return error;
3 q7 w( ~: K6 r4 g- e}" U+ ?8 q) d4 Z! O/ i9 O' k
, S; M. Q* \: F& s1 x2 Y5 u
unsigned char *tgaImageFile::getRGBA( FILE *s, int size )$ I+ {2 U0 z- N6 M" ?% d/ E
{% B: @* H+ x0 A( ]/ P3 D3 [+ S
// Read in RGBA data for a 32bit image.
" c; }8 x! r8 g7 Vunsigned char *rgba;- R" s z c' ^4 J/ s, H" L/ }
unsigned char temp;
+ t4 g% K9 I: Z' Q1 |, Oint bread;
8 u, Y, h* k! y% _ @# f0 `int i;! v# D q) J: p5 B- \6 |9 [1 W8 \$ Y' @
9 }8 i: [4 F# Z' _5 m" w% vrgba = (unsigned char *)malloc( size * 4 );. S7 g1 f- L" f4 B) ?
( t% Z7 w1 ?/ [1 J8 Eif( rgba == NULL )3 A# Q8 ~- w b; L2 m- M2 C
return 0;" a& ?( `( u, P! x6 u. P
! ^ J$ w' }, {' w3 e
bread = fread( rgba, sizeof (unsigned char), size * 4, s );
. w" p: y1 |, Q. e
# _$ J2 p9 t7 `8 r1 q, _// TGA is stored in BGRA, make it RGBA
+ q5 x6 U8 w. @if( bread != size * 4 )
* k% e5 S# Y }{
/ U0 F5 w2 C3 {& q1 Afree( rgba );
1 j$ i) k; ^* a' ~. p3 vreturn 0;
7 U6 p" V0 c: z M _; z}6 k/ t- [! _; `" o. @" k
2 `; I. d) L. Pfor( i = 0; i < size * 4; i += 4 )
3 a% d: ~$ v, T. g{
% Q5 ]' Z- K8 ~* N% ltemp = rgba[i];
& g( Y5 Y7 L5 U6 y$ w, jrgba[i] = rgba[i + 2];
( f8 y) [6 s; hrgba[i + 2] = temp;6 c% m! j7 ?3 ~) s6 |
}
* n+ ] H' I: X# B2 n
" U2 O5 B7 g: N9 d( Tm_texFormat = GL_RGBA;
, Q, h5 j" H( ^, rreturn rgba;
6 Y9 ?# X% c" J3 U7 M7 p1 R}
" T: }( C# g- A. E/ U* Z, T2 R; `- Q9 b) `
unsigned char *tgaImageFile::getRGB( FILE *s, int size )( r9 u) _, {4 \2 r7 ~
{
# |5 [, `5 n* W// Read in RGB data for a 24bit image. 5 j: Q. E5 C/ C F
unsigned char *rgb;
+ m; I: ^ m- x) P! G& @; Junsigned char temp;; c* V- J, K% n1 G* L) \9 V; |
int bread;
' O9 ?% _: ?$ ~, o% _1 Oint i;
7 U0 s v1 d+ _/ m$ c' Q2 ]3 T: _6 o2 r: F& _* b
rgb = (unsigned char*)malloc( size * 3 );
6 r- e& w9 V8 f1 M* T/ B
2 J% v* G* o. j$ Q& t# s/ S, oif( rgb == NULL ). O8 A K" V+ O8 n/ C
return 0;
! i+ t0 v" h6 i1 M0 j8 c, y& G- u! r
bread = fread( rgb, sizeof (unsigned char), size * 3, s ); s: S% G' H- B) }* N) x5 ~
/ N$ |; Z- P! b9 S2 `1 M+ _if(bread != size * 3)
3 f4 D" [2 D+ n{+ A1 k9 L# K( j
free( rgb );+ F; F3 R. b! s# ^. {# @! r
return 0;# ]/ T+ } F) v/ z& R$ i9 ]
}4 r; s7 x! \" ?/ C1 s0 x/ `$ n
' b' ]" D( w p7 W// TGA is stored in BGR, make it RGB + P/ M% r) i! ~) Y1 q
for( i = 0; i < size * 3; i += 3 )
* D V) u. B( D: Y/ W; p{
# ~2 l5 E& J) h6 b( { ?2 t. Atemp = rgb[i];
0 e, R$ h' @8 a8 |: Yrgb[i] = rgb[i + 2];
/ i7 K: E8 `! C. h# drgb[i + 2] = temp;
3 t: p- L* \& w5 t' o}
0 O# n3 p8 Z: ?6 B% a0 W( P- j- c$ ?& w
m_texFormat = GL_RGB;
0 B( H* b' A$ |& ` p& d. p7 }. Y+ n/ S. V3 u) v
return rgb;2 w# i1 G; d1 C/ r8 F a/ _! `
}8 K) u' h2 s9 \4 s
% D$ P+ M7 p- i1 ]4 _. x3 ~unsigned char *tgaImageFile::getGray( FILE *s, int size )
( f/ I0 Z( S/ X1 ]0 o3 g{- G# y( u5 b7 I' Z& y1 A& h$ v1 Q
// Gets the grayscale image data. Used as an alpha channel.
/ o$ x0 ?8 `, M* X5 u* p) ?unsigned char *grayData;
/ L- \4 p3 z: J4 yint bread;
9 L5 A( W( [/ y+ E# f0 i' T; J* k5 C* d2 t8 J# P' M. M
grayData = (unsigned char*)malloc( size ); I( T1 m% f% }2 N9 M7 M5 S
/ w- a; I. U3 T
if( grayData == NULL )% k, Z% l3 H: `# C7 U
return 0;
: u* g9 S: c6 s0 M
" o, x% k& F0 f. [! Tbread = fread( grayData, sizeof (unsigned char), size, s );8 a- k `9 L: ~- W0 E: `8 f, ~
$ O; f- `4 t4 j" nif( bread != size )
9 f: y) n* O5 o, n; y3 w{# S) q' x; ]0 \2 p0 H) ~! l
free( grayData );: D' X7 c' V9 S& ^5 U0 n
return 0;/ m3 R/ A8 D! s5 P. K
}# g* Q7 M T* A N1 \+ d! U
+ d, R' Q9 `5 ~' zm_texFormat = GL_ALPHA;7 p+ U* Y% R8 F" H! T6 c6 `1 O5 r
4 B4 s) ~' Z- H% J8 i) d/ [" |% H2 areturn grayData;/ F' [, z5 X; S
}, C2 {- S4 B* {$ g9 n* s0 S% t
$ a3 D" b8 t0 mtgaImageFile::TGALoadError tgaImageFile::load( char *name )4 l' r3 B! ]7 s5 f
{6 I& s0 N" S5 I3 ^5 {7 }: k2 t
// Loads up a targa file. Supported types are 8, 24 and 32 " c4 X0 H4 A9 Z
// uncompressed images.
9 y9 V, Z% l5 m3 Nunsigned char type[4];
1 d/ J$ L, D% ?$ l, C4 `: Z7 bunsigned char info[7];: H: R/ y o1 J9 X
FILE *s = NULL;
* o! I0 C6 ~( ]int size = 0;
- `3 m: ]: N1 H" t' M( {$ H) a8 |; C, L0 O3 s" U( C: r+ m' g1 X
if( !(s = fopen( name, "rb" )) )
3 o9 D4 w1 \+ U" c, I. O) M' nreturn TGA_FILE_NOT_FOUND;$ q0 W' D7 h) b' O% l
; g" a% g- @. \
fread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored$ f6 @* Q4 h" v
fseek( s, 12, SEEK_SET); // Seek past the header and useless info
/ i5 s9 {, i/ |; `fread( &info, sizeof (char), 6, s );& r4 Y W! h" M" R' G9 @
5 |" u, |% k5 H# r, e5 s- y
if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )! d0 ~ d! q' R; S8 Z0 R
returnError( s, TGA_BAD_IMAGE_TYPE );6 [) U* }, V- p `1 Z. s
& U0 c% U% ~) R7 {* Y
m_nImageWidth = info[0] + info[1] * 256; 0 V9 H# c, n: N: u
m_nImageHeight = info[2] + info[3] * 256;. S& K6 u S4 O3 ?* b
m_nImageBits = info[4];
1 x4 H7 W5 c4 x' q( U
5 D% Y& ]/ w# bsize = m_nImageWidth * m_nImageHeight;
) `* O! K; z& ?/ P" \
6 Q1 ]) s% L; X+ s* `8 Q// Make sure dimension is a power of 2
+ z* O. @) O* j; A8 Z/ f. F Sif( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight))
4 w: X+ u% j- \0 NreturnError( s, TGA_BAD_DIMENSION);9 ^4 N( e" |$ D( X) ]
9 X* ~- }+ k2 R# D* b- W
// Make sure we are loading a supported type
( E4 O$ G, t3 W7 a5 eif( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 )( a' t A7 g' v( P; L
returnError( s, TGA_BAD_BITS );
4 f: ]& m" C5 U- @% D$ L+ l
8 r5 O: \! f4 b/ e$ R6 F1 zif( m_nImageBits == 32 )
* ?6 P- Y; t s4 o" xm_nImageData = getRGBA( s, size );4 K0 R) L7 C4 Y' F, a
else if( m_nImageBits == 24 ): Z9 X0 q: W9 M$ [: v9 h
m_nImageData = getRGB( s, size );
( X! v2 A0 l7 c6 velse if( m_nImageBits == 8 )' `8 k: v. }" j' X* U7 C
m_nImageData = getGray( s, size );
`' Y R, M; b0 B
' `, h# H& x1 s, y+ N5 O// No image data
6 g6 c' i8 v/ N. O/ _if( m_nImageData == NULL )
' x t7 X+ _ X6 ]returnError( s, TGA_BAD_DATA );
. m* b9 t$ R% e; u3 i3 w7 o3 f- D* z6 b" Z" b' D
fclose( s );
4 {& p" y8 A6 u( s+ q
9 i) H* I: |- d! q/ V' l/ Rreturn TGA_NO_ERROR;! K K- ?4 P ~$ u
}
9 U1 h [+ @5 A: c
" y! }1 `3 @, h/ }+ u! j9 E+ T& o+ S7 r2 ^: ^
调用举例:# p. e9 j# v- L( ~/ I
//
- [* b( M) s; x) H6 `// For the billboard poly, load a texture of a steel sphere. We'll use a
0 M$ t6 C. i! ?4 ^& ^, F3 ]// .tga file for this image so we can use an alpha channel.7 A# V$ S2 E! ^9 }
//# v& g) S O. L8 u. a- g
. I8 W8 ^- z8 C& o
tgaImageFile tgaImage;
! Z6 s/ A) c. X- u, s; i1 b8 htgaImage.load( "steel_sphere.tga" );
^" ^( G; Q9 k8 s& a5 \, r& o2 v1 g0 {" P
glGenTextures( 1, &g_sphereTextureID );) d& v' y" |1 x5 Q7 D# E- C* J
1 O k2 C- F3 AglBindTexture( GL_TEXTURE_2D, g_sphereTextureID );% W s# s# ~6 t, D$ V8 Q7 }
" v( |2 z" E4 t8 j0 ~glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
: R7 E4 E2 \. G% k" k* AglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
3 s9 @- ?" h+ f% J6 N1 i
7 ^/ @* M3 C4 r3 g$ VglTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat,
6 [. b) Q* ~# ]2 `3 j) YtgaImage.m_nImageWidth, tgaImage.m_nImageHeight, & u4 Y6 y# y) o( Q. [
0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE, " A$ h: W; Q1 _ @
tgaImage.m_nImageData );[/i][/i][/i][/i] |
|