1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 2001  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library 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 GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21      $Id: ssgLoadPCX.cxx 1963 2004-09-26 09:27:28Z bram $
22 */
23 
24 //===========================================================================
25 //
26 // File: ssgLoadPCX.cxx
27 //
28 // Created: 12.12.2003
29 //
30 // Author: Wolfram Kuss
31 //
32 // Revision: $Id: ssgLoadPCX.cxx 1963 2004-09-26 09:27:28Z bram $
33 //
34 // Description: Loads PCX texture files. Only 8 bit indexed for now.
35 //
36 //
37 //===========================================================================
38 
39 #include "ssgLocal.h"
40 typedef unsigned char UByte,*UByteP;
41 #include "pcx.h"
42 
43 
44 #ifdef SSG_LOAD_PCX_SUPPORTED
45 
ReadFileIntoBuffer(const char * fname,UByte * & buffer,UByte * & bufferorig,unsigned long & file_length)46 int ReadFileIntoBuffer(const char *fname, UByte *&buffer, UByte *&bufferorig, unsigned long &file_length)
47 // Opens the file, allocates buffer of correct size to hold the file, reads it, closes it
48 {
49   // **** open file ****
50   FILE *tfile;
51   if ( (tfile = fopen(fname, "rb")) == NULL) {
52     ulSetError( UL_WARNING, "ssgLoadTexture: Failed to open file '%s' for reading.", fname );
53     return false ;
54   }
55 
56   // **** allocate buffer, read file into it and close file ****
57   fseek(tfile, 0, SEEK_END);
58   file_length = ftell(tfile);
59   fseek(tfile, 0, SEEK_SET);
60 
61   buffer = new UByte[file_length];
62   bufferorig = buffer;
63 
64   fread(buffer, file_length, 1, tfile);
65   fclose(tfile);
66   return true;
67 }
68 
ssgLoadPCX(const char * fname,ssgTextureInfo * info)69 bool ssgLoadPCX ( const char *fname, ssgTextureInfo* info )
70 {
71   UByte *buffer, *bufferorig;
72   unsigned long file_length;
73   if(!ReadFileIntoBuffer(fname, buffer, bufferorig, file_length))
74     return false ;
75   // **** "read" header and "analyse" it ****
76   pcxHeaderType *ppcxHeader = (pcxHeaderType *) buffer;
77   buffer += sizeof(pcxHeaderType);
78 
79   short width = ppcxHeader->xmax-ppcxHeader->x+1;
80   short height = ppcxHeader->ymax-ppcxHeader->y+1;
81   //p->isMasked = ((p->resOfRowanTexture & 0x200) != 0) ? 1 : 0;
82 
83   if ( info != NULL )
84   {
85     info -> width = width ;
86     info -> height = height ;
87     info -> depth = 4 ;
88     info -> alpha = TRUE ;  //I think we have to set it to true always, since we always generate 4 bytes per pixel
89   }
90 
91   // **** read body�; Do error checking ****
92   long size = ((long)width)*height;
93   UByte *pAlfa = NULL, * pBody = new UByte [size]; // 1 byte per texel
94   UByte * pBodyorig = pBody;
95 
96   if(!ReadPCXBody(buffer, ppcxHeader, pBody))
97 // writes to pBody, which must have been allocated
98   {
99     delete [] buffer;
100     delete [] pBody;
101     ulSetError ( UL_WARNING,
102       "ssgLoadTexture: '%s' - unsupported or broken PCX texture file", fname ) ;
103     return false ;
104   }
105   if(*buffer++ != 12)
106   { ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - PCX files needs a '12' byte", fname ) ;
107     return false ;
108   }
109   assert(bufferorig + file_length - 768 == buffer);
110   // starting at "buffer", you can find the palette, 256 entrys with 3 bytes each
111   // only true for version 5 (and possible later versions)=
112 
113 // start alfa handling
114   // PCX does not allow alfa, so to enable alfa, you need two files :-(,
115   // one for the body, for example abc.pcx and one for the alfa component, for example abc_trans.pcx
116   if(fname[strlen(fname)-4]=='.')
117   {
118     char *t, *s = new char[strlen(fname)+15];
119     strcpy(s, fname);
120     t=&(s[strlen(s)-4]);
121     strcpy(t, "_trans.pcx");
122     if(ulFileExists(s))
123     {
124       UByte *alfaBuffer, *alfaBufferorig;
125       if(!ReadFileIntoBuffer(s, alfaBuffer, alfaBufferorig, file_length))
126         return false ;
127       // **** "read" header and "analyse" it ****
128       ppcxHeader = (pcxHeaderType *) alfaBuffer;
129       alfaBuffer += sizeof(pcxHeaderType);
130 
131       if(width != ppcxHeader->xmax-ppcxHeader->x+1)
132         ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - Width does not agree to 'body' width, so alfa is ignored", s ) ;
133       else
134       {
135 
136         if (height != ppcxHeader->ymax-ppcxHeader->y+1)
137           ulSetError ( UL_WARNING, "ssgLoadTexture: '%s' - Height does not agree to 'body' height, so alfa is ignored", s ) ;
138         else
139         {
140           // **** read body�; Do error checking ****
141           pAlfa = new UByte [size]; // 1 byte per texel
142 
143           if(!ReadPCXBody(alfaBuffer, ppcxHeader, pAlfa))
144           // writes to pBody, which must have been allocated
145           {
146             delete [] buffer;
147             delete [] pAlfa;
148             ulSetError ( UL_WARNING,
149               "ssgLoadTexture: '%s' - unsupported or broken PCX texture file", fname ) ;
150             return false ;
151           }
152         }
153       }
154     }
155   }
156 // end alfa handling
157 
158   UByte *texels = new UByte [size * 4]; // 4 bytes per texel
159   int c = 0;
160   int iRunningIndex = 0;
161   for (int y = 0; y < height; y++) {
162     for (int x = 0; x < width; x++) {
163       UByte a = pAlfa?pAlfa[iRunningIndex]:255;
164       UByte b = pBody[iRunningIndex++];
165       texels[c++] = buffer[b*3    ];
166       texels[c++] = buffer[b*3 + 1];
167       texels[c++] = buffer[b*3 + 2];
168       texels[c++] = a;
169     }
170   }
171 
172   delete [] pBodyorig;
173   delete [] bufferorig;
174   if (pAlfa)
175     delete [] pAlfa;
176   return ssgMakeMipMaps ( texels, width, height, 4 ) ;
177 }
178 #else
179 
ssgLoadPCX(const char * fname,ssgTextureInfo * info)180 bool ssgLoadPCX ( const char *fname, ssgTextureInfo* info )
181 {
182   ulSetError ( UL_WARNING,
183     "ssgLoadTexture: '%s' - PCX texture support not configured", fname ) ;
184   return false ;
185 }
186 
187 #endif
188 
189