source: Graphics/image2.cpp @ 15

Revision 15, 4.8 KB checked in by chris, 4 years ago (diff)

Graphics/Image? work

Line 
1/*
2 * Filename      : image2.cpp
3 * Author(s)     : Chris Thielen (chris@epiar.net)
4 * Date Created  : Saturday, January 31, 2009
5 * Purpose       : Image loading and display
6 * Notes         : See this note section in image2.h for an important clarification about the handling
7 *                 of non-power of two image sizes and the difference between virtual/effective dimensions
8 *                 and real dimensions.
9 */
10
11#include "Graphics/image2.h"
12#include "Utilities/log.h"
13
14// Create instance by loading image from file
15Image2::Image2( string filename ) {
16        // Initialize variables
17        w = h = rw = rh = image = 0;
18        scale_w = scale_h = 1.;
19
20        Load(filename);
21}
22
23// Load image from file
24bool Image2::Load( string filename ) {
25        SDL_Surface *s = NULL;
26
27        if( ( s = IMG_Load( filename.c_str() ) ) == NULL ) {
28                Log::Warning( "Failed to load %s", filename.c_str() );
29                return( false );
30        }
31
32        // virtual/effective w/h is whatever the original file intended (eg ignoring canvas expansion)
33        w = s->w;
34        h = s->h;
35
36        if( ConvertToTexture( s ) == false ) {
37                Log::Warning( "Failed to load %s", filename.c_str() );
38                SDL_FreeSurface( s );
39
40                return( false );
41        }
42
43        return( true );
44}
45
46// Load image from buffer
47bool Image2::Load( unsigned char *buf, int bufSize ) {
48
49}
50
51// Draw the image
52void Image2::Draw( int x, int y, float angle ) {
53
54}
55
56// Draw the image centered on (x,y)
57void Image2::DrawCentered( int x, int y, float angle ) {
58
59}
60
61// Returns the next highest power of two if num is not a power of two
62int Image2::PowerOfTwo(int num) {
63        float q = (float)num;
64
65        if(q != 1.)
66                while( !((int)( q /= 2. ) % 2) && q != 1. );
67
68        if(q != 1.) {
69                // num is not a power of two
70                int c = 1;
71                while(c < num) c *= 2;
72                return(c);
73        } else {
74                // num is a power of two
75                return(num);
76        }
77}
78
79// Converts an SDL surface to an OpenGL texture
80bool Image2::ConvertToTexture( SDL_Surface *s ) {
81        assert(s);
82
83        // delete an old loaded image if one eixsts
84        if( image ) {
85                glDeleteTextures( 1, &image );
86                image = 0;
87
88                Log::Warning( "Loading an image after another is loaded already. Deleting old ... " );
89        }
90
91        // Check to see if we need to expand the image
92        int expanded_w = PowerOfTwo(s->w);
93        int expanded_h = PowerOfTwo(s->h);
94
95        if(expanded_w == 1) expanded_w = 2; // many cards won't accept 1 as a power of two
96        if(expanded_h == 1) expanded_h = 2;
97
98        if((expanded_w != s->w) || (expanded_h != s->h)) {
99                // Expand the canvas (needed)
100                SDL_Surface *newSurface = NULL;
101                newSurface = ExpandCanvas( s, expanded_w, expanded_h ); // ExpandCavas will set new scale_w/scale_h
102                s = newSurface;
103        }
104
105        // real width/height always equal the expanded canvas (or original canvas if no expansion)'s w/h
106        rw = s->w;
107        rh = s->h;
108
109        // check the pixel format, since it could depend on the file format:
110        GLenum internal_format;
111        GLenum img_format, img_type;
112        switch (s->format->BitsPerPixel) {
113                case 32: img_format = GL_RGBA; img_type = GL_UNSIGNED_BYTE;
114                        internal_format = GL_RGBA8; break;
115                case 24: img_format = GL_RGB; img_type = GL_UNSIGNED_BYTE;
116                        internal_format = GL_RGB8; break;
117                case 16: img_format = GL_RGBA; img_type = GL_UNSIGNED_SHORT;
118                        internal_format = GL_RGB5_A1; break;
119                default: img_format = GL_LUMINANCE; img_type = GL_UNSIGNED_BYTE;
120                        internal_format=GL_LUMINANCE8; break;
121        }
122
123        // generate the texture
124        glGenTextures( 1, &image );
125
126        // use the bitmap data stored in the SDL_Surface
127        glBindTexture( GL_TEXTURE_2D, (unsigned int)image );
128
129        // these settings depend entirely on how you intend to use the texture!
130        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
131        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
132
133        // turn on linear filtering
134        // upload the texture data, letting OpenGL do any required conversion.
135        glTexImage2D( GL_TEXTURE_2D, 0, internal_format, w, h, 0, img_format, img_type, s->pixels );
136
137        return( true );
138}
139
140SDL_Surface *Image2::ExpandCanvas( SDL_Surface *s, int w, int h ) {
141        SDL_Surface *expanded = NULL;
142        SDL_Surface *original = s;
143       
144        // create the expanded surface
145        expanded = SDL_CreateRGBSurface(original->flags, w, h, original->format->BitsPerPixel,
146                                        original->format->Rmask, original->format->Gmask, original->format->Bmask,
147                                        original->format->Amask);
148        assert( expanded );
149
150        // make sure alpha values are copied properly
151        SDL_SetAlpha( original, 0, SDL_ALPHA_OPAQUE );
152
153        // copy the old image to the upper-left corner of the expanded canvas
154        SDL_Rect area;
155        area.x = 0;
156        area.y = 0;
157        area.w = original->w;
158        area.h = original->h;
159        SDL_BlitSurface( original, &area, expanded, &area );
160       
161        // re-calculate the texture coordinates given to opengl during drawing (u/v coordinates)
162        scale_w = (float)original->w / (float)w;
163        scale_h = (float)original->h / (float)h;
164       
165        // update the callee's pointer to the new image and free the old one
166        SDL_FreeSurface( original );
167       
168        return( expanded );
169}
170
Note: See TracBrowser for help on using the repository browser.