00001 /* 00002 * Copyright (C) 2002 Ryan Nunn and The Pentagram Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #include "pent_include.h" 00020 #include "TextureBitmap.h" 00021 #include "IDataSource.h" 00022 00023 // graphics defines 00024 #define BITMAP_ID 0x4D42 // universal id for a bitmap 00025 00026 // 00027 // Bitmap Header 00028 // 00029 struct BMPHeader { 00030 uint16 bfType; 00031 uint32 bfSize; 00032 uint16 bfReserved1; 00033 uint16 bfReserved2; 00034 uint32 bfOffBits; 00035 00036 void Read(IDataSource *ds) { 00037 bfType = ds->read2(); 00038 bfSize = ds->read4(); 00039 bfReserved1 = ds->read2(); 00040 bfReserved2 = ds->read2(); 00041 bfOffBits = ds->read4(); 00042 } 00043 }; 00044 00045 // 00046 // Bitmap Info Header 00047 // 00048 struct BMPInfoHeader { 00049 uint32 biSize; 00050 sint32 biWidth; 00051 sint32 biHeight; 00052 uint16 biPlanes; 00053 uint16 biBitCount; 00054 uint32 biCompression; 00055 uint32 biSizeImage; 00056 sint32 biXPelsPerMeter; 00057 sint32 biYPelsPerMeter; 00058 uint32 biClrUsed; 00059 uint32 biClrImportant; 00060 00061 void Read(IDataSource *ds) { 00062 biSize = ds->read4(); 00063 biWidth = ds->read4(); 00064 biHeight = ds->read4(); 00065 biPlanes = ds->read2(); 00066 biBitCount = ds->read2(); 00067 biCompression = ds->read4(); 00068 biSizeImage = ds->read4(); 00069 biXPelsPerMeter = ds->read4(); 00070 biYPelsPerMeter = ds->read4(); 00071 biClrUsed = ds->read4(); 00072 biClrImportant = ds->read4(); 00073 } 00074 }; 00075 00076 00077 // 00078 // Read from a Data Source 00079 // 00080 bool TextureBitmap::Read(IDataSource *ds) 00081 { 00082 // Seek to start 00083 ds->seek(0); 00084 00085 // looping index 00086 int index; 00087 00088 // used to convert images to 32 bit 00089 uint8 *temp_buffer = NULL; 00090 00091 // this contains the bitmapfile header 00092 BMPHeader bitmapfileheader; 00093 00094 // this is all the info including the palette 00095 BMPInfoHeader bitmapinfoheader; 00096 00097 // now load the bitmap file header 00098 bitmapfileheader.Read(ds); 00099 00100 // test if this is a bitmap file, if not return false 00101 if (bitmapfileheader.bfType!=BITMAP_ID) return false; 00102 00103 // now we know this is a bitmap, so read in all the sections 00104 // first the bitmap infoheader 00105 bitmapinfoheader.Read(ds); 00106 00107 // now load the color palette if there is one 00108 uint8 palette[768]; 00109 if (bitmapinfoheader.biBitCount == 8) 00110 { 00111 for (index=0; index < 256; index++) 00112 { 00113 palette[index*3] = ds->read1(); 00114 palette[index*3+1] = ds->read1(); 00115 palette[index*3+2] = ds->read1(); 00116 ds->skip(1); 00117 00118 } 00119 00120 } 00121 00122 // finally the image data itself 00123 ds->seek(ds->getSize()-bitmapinfoheader.biSizeImage); 00124 00125 // allocate temporary buffer 00126 if (0 == (temp_buffer = new uint8 [bitmapinfoheader.biSizeImage])) 00127 return false; 00128 00129 // allocate final 32 bit storage buffer 00130 if (0 == (buffer=new uint32[bitmapinfoheader.biWidth * bitmapinfoheader.biHeight])) 00131 { 00132 // release working buffer 00133 delete [] temp_buffer; 00134 00135 // return error 00136 return false; 00137 } // end if 00138 00139 // now read it in 00140 ds->read(static_cast<uint8 *>(temp_buffer),bitmapinfoheader.biSizeImage); 00141 00142 // 8 Bit Palette 00143 if (bitmapinfoheader.biBitCount == 8) { 00144 for (index=0; index<bitmapinfoheader.biWidth*bitmapinfoheader.biHeight; index++) 00145 { 00146 // extract RGB components (in BGR order), note the scaling 00147 uint8 palindex = temp_buffer[index]; 00148 00149 int row = index / bitmapinfoheader.biWidth; 00150 int write = index % bitmapinfoheader.biWidth; 00151 write += (bitmapinfoheader.biHeight-1-row) * bitmapinfoheader.biWidth; 00152 00153 buffer[write] = (palette[palindex*3 + TEX32_B_SHIFT]) 00154 | (palette[palindex*3 + 1] << TEX32_G_SHIFT) 00155 | (palette[palindex*3 + 2] << TEX32_R_SHIFT) 00156 | (255 << TEX32_A_SHIFT); 00157 00158 } // end for index 00159 } 00160 // 16 Bit High Colour 00161 else if (bitmapinfoheader.biBitCount == 16) { 00162 // Colour shifting values 00163 #define UNPACK_BMP16(pix,r,g,b) { r = static_cast<uint8>((((pix)&31)>>10)<<5); g = static_cast<uint8>((((pix)&31)>>5)<<5); b = static_cast<uint8>(((pix)&31)<<5); } 00164 00165 for (index=0; index<bitmapinfoheader.biWidth*bitmapinfoheader.biHeight; index++) 00166 { 00167 // extract RGB components, and pack them into an int 00168 uint8 red, green, blue ; 00169 uint16 color = temp_buffer[index*2 + 0] | (temp_buffer[index*2 + 1]<<8); 00170 UNPACK_BMP16(color,red,green,blue); 00171 00172 int row = index / bitmapinfoheader.biWidth; 00173 int write = index % bitmapinfoheader.biWidth; 00174 write += (bitmapinfoheader.biHeight-1-row) * bitmapinfoheader.biWidth; 00175 00176 00177 buffer[write] = (blue << TEX32_B_SHIFT) 00178 | (green << TEX32_G_SHIFT) 00179 | (red << TEX32_R_SHIFT) 00180 | (255 << TEX32_A_SHIFT); 00181 } 00182 } 00183 // 24 Bit True Colour 00184 else if (bitmapinfoheader.biBitCount == 24) { 00185 for (index=0; index<bitmapinfoheader.biWidth*bitmapinfoheader.biHeight; index++) 00186 { 00187 int row = index / bitmapinfoheader.biWidth; 00188 int write = index % bitmapinfoheader.biWidth; 00189 write += (bitmapinfoheader.biHeight-1-row) * bitmapinfoheader.biWidth; 00190 00191 // extract RGB components, and pack them into an int 00192 buffer[write] = (temp_buffer[index*3 + 0] << TEX32_B_SHIFT) 00193 | (temp_buffer[index*3 + 1] << TEX32_G_SHIFT) 00194 | (temp_buffer[index*3 + 2] << TEX32_R_SHIFT) 00195 | (255 << TEX32_A_SHIFT); 00196 00197 } 00198 } 00199 00200 // Make sure the width and height are correctly copied 00201 width = bitmapinfoheader.biWidth; 00202 height = bitmapinfoheader.biHeight; 00203 format = TEX_FMT_STANDARD; 00204 00205 // Calc texture log2's 00206 CalcLOG2s(); 00207 00208 // return success 00209 return true; 00210 00211 }