|
|
#include <stdio.h>
9 b/ ~4 B0 l) i4 D; E1 `6 ]4 H2 }) X) q#include <stdlib.h>
# ~2 e! ~; R. L' R/ j#include <string.h> C- q9 }* Y% q" e
#include <windows.h>5 H I0 N# |7 e [
#include <GL/gl.h>" Q y( Y' t* Q: D& @4 V
, K1 h X, q* E! w0 zclass tgaImageFile* G, B( V$ z1 L+ B4 L
{
2 u; i" a+ K; G& ^public:4 m* H% [( {9 [6 ~
5 k0 t0 A5 @. S
tgaImageFile(void) :
# J2 S! R% y8 U- j+ Cm_texFormat(-1),
) c& \9 p8 a3 \1 G1 s1 Mm_nImageWidth(0),' N' w4 X- N6 j* d* Y. q) I2 [
m_nImageHeight(0),+ a! i& `5 y+ V- P
m_nImageBits(0),
3 w" d7 ^- n. Y8 ym_nImageData(NULL) {}: f6 E, j: V& v' y
8 Q# ]8 N0 K# O3 Z& x8 o
~tgaImageFile(void);
. t7 L7 G% T7 o$ p2 X
g9 b' V6 B O+ Q4 z I3 Genum TGALoadError
& F4 g0 O y& U{3 y" K) y$ |. w0 T! G
TGA_NO_ERROR = 1, // No error. T( r1 g# G' x
TGA_FILE_NOT_FOUND, // File was not found
, b6 j. a& L4 KTGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed
" a, T! K$ @6 Q% @/ H* _4 j1 m6 l- ITGA_BAD_DIMENSION, // Dimension is not a power of 2 / `( J: U7 H: g2 A4 z; `
TGA_BAD_BITS, // Image bits is not 8, 24 or 32 ( ~- j* {- j9 M' m; J
TGA_BAD_DATA // Image data could not be loaded 1 V+ C: R! F7 a: m# v% w. y
};/ }5 R2 f9 x, c! x( V/ R% S+ o3 i( j
; D% Y1 W% z1 rtgaImageFile::TGALoadError load( char *name );$ G$ |* c. y/ \5 X) i, A" `1 s' j \
2 w/ }7 k, c8 e( o: x
GLenum m_texFormat;
+ Y$ C, G5 M5 [int m_nImageWidth;
) o; H2 b# v5 W% k2 E& Sint m_nImageHeight;
; X$ V2 n; w9 b8 i. }/ h3 eint m_nImageBits;
! F+ b1 i) m j9 r( e( Zunsigned char * m_nImageData;
) n1 l! |4 I/ F% v# O2 A7 j. }' r
! f ^2 U6 L0 ^2 P2 O s; I" nprivate:
1 I- W9 J- e0 @' l, l. O# D( T- p0 W% h4 x3 u4 k
bool checkSize(int x);
' Q: {# p% m: l2 @. iint returnError(FILE *s, int error);) W; Y3 l7 L$ i6 @$ r: o% G' T
unsigned char *getRGBA(FILE *s, int size);' P2 l9 B) B1 N$ }, ^
unsigned char *getRGB(FILE *s, int size);
5 ?3 S. V7 W( O8 L9 {unsigned char *getGray(FILE *s, int size);* T2 A8 n6 P6 k8 p; B* C8 i3 M' |
};0 z/ _- @. {! ~' d- k) U) e1 l$ V
' p3 ~ Z5 Z9 BtgaImageFile::~tgaImageFile( void )
- ^# L( u! ^9 \, w/ e% t{
+ G0 o5 `" @: x6 P5 `if( m_nImageData != NULL ), a w5 ~, Y" @9 B. j
{5 @$ K! T7 |( t
free( m_nImageData );7 @# y' l0 z/ L; B' l
m_nImageData = NULL;
* {: @1 \: v, m/ B3 g5 V0 K4 E7 O}
4 r. T* [5 \1 `2 q* z2 p: V}$ z6 s! J$ F; ]9 Z* N! ^. z& T* F9 T! t
/ F4 H* t+ ?) f9 u. {5 ]
bool tgaImageFile::checkSize( int x )
3 s0 I& P& F2 S( ~/ B" o/ f* ?{0 Y- ~! B) g' V$ F" U8 K2 ?/ v
// Make sure its a power of 2.
/ A4 S v5 F# l$ [' ~0 C- Iif( x == 2 || x == 4 || 2 ], r5 L, a5 V) \, z# t1 L
x == 8 || x == 16 || 6 p7 ]* [$ Y9 @/ t" Q
x == 32 || x == 64 ||) V. U! V H% e! t, d
x == 128 || x == 256 || # p) F8 Z0 G; w; V: I# g
x == 512 ); a, x( l; _& `& `9 {+ n# Y9 `
return true;
9 ~" Y( x1 h1 ~$ U: f R& J1 x2 Y: h0 \4 [* O
return false;* V" B( K9 v6 M" l" v, Z7 k
}% }1 H9 |( w0 y$ O% ^. u& k) F
3 i G8 N5 }& X) aint tgaImageFile::returnError( FILE *s, int error )
# G1 E4 Q& T1 [+ {{0 a; c1 A6 r ^
// Called when there is an error loading the .tga texture file.
; a- ]; \" _* I1 \: m! mfclose( s );; k% I9 k* o: H: @7 h2 [: P/ [
return error;
% L: }; f' ~- q+ y}) j4 [# w: C% Y- \* h0 c9 v
- \% M+ l3 L" M) f9 Aunsigned char *tgaImageFile::getRGBA( FILE *s, int size )9 c; P' x3 w( a7 a+ P8 M
{# f3 M" R# X+ A- x1 F) ^9 B% X
// Read in RGBA data for a 32bit image. k, G5 G5 z- h5 q! K( A
unsigned char *rgba;
/ k8 v3 K: Y& z! g7 K" xunsigned char temp;( }3 }3 p6 P% h: u6 z
int bread;
8 `7 x! B" n% Z) X' Zint i;
Z) Q4 O9 [% w% `3 M7 Y) ?+ o. |' V4 G, F) w, U) X5 X1 M2 H
rgba = (unsigned char *)malloc( size * 4 );: ~7 s) o! P1 ?5 G8 h" H! r2 l0 W
6 U5 e3 d/ X& m$ I, t7 ~if( rgba == NULL )
$ g, J/ m# @4 C/ Jreturn 0;9 }/ c. J# s6 r
: m( ~, e% c: f( L* g
bread = fread( rgba, sizeof (unsigned char), size * 4, s );
: m! Z( i8 S1 {' Y
% ]. A: p( f" q0 h6 c/ o+ `// TGA is stored in BGRA, make it RGBA 8 T; a0 e$ Z, m& o) B
if( bread != size * 4 ); a/ \: d! l5 h, i
{* b5 Z& ^4 z+ A8 Y8 b
free( rgba );
! k% a8 x f- o( `1 e- A' jreturn 0;2 X- B- f j' F9 K' c6 x
}3 R4 W1 q: `! H L
3 a- O4 y; B& m9 W; }& Q9 sfor( i = 0; i < size * 4; i += 4 )
( q0 r/ G S0 x{
" Y8 a/ ]- p9 T+ c) @7 d5 Otemp = rgba[i];
) _3 r7 x% {* E0 h& Prgba[i] = rgba[i + 2];
. b* {- S" C# x) H/ o9 y# drgba[i + 2] = temp;: d: z9 [: m. m; s M. i7 j
}% _6 I! p" k' Q& n* @& y* k
6 q9 j# b. f" c6 xm_texFormat = GL_RGBA;
8 q( x$ N7 ^1 C* ~7 N, qreturn rgba;2 I0 f8 `1 X7 J/ Z8 i& F
}/ M+ y2 [8 C) M" ~9 H+ Q$ j8 Y
+ Q; K" F! G/ o4 c6 }2 C5 L+ bunsigned char *tgaImageFile::getRGB( FILE *s, int size )$ A- Y, {7 I& C- }
{9 c, [! v& }* n9 w
// Read in RGB data for a 24bit image. 2 t' F$ \& k3 e! h6 h, h
unsigned char *rgb;8 _- k5 p4 |7 q' w) ?# T) L
unsigned char temp;
$ D" u! i) S' H- g$ B: }int bread;. g: @2 y8 W1 Y9 q' x# l# ~5 A5 L
int i;; c, L6 u) X# Q. A: ^
8 [; ^) x3 K8 ]* X& O
rgb = (unsigned char*)malloc( size * 3 );
) ^& A- _" ~2 ^
2 W5 P/ H. L: U, P8 ~if( rgb == NULL ): C) D2 h4 b5 p/ S9 x; k( f
return 0;
% Z0 o( p- [" g5 N$ x D3 ] G
+ s6 J# o8 I, ~/ o6 c& g2 m: A4 mbread = fread( rgb, sizeof (unsigned char), size * 3, s );5 N, U# |5 g2 R/ T. N) m1 y
1 M3 Q0 L: R" c9 Aif(bread != size * 3)
6 {3 a0 m1 s3 Y' a0 c- O4 \{
. T' d& h" `5 v6 [5 {: Ffree( rgb );
$ p' X! E6 P" C: Areturn 0;2 d4 N$ }3 Y: h9 ]' T" [5 h
}
8 ]/ u9 q' _- g, J1 J! x& P1 S" G6 G1 r c
// TGA is stored in BGR, make it RGB 2 [$ _( n8 c3 ]3 L7 ?
for( i = 0; i < size * 3; i += 3 )
+ J* A3 c0 e: C! Y{4 r% p5 ], C5 N- i8 Z6 \. X
temp = rgb[i];) C# X# }9 W) }$ J. J2 u/ t5 i' a
rgb[i] = rgb[i + 2];# B7 D2 U+ c# | S3 F
rgb[i + 2] = temp;
% {5 U( K" H$ x) j& m}
' v5 X% j. F# L. d: d* c" E8 r/ l* Y3 d
m_texFormat = GL_RGB;
9 y1 |+ s6 p/ H* E, r& ]# p7 _/ X; h
return rgb;7 D, o4 \" E" |& \
}
5 ?' w T" d/ m7 D+ e
, `) Q( n: d/ @6 q+ z& aunsigned char *tgaImageFile::getGray( FILE *s, int size )/ ^5 x/ ]! K) i
{* ~- \, }/ ?" B( v4 [# M
// Gets the grayscale image data. Used as an alpha channel.7 T3 p9 z) [% r$ b
unsigned char *grayData;
- q% c% y" |5 Z% w# Aint bread;; m3 H: D6 g7 [$ Q! ]
, F/ u n6 o' V3 s1 V
grayData = (unsigned char*)malloc( size );
4 r1 v% ~' Y# D& `
( X& u( ^% f8 C6 Fif( grayData == NULL ); Q; h8 ]1 _9 e4 v$ x. i( {! ^
return 0;
( ?# n) q8 h0 O# a( V/ S6 W% m; `$ h: X
: i% ?+ l5 b# r+ A# ^bread = fread( grayData, sizeof (unsigned char), size, s );5 X, y. p/ n) ~( c" |* j
7 G- l n" t- M/ kif( bread != size )
o5 V6 @- H3 F{
/ s- r/ x; r+ Kfree( grayData );
7 P% i) r) N7 h# _9 vreturn 0;6 H7 P# j! h% |* C' S# G" w* K
}
5 {$ n* P( x# w0 d. R, f, d- c
# s0 k; @3 i( S- T' Xm_texFormat = GL_ALPHA;
3 t1 I: q1 U( X8 q @" X; I; h/ @& i [
return grayData;
0 W( E, w) B V9 o2 S& r}
2 z. t9 f U* f, b
6 ?/ z1 {7 d: `/ p) w$ w0 f5 [$ v: otgaImageFile::TGALoadError tgaImageFile::load( char *name )7 p+ j: p0 s% B0 }
{1 m2 ~# g9 c) G& ^% J" p5 C
// Loads up a targa file. Supported types are 8, 24 and 32 4 g' m) m3 l; X. @
// uncompressed images.' N6 R/ n: T5 L/ j
unsigned char type[4];
' U! S, X1 x' u3 q2 Zunsigned char info[7];7 o" z+ B; I! j/ Y" i
FILE *s = NULL;
0 Z4 G4 J X7 K& k8 gint size = 0;( Y! t# w8 A4 a) o3 @0 ~5 }
: O/ d! p* N& k4 Wif( !(s = fopen( name, "rb" )) )* d" E, a6 \" U: ~5 ^
return TGA_FILE_NOT_FOUND;: J6 v/ Y/ f7 L
: ]6 | U/ ]2 a# G, w) Tfread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored; P5 }1 s% F/ T* j' k
fseek( s, 12, SEEK_SET); // Seek past the header and useless info7 G. v& C& g# j5 h: o8 P
fread( &info, sizeof (char), 6, s );
! T" u* z4 J/ F0 x
4 H* b4 B6 w. `" L8 `if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
7 N& `& m" \# |" j/ ~- o/ freturnError( s, TGA_BAD_IMAGE_TYPE );- s. _4 K) E$ o0 O2 W
! w) M) p. c4 ?/ K# ]m_nImageWidth = info[0] + info[1] * 256;
1 ~ }) S4 X/ y ~$ em_nImageHeight = info[2] + info[3] * 256;. j( \6 F% r8 t+ k! u9 }) s) `
m_nImageBits = info[4]; 0 Z$ ?3 y. g8 M* W) t5 @
. F9 z& A+ C1 q9 s% tsize = m_nImageWidth * m_nImageHeight;
2 p3 F t( P6 p" F. `& F; _; u# o1 \: b4 o3 y5 U
// Make sure dimension is a power of 2 " I. |* ?+ C _1 L/ I
if( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight))
: R8 \) j# g) d3 v' ]returnError( s, TGA_BAD_DIMENSION);7 \9 ?) ?# v5 V* r6 I3 t! A
2 D& C. h: t* M% e7 v$ v// Make sure we are loading a supported type ( ^& J6 i8 J$ ^$ s+ n% h
if( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 )
! M0 A5 u( ]! kreturnError( s, TGA_BAD_BITS );
; ~% }) l3 X+ B2 ?( M6 V) T
: X- ]& T* {( F3 `- L3 ^if( m_nImageBits == 32 )8 T# g9 X' Z# Z2 `/ g
m_nImageData = getRGBA( s, size );9 { c" f6 j1 d0 ^& |+ D
else if( m_nImageBits == 24 )
, P' J4 C$ ?& g! r4 n2 R) z: em_nImageData = getRGB( s, size );
+ o/ G4 _: H$ {, { `else if( m_nImageBits == 8 )2 t0 Q; T; V G1 `6 j9 ?
m_nImageData = getGray( s, size );( m+ X9 x( ]! e8 _/ x5 f3 D
3 ^0 Q0 Y; q+ |5 Z+ O. L
// No image data
, X; f, ~9 n6 b% H; u5 ~2 P( pif( m_nImageData == NULL )
8 |7 p1 t' R" e3 Z5 `3 S) C9 ^returnError( s, TGA_BAD_DATA );4 c5 K9 T2 l/ B) M, q
6 R+ ^3 [& A- w6 r0 t9 Kfclose( s );
" B: T9 a- @, D6 o& V3 X- H& z) l& i& }6 X( _3 t
return TGA_NO_ERROR;! O5 B2 [+ }$ {, k6 d
}* d5 K$ W% q% K6 c/ Q- P, f
/ `% T2 C( f2 Y, N
, ?2 g. @7 p6 r4 E8 e
调用举例:
3 U- `% e' h- u" z//
3 {1 G" e Z# {5 ~- g" ]// For the billboard poly, load a texture of a steel sphere. We'll use a
/ X+ Y# k1 L% b$ S// .tga file for this image so we can use an alpha channel./ I& A( z5 Q4 l
//1 u7 \+ X9 n* l1 ~
, ?) J9 w* n0 G8 H4 Q
tgaImageFile tgaImage;# p( T- m1 k7 p( r; x w6 Z
tgaImage.load( "steel_sphere.tga" );5 G% l7 E2 e5 G; D- w; w( ]1 B
) T! `+ i& e; zglGenTextures( 1, &g_sphereTextureID );
# p3 E& _; h3 q4 z3 g* `0 v3 H) }5 h y
glBindTexture( GL_TEXTURE_2D, g_sphereTextureID );
& P' M. Q6 X4 X" e
0 d- G; f: Y, b: S$ DglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
' l$ o9 _" d7 m2 `8 EglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );, ?8 _$ u( @) _2 k
; d. ^( u- ]8 h2 xglTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat,
/ K, {# n8 ?1 \' N6 `9 rtgaImage.m_nImageWidth, tgaImage.m_nImageHeight, 1 g$ Y, k/ A E) A- X& [5 B: }
0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE,
- ?! u) }; h# q3 ztgaImage.m_nImageData );[/i][/i][/i][/i] |
|