|
|
#include <stdio.h>5 G0 u0 U1 B# g7 J7 r7 P: V9 K1 B
#include <stdlib.h>
1 _ D- ]( p+ t1 R6 G#include <string.h>
, g$ F9 ~; }2 q5 a#include <windows.h>! G( f+ x1 P1 S. z- Z
#include <GL/gl.h>3 m( G$ z) Z+ M( J/ T+ j3 M
: m2 r% A+ B( W3 [% E" o
class tgaImageFile
; q) T+ j4 N, J6 P0 g0 A9 i* p0 q0 ~{
. Q! b; t. @2 G5 \) Zpublic:
+ S7 L6 _6 X( ]4 |# C1 q% V
# O) r9 ^# U# R2 J+ g/ etgaImageFile(void) :
& Z- x8 A( Z" ?5 k9 em_texFormat(-1), K; x( l# c& s) d, u1 z1 i: Q
m_nImageWidth(0),! G7 D& b) n' N9 G( T: L
m_nImageHeight(0),
4 j3 S) ^0 i; Vm_nImageBits(0),% K9 N1 U6 i: O/ l. |4 k
m_nImageData(NULL) {}
% S: P8 ~+ B. G+ l ?( _: D& F& I/ Q" }
~tgaImageFile(void);
, P7 Z; [% Z' A
8 N- J! F9 R, l% ~3 C( |: `" Xenum TGALoadError
8 k4 [- b8 b0 Z7 L, W9 c{
( G# x$ O! {& A/ X* qTGA_NO_ERROR = 1, // No error: B2 v0 z! `$ X5 _
TGA_FILE_NOT_FOUND, // File was not found 5 m; ~5 u% f, u
TGA_BAD_IMAGE_TYPE, // Color mapped image or image is not uncompressed2 y6 }1 ~1 {! B
TGA_BAD_DIMENSION, // Dimension is not a power of 2
' E" L6 q) p. p0 ]$ N* ~+ [TGA_BAD_BITS, // Image bits is not 8, 24 or 32
; s! |/ A# M \$ ~1 P! }) Z3 jTGA_BAD_DATA // Image data could not be loaded , g9 ^! l5 h9 c' s! Q
};# h3 @ a& Q2 S4 B4 W; X
/ b! f% f V5 S7 z3 ]tgaImageFile::TGALoadError load( char *name );
$ h5 N6 j* @( C. p% I- v+ O+ t( K
7 Z' M- T5 Y! s+ y& ^3 E3 MGLenum m_texFormat;8 B4 b. x4 U% T f) J9 p0 N7 W
int m_nImageWidth;
, @" T/ r% h, `int m_nImageHeight;
9 s" j# h0 W) kint m_nImageBits;1 U2 Q, Z4 C/ W6 Q$ q1 V# g6 s% p
unsigned char * m_nImageData;# i0 ]. X) [" U# }
; j6 G5 g. S; K. vprivate:. [, ~( @ K9 ?3 X; i% v; V
0 M3 A8 w }) {bool checkSize(int x);
- d3 q* A$ f' P, q4 D6 J( Y$ ^int returnError(FILE *s, int error);" {, `9 | Z$ m! e/ o
unsigned char *getRGBA(FILE *s, int size);% l8 _1 e3 B# A( M; ?& X' J0 ^% c: x
unsigned char *getRGB(FILE *s, int size);+ P/ L2 B8 H8 a# @
unsigned char *getGray(FILE *s, int size);, e/ ~9 }/ Y: ? P# D6 L
};% a5 F0 Q% F o3 F0 q, U7 p
. i2 T! B' k' ]* C5 e
tgaImageFile::~tgaImageFile( void )# H8 e6 F4 y2 q' @2 P' H3 R
{; F) }- `; g* ~* M
if( m_nImageData != NULL )
, V) [! U4 N! \; x{
6 R' k5 d1 s7 x2 {0 [free( m_nImageData );: w, y6 p" y% f' [# d" J* g
m_nImageData = NULL;
* q, v: N% ~; _; S1 Q7 i0 j% c2 J}
5 t V6 L+ c) d% b& M8 z) ]6 b}
3 E l5 d6 }" Z5 ~( O: W/ e* ?# u
bool tgaImageFile::checkSize( int x )$ T& W( Q9 T9 u+ ]+ B& i% a
{
# T7 m+ a5 j# I' F/ I// Make sure its a power of 2.
, x# E& v% w# t/ J% r! Eif( x == 2 || x == 4 ||
# I5 q1 x$ z- b* ?% y% dx == 8 || x == 16 ||
& w5 _# c; D) G+ B }2 z3 v% \x == 32 || x == 64 ||+ g& H% t U: O
x == 128 || x == 256 ||
3 U: e3 ` ]' z2 zx == 512 )- p! ~$ V9 L1 H2 h8 n
return true;
6 T2 l- H- q) }' J. S# Y& }& o _$ K% c+ z; Q/ ^
return false;- U6 `8 V9 a1 K
}. i5 { T' S" A8 _
; Y( x% O% d, L9 |3 f
int tgaImageFile::returnError( FILE *s, int error )- [% Y, H1 y# L s" [. ^% t# l
{
/ O" _7 [# `3 q/ f+ m// Called when there is an error loading the .tga texture file.1 H* ]6 M# U% `
fclose( s ); |% u5 h- d" ^9 m7 R- e4 ^- ^
return error;
_5 [2 L+ S4 x}
8 M! `- v' w4 }! {7 X$ w
% F3 c9 u2 \9 ~3 yunsigned char *tgaImageFile::getRGBA( FILE *s, int size )
) R) }- |5 C* `- M1 ]* A. N1 B3 E/ c9 O{
( T: }. v# h' R3 ], y// Read in RGBA data for a 32bit image.
2 j& }* r+ d! D* funsigned char *rgba;8 V2 f: O! g( G u' a* D
unsigned char temp;
" E' l- D8 E6 Sint bread;9 q& U% A& ]0 Q8 J6 X5 o
int i;) P% R. Z; G, _2 R, U
8 a' @; a U) p; _$ P9 s6 grgba = (unsigned char *)malloc( size * 4 );
" Q2 q) l6 h- A
+ L9 U2 F8 Y$ I X' p* wif( rgba == NULL ) |5 d' W# t# t0 w- [. [
return 0;
" H( z: `+ R) h$ W; |# @9 D3 T% M5 y! ^! x
bread = fread( rgba, sizeof (unsigned char), size * 4, s ); . c1 z# Q6 L3 ^
/ E9 l i1 S8 T1 x5 l// TGA is stored in BGRA, make it RGBA 1 u% ^ @+ A, F( z0 C0 [
if( bread != size * 4 )$ C( j: [1 ]0 M5 F9 B
{4 @, G. ?( w/ Z9 K) s$ f9 [, R
free( rgba );! u; l, Z9 G O j" O
return 0;* {, n$ y. I6 r! p+ j/ P
}1 ?, j+ B& \; @% h
( i) O* ]5 b7 T4 e+ k
for( i = 0; i < size * 4; i += 4 )) ~( b/ b! p$ Z) X
{
6 i9 u& }' y- [3 Ztemp = rgba[i];
7 x% ]0 s# O; z& trgba[i] = rgba[i + 2];1 U- g8 R5 E* ]% g; ]
rgba[i + 2] = temp;
* X6 U3 v7 x, ~( D: b}" t" u/ I7 ] g8 z8 \: J+ z
# @8 U' N$ W8 I/ r! `) dm_texFormat = GL_RGBA;. \, @4 @9 I4 i: k/ O
return rgba;
" I& J1 m0 S* b}6 _; f/ y7 E! g; M$ _- X* B
: B8 S* S0 n' W: T8 @unsigned char *tgaImageFile::getRGB( FILE *s, int size )1 o/ C# _! R( ^0 O& ]
{" p' S+ ?) U( y: t9 Q
// Read in RGB data for a 24bit image. ' D7 X7 o. G3 `$ ^4 A: d) T5 }7 _. r/ Y
unsigned char *rgb;; F J, m( h4 y4 T' N- @$ O O
unsigned char temp;
6 W9 q. H: m8 x% J& x9 Pint bread;# C. B6 N3 d M" B) ~) u* w. r
int i;
) C4 p2 k) e6 m0 n6 g8 V* H
% W4 o2 @" u* h& ?3 p6 I: zrgb = (unsigned char*)malloc( size * 3 );# } v4 N' b% ]
2 y6 F; i* l- M
if( rgb == NULL )
' o: K5 M. L/ W) `1 G1 Kreturn 0;, O1 ^% v: E( _7 E
8 ` B$ O, B9 Abread = fread( rgb, sizeof (unsigned char), size * 3, s );
" w, n B) T$ T$ ]" x6 f3 a1 ^, G0 V, R" g( E# X
if(bread != size * 3)
3 C9 M+ q2 ]7 @! W- g! R- P& k# {{* q, v1 F% `- C6 {
free( rgb );& k7 Z/ M. d+ E5 T& G W* J
return 0;! @& U: j s9 {8 \! _0 r2 e4 m
}% v! C6 r) i2 G
+ |8 E. Z3 D' O/ x: l: C* L. ~
// TGA is stored in BGR, make it RGB 5 O- k$ l6 r5 S1 b: ^+ k6 T
for( i = 0; i < size * 3; i += 3 )
8 V4 H4 ~: g- x R* _" d* A( r# W{
2 Z: ~2 b* G! c4 P* m8 Mtemp = rgb[i]; n' G u& O+ V* u4 m4 u. H
rgb[i] = rgb[i + 2];
9 X: c: s; B9 y v5 }4 xrgb[i + 2] = temp;6 H8 S F; J/ P- m
}7 E: V( j( S. ~# y* u6 V
, k" l4 W% p7 _
m_texFormat = GL_RGB;
) T3 [! ]3 @1 e; I5 Y! n9 X$ V; p: y: }/ N9 }5 Q/ o
return rgb;
* r+ W- Z6 N6 ~9 a( d c}
/ Y0 I# l6 d8 t/ O% `
! f) f/ \# v1 }unsigned char *tgaImageFile::getGray( FILE *s, int size )
5 n) \" I3 } u# G( G{ U1 D2 n( j1 a0 ^7 W* T+ {
// Gets the grayscale image data. Used as an alpha channel.1 ?3 a% w# M) j8 `) g/ I
unsigned char *grayData;
6 V' O D7 N0 F' L- F; t: N/ N0 H' Vint bread;6 w# U& ?; l; k+ A
# |# X+ N! o3 U' J+ o9 M2 n& MgrayData = (unsigned char*)malloc( size );
+ N2 {0 z: ^; q1 N! g0 _$ F6 V2 J# W
if( grayData == NULL )
3 c! a% t3 N$ zreturn 0;
1 g2 R9 a* I& G" _
+ y6 ` T. E' M: h1 Mbread = fread( grayData, sizeof (unsigned char), size, s );* h0 F0 t' |$ s, ~' f0 X! s# U
5 i6 }7 G% S# a
if( bread != size )
& w$ R1 A2 F' z6 {& y{
( c- }' D( F+ d b. W2 e( {free( grayData );) h; t* w8 O$ ~
return 0;
. Q, x0 a/ [( ]2 g}3 S% b; S' M! A1 B
+ a* c( {9 p2 ~/ Bm_texFormat = GL_ALPHA;
, f$ |* _- P. S" m) d& S1 M4 R% ]
7 Q9 q, J3 m2 P" q( h3 Breturn grayData;
8 @1 G* C- x7 q5 @" s}; d' u J3 _) Y- H" d+ b
& H: t1 I& \0 X
tgaImageFile::TGALoadError tgaImageFile::load( char *name )+ }& q6 d# ]' o( A) g
{
; w3 J* [. \5 ? j// Loads up a targa file. Supported types are 8, 24 and 32 ; A0 I7 }; s" s; v
// uncompressed images.+ D( T2 M5 f/ S. o$ O
unsigned char type[4];7 H; v$ t9 r W$ S! Y
unsigned char info[7];
' Z ?. @7 B: U" M4 S% ^7 B; @FILE *s = NULL;! m" K% v9 ?/ |/ b0 |! R
int size = 0;
5 W4 E, p& f, @' \
+ I/ R8 g+ w5 h, A5 \3 Y9 aif( !(s = fopen( name, "rb" )) )
* N4 e6 d# Q% ^return TGA_FILE_NOT_FOUND;" ^& u- g( m, T
/ h4 y2 h; O5 |/ O$ {9 I
fread( &type, sizeof (char), 3, s ); // Read in colormap info and image type, byte 0 ignored
* g7 U$ @. b2 Bfseek( s, 12, SEEK_SET); // Seek past the header and useless info
7 Z" V1 l4 [$ x1 G9 ^1 v7 d4 gfread( &info, sizeof (char), 6, s );
8 \( Q9 S; M6 S b4 C8 X& f. B9 i
6 e( l5 z- ]" k3 a- n! M; {if( type[1] != 0 || (type[2] != 2 && type[2] != 3) )
4 A0 p6 U# h# u2 L' x4 M- h; S* l/ RreturnError( s, TGA_BAD_IMAGE_TYPE );
8 x, s- t0 \& o4 J1 _9 h9 ?4 m1 g# S" R4 @5 t4 P/ a0 J$ E& z
m_nImageWidth = info[0] + info[1] * 256;
; v- x3 m; S- X& A0 C( Tm_nImageHeight = info[2] + info[3] * 256;/ M/ ~* t6 o D
m_nImageBits = info[4];
3 {+ o, q1 `/ v2 }1 z: ?( O1 A" h& J3 d" _$ r2 ?/ K+ o( z9 b
size = m_nImageWidth * m_nImageHeight;
2 ]) Z( G r3 d% ?/ T& [& E' o
# A5 F3 E, k3 B! K0 t* f \. \// Make sure dimension is a power of 2 " @. g1 Y# o4 F- z# R* S
if( !checkSize(m_nImageWidth) || !checkSize(m_nImageHeight)); }# M; Q F8 f. n' E/ v$ q
returnError( s, TGA_BAD_DIMENSION);; B& y" K/ i/ \% T
5 m$ r* m& t$ q
// Make sure we are loading a supported type / e; i" k) e9 V5 P0 g4 E6 U
if( m_nImageBits != 32 && m_nImageBits != 24 && m_nImageBits != 8 )5 x9 A. O4 f: h( n. J
returnError( s, TGA_BAD_BITS );8 F9 |# p- u7 y3 u
4 k$ B. X% ~6 w1 G; }# Aif( m_nImageBits == 32 )
! M( V8 R* d" D5 T* D3 pm_nImageData = getRGBA( s, size );
1 W" @% V3 W6 Selse if( m_nImageBits == 24 )
, t6 X* O6 Y0 ]2 s7 s3 Q% Mm_nImageData = getRGB( s, size );
2 ~- ^7 x' C$ l) C5 uelse if( m_nImageBits == 8 )
/ i- _$ O& w) M* h3 `, y5 h$ Nm_nImageData = getGray( s, size );& f! K2 j/ e+ X
r m; G+ o+ S) X9 I8 y
// No image data 1 l: Z$ [7 t% h- y) @, Q0 q
if( m_nImageData == NULL )8 l4 v9 W6 p; V: k
returnError( s, TGA_BAD_DATA );
/ {' m2 \+ C1 x9 g" j
) `7 f6 Z, I, i8 G# |3 ?fclose( s );! k' J6 D, n' _1 K9 c/ O/ U
$ u; B* X3 B0 L, _
return TGA_NO_ERROR;. e& D3 ^! d; F) o6 o4 D, @ \' C. L3 m7 R
}6 C( V& W( [4 }* p
5 b3 s7 b, x3 x, R) E5 R O" h3 |5 l' t' j9 [1 w3 j
调用举例:
% d2 `* `7 g2 E+ d3 i U7 F1 A//( b X* f+ @: S* m% L
// For the billboard poly, load a texture of a steel sphere. We'll use a * m$ I3 e4 V: d; o
// .tga file for this image so we can use an alpha channel.9 ?. b. S0 ?/ B1 M% `
//; y" ~9 R3 i4 e$ v, h
# g. M1 _/ ^, R* P6 X8 b/ ?tgaImageFile tgaImage;
& {# v: ?6 L# A+ R( O' Y# [tgaImage.load( "steel_sphere.tga" );
8 R4 H6 k4 @" B0 \( B
8 T9 W! S9 T" O0 uglGenTextures( 1, &g_sphereTextureID );
9 t: r4 |4 V( ?" O: s i2 v; m* h$ d0 M! i! O! X$ l4 Y
glBindTexture( GL_TEXTURE_2D, g_sphereTextureID );% P6 K; b8 |4 @. h! S6 ~! j; `
) z0 B( n8 q2 }
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
- X5 v; G# m' T; `- o4 ZglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );2 H, {% r: x$ r9 M. O1 m* \ q
' v1 `6 [& p+ r/ J& L
glTexImage2D( GL_TEXTURE_2D, 0, tgaImage.m_texFormat,
/ l, c* b/ R/ Y! g& `tgaImage.m_nImageWidth, tgaImage.m_nImageHeight, 0 B0 f) r3 K& q
0, tgaImage.m_texFormat, GL_UNSIGNED_BYTE,
/ w6 D0 R' h2 R0 @- i; T6 gtgaImage.m_nImageData );[/i][/i][/i][/i] |
|