1 /* $Id: LoadImage.cpp,v 1.6 2002/12/24 14:56:15 nan Exp $ */
2 
3 // Copyright (C) 2000, 2002  $B?@Fn(B $B5H9((B(Kanna Yoshihiro)
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 #include "ttinc.h"
20 #include "LoadImage.h"
21 
22 #ifdef HAVE_LIBZ
23 #include "z.h"
24 #endif
25 
ImageData()26 ImageData::ImageData() {
27   m_image = NULL;
28   m_width = m_height = m_bytes = 0;
29 }
30 
ImageData(long width,long height,long bytes)31 ImageData::ImageData( long width, long height, long bytes) {
32   m_image = new GLubyte[width*height*bytes];
33 
34   if ( m_image ) {
35     m_width = width;
36     m_height = height;
37     m_bytes = bytes;
38   }
39 }
40 
~ImageData()41 ImageData::~ImageData() {
42   if ( m_image )
43     delete m_image;
44 }
45 
46 GLubyte
GetPixel(long width,long height,long bytes)47 ImageData::GetPixel( long width, long height, long bytes ) {
48   if ( width > m_width || width < 0 || height > m_height || height < 0 ||
49        bytes > m_bytes || bytes < 0 )
50     return 0;
51 
52   return m_image[height*m_width*m_bytes + width*m_bytes + bytes];
53 }
54 
55 bool
SetPixel(long width,long height,long bytes,GLubyte val)56 ImageData::SetPixel( long width, long height, long bytes , GLubyte val ) {
57   if ( width > m_width || width < 0 || height > m_height || height < 0 ||
58        bytes > m_bytes || bytes < 0 )
59     return false;
60 
61   m_image[height*m_width*m_bytes + width*m_bytes + bytes] = val;
62   return true;
63 }
64 
65 bool
LoadPPM(const char * filename)66 ImageData::LoadPPM(const char* filename ) {
67   int i, j;
68 #ifndef HAVE_LIBZ
69   FILE *fp;
70 #else
71   gzFile fp;
72 #endif
73   char *w;
74   int pb;
75 
76 #ifndef HAVE_LIBZ
77   if( (fp = fopen(filename, "r")) == NULL ) {
78     return false;
79   }
80 #else
81   if (NULL == (fp = gzopenx(filename, "rs"))) return false;
82 #endif
83 
84   w = getWord(fp);
85   if( !strcmp("P3", w) )
86     pb = 3;
87   else if( !strcmp("P2", w) )
88     pb = 2;
89   else if( !strcmp("P4", w) )
90     pb = 4;
91   else if ( !strcmp("P5", w) )
92     pb = 5;
93   else if ( !strcmp("P6", w) )
94     pb = 6;
95   else
96     return false;
97 
98   m_width = atoi( getWord(fp) );
99   m_height = atoi( getWord(fp) );
100   m_bytes = 4;
101 
102   if ( pb != 4 )
103     getWord( fp );
104 
105   if ( m_image )
106     delete m_image;
107 
108   m_image = new GLubyte[m_width*m_height*m_bytes];
109   if ( !m_image ) {
110     m_width = m_height = m_bytes = 0;
111     return false;
112   }
113 
114   if ( pb == 5 ) {
115     GLubyte b;
116     for ( i = 0 ; i < m_height ; i++ ){
117       for ( j = 0 ; j < m_width ; j++ ){
118 #ifndef HAVE_LIBZ
119 	fread( &b , 1, 1, fp );
120 #else
121 	gzread(fp, &b, 1 * 1);
122 #endif
123 	SetPixel( j, i, 0, b );
124 	SetPixel( j, i, 1, b );
125 	SetPixel( j, i, 2, b );
126 	SetPixel( j, i, 3, 255 );
127       }
128     }
129   } else if ( pb == 6 ) {
130     GLubyte b;
131     for ( i = 0 ; i < m_height ; i++ ){
132       for ( j = 0 ; j < m_width ; j++ ){
133 #ifndef HAVE_LIBZ
134 	fread( &b , 1, 1, fp ); SetPixel( j, i, 0, b );
135 	fread( &b , 1, 1, fp ); SetPixel( j, i, 1, b );
136 	fread( &b , 1, 1, fp ); SetPixel( j, i, 2, b );
137 #else
138 	gzread(fp, &b , 1 * 1); SetPixel( j, i, 0, b );
139 	gzread(fp, &b , 1 * 1); SetPixel( j, i, 1, b );
140 	gzread(fp, &b , 1 * 1); SetPixel( j, i, 2, b );
141 #endif
142 	SetPixel( j, i, 3, 255 );
143       }
144     }
145   } else if ( pb == 4 ) {
146     int rowbytes = m_width/8;
147     if ( m_width%8 > 0 )
148       rowbytes++;
149 
150 #ifndef HAVE_LIBZ
151     fread( m_image, 1, rowbytes*m_height, fp );
152 #else
153     gzread( fp, m_image, rowbytes*m_height );
154 #endif
155   } else {
156     for ( i = 0 ; i < m_height ; i++ ){
157       for ( j = 0 ; j < m_width ; j++ ){
158 	if ( pb == 3 ) {
159 	  SetPixel( j, i, 0, (GLubyte)atoi(getWord( fp ) ) );
160 	  SetPixel( j, i, 1, (GLubyte)atoi(getWord( fp ) ) );
161 	  SetPixel( j, i, 2, (GLubyte)atoi(getWord( fp ) ) );
162 	  SetPixel( j, i, 3, 255 );
163 	} else if ( pb == 2 ) {
164 	  SetPixel( j, i, 0, (GLubyte)atoi(getWord( fp ) ) );
165 	  SetPixel( j, i, 1, (GLubyte)atoi(getWord( fp ) ) );
166 	  SetPixel( j, i, 2, (GLubyte)atoi(getWord( fp ) ) );
167 	  SetPixel( j, i, 3, (GLubyte)atoi(getWord( fp ) ) );
168 	}
169       }
170     }
171   }
172 
173 #ifndef HAVE_LIBZ
174   fclose( fp );
175 #else
176   gzclose(fp);
177 #endif
178 
179   return true;
180 }
181 
182 #ifdef HAVE_LIBZ
183 char*
getWord(gzFile fp)184 getWord( gzFile fp ) {
185   static char buf[256];
186   static char* ptr = buf;
187   char* ptr2;
188 
189   while(1) {
190     if( *ptr == 0 || *ptr == '#' ) {
191       gzgets(fp, buf, 256);
192       ptr = buf;
193       continue;
194     } else if( isspace(*ptr) ) {
195       ptr++;
196       continue;
197     } else
198       break;
199   }
200 
201   ptr2 = ptr;
202   while( !isspace(*ptr) && *ptr != 0 ) {
203     ptr++;
204   }
205   *ptr = 0;
206   ptr++;
207 
208   return ptr2;
209 }
210 #else
211 char*
getWord(FILE * fp)212 getWord( FILE *fp ) {
213   static char buf[256];
214   static char* ptr = buf;
215   char* ptr2;
216 
217   while(1) {
218     if( *ptr == 0 || *ptr == '#' ) {
219       fgets( buf, 256, fp );
220       ptr = buf;
221       continue;
222     } else if( isspace(*ptr) ) {
223       ptr++;
224       continue;
225     } else
226       break;
227   }
228 
229   ptr2 = ptr;
230   while( !isspace(*ptr) && *ptr != 0 ) {
231     ptr++;
232   }
233   *ptr = 0;
234   ptr++;
235 
236   return ptr2;
237 }
238 #endif
239 
LoadJPG(const char * filename)240 bool ImageData::LoadJPG(const char *filename)
241 {
242   SDL_Surface *img = SDL_GL_LoadTexture((char *)filename);
243   m_width = img->w;
244   m_height = img->h;
245   m_bytes = 4;
246 
247   m_image = new GLubyte[m_width*m_height*m_bytes];
248   memcpy( m_image, img->pixels, m_width*m_height*m_bytes );
249 
250   SDL_FreeSurface(img);
251 
252   return true;
253 }
254 
extmatch(const char * filename,const char * ext)255 inline bool extmatch(const char *filename, const char *ext)
256 {
257     int lf = strlen(filename);
258     int le = strlen(ext);
259     return 0 == strcmp(&filename[lf-le], ext);
260 }
261 
LoadFile(const char * filename)262 bool ImageData::LoadFile(const char *filename)
263 {
264     if      (extmatch(filename, ".jpg")) {
265 	return LoadJPG(filename);
266     }
267     else if (extmatch(filename, ".ppm") || extmatch(filename, ".ppm.gz") ||
268 	     extmatch(filename, ".pbm") || extmatch(filename, ".pbm.gz") ) {
269 	return LoadPPM(filename);
270     }
271     else {
272 	return false;
273     }
274 }
275 
276 // Copyed from testgl.c of SDL source code
SDL_GL_LoadTexture(char * filename)277 SDL_Surface* SDL_GL_LoadTexture(char *filename)
278 {
279   GLuint texture;
280   int w, h;
281   SDL_Surface *image, *jpg;
282   SDL_Rect area;
283   Uint32 saved_flags;
284   Uint8  saved_alpha;
285 
286   jpg = IMG_Load( filename );
287   /* Use the surface width and height expanded to powers of 2 */
288 
289   image = SDL_CreateRGBSurface(
290 			       SDL_SWSURFACE,
291 			       jpg->w, jpg->h,
292 			       32,
293 #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
294 			       0x000000FF,
295 			       0x0000FF00,
296 			       0x00FF0000,
297 			       0xFF000000
298 #else
299 			       0xFF000000,
300 			       0x00FF0000,
301 			       0x0000FF00,
302 			       0x000000FF
303 #endif
304 			       );
305   if ( image == NULL ) {
306     return 0;
307   }
308 
309   /* Save the alpha blending attributes */
310   saved_flags = jpg->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
311   saved_alpha = jpg->format->alpha;
312   if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
313     SDL_SetAlpha(jpg, 0, 0);
314   }
315 
316   /* Copy the surface into the GL texture image */
317   area.x = 0;
318   area.y = 0;
319   area.w = jpg->w;
320   area.h = jpg->h;
321   SDL_BlitSurface(jpg, &area, image, &area);
322 
323   /* Restore the alpha blending attributes */
324   if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
325     SDL_SetAlpha(jpg, saved_flags, saved_alpha);
326   }
327 
328   return image;
329 }
330