00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #ifdef __hpux // prevent int32 clash (model.h/tiff.h)
00043 #define _INT32
00044 #endif
00045
00046 #include <stdlib.h>
00047 #include <stdio.h>
00048
00049 #include "OSGConfig.h"
00050 #include "OSGBaseFunctions.h"
00051
00052 #include "OSGTGAImageFileType.h"
00053
00054 #ifdef OSG_WITH_TGA
00055 #include <tiffio.h>
00056 #endif
00057 #include <OSGLog.h>
00058
00059
00060 OSG_USING_NAMESPACE
00061
00062
00075
00076 static const Char8 *suffixArray[] = {
00077 "tga"
00078 };
00079
00080
00084 TGAImageFileType& TGAImageFileType::the (void)
00085 {
00086 return _the;
00087 }
00088
00089 void TGAImageFileType::readHeader(std::istream &in, TGAHeader &header)
00090 {
00091 UInt8 dum[18];
00092
00093 in.read(reinterpret_cast<char *>(dum), 18);
00094
00095 header.idLength = dum[ 0];
00096 header.colorMapType = dum[ 1];
00097 header.imageType = dum[ 2];
00098 header.cmapEntrySize = dum[ 7];
00099 header.depth = dum[16];
00100 header.descriptor = dum[17];
00101
00102 if(osgIsBigEndian())
00103 {
00104 header.cmapFirst = dum[ 4] + dum[ 3] * 256;
00105 header.cmapLength = dum[ 6] + dum[ 5] * 256;
00106 header.xOrigin = dum[ 9] + dum[ 8] * 256;
00107 header.yOrigin = dum[11] + dum[10] * 256;
00108 header.width = dum[13] + dum[12] * 256;
00109 header.height = dum[15] + dum[14] * 256;
00110 }
00111 else
00112 {
00113 header.cmapFirst = dum[ 3] + dum[ 4] * 256;
00114 header.cmapLength = dum[ 5] + dum[ 6] * 256;
00115 header.xOrigin = dum[ 8] + dum[ 9] * 256;
00116 header.yOrigin = dum[10] + dum[11] * 256;
00117 header.width = dum[12] + dum[13] * 256;
00118 header.height = dum[14] + dum[15] * 256;
00119 }
00120 }
00121
00122 bool TGAImageFileType::readCompressedImageData(std::istream &in, ImagePtr &image)
00123 {
00124 UInt32 npix = image->getWidth() * image->getHeight();
00125 UInt8 rep;
00126 UChar8 *data = image->getData();
00127 UInt16 bpp = image->getBpp();
00128 UChar8 r,g,b,a;
00129
00130 while(npix)
00131 {
00132 in.read(reinterpret_cast<char *>(&rep), 1);
00133
00134 if(rep & 0x80)
00135 {
00136 rep = (rep & 0x7f) + 1;
00137 npix -= rep;
00138
00139 switch(image->getPixelFormat())
00140 {
00141 case Image::OSG_L_PF:
00142 in.read(reinterpret_cast<char *>(&a), 1);
00143 while(rep--)
00144 {
00145 *data++ = a;
00146 }
00147 break;
00148 case Image::OSG_RGB_PF:
00149 in.read(reinterpret_cast<char *>(&b), 1);
00150 in.read(reinterpret_cast<char *>(&g), 1);
00151 in.read(reinterpret_cast<char *>(&r), 1);
00152 while(rep--)
00153 {
00154 *data++ = b;
00155 *data++ = g;
00156 *data++ = r;
00157 }
00158 break;
00159 case Image::OSG_RGBA_PF:
00160 in.read(reinterpret_cast<char *>(&b), 1);
00161 in.read(reinterpret_cast<char *>(&g), 1);
00162 in.read(reinterpret_cast<char *>(&r), 1);
00163 in.read(reinterpret_cast<char *>(&a), 1);
00164 while(rep--)
00165 {
00166 *data++ = b;
00167 *data++ = g;
00168 *data++ = r;
00169 *data++ = a;
00170 }
00171 break;
00172 default:
00173 FWARNING(("TGA: unknown pixel "
00174 "format!?!\n"));
00175 return false;
00176 }
00177 }
00178 else
00179 {
00180 rep = (rep & 0x7f) + 1;
00181 in.read(reinterpret_cast<char *>(data), bpp * rep);
00182 data += rep * bpp;
00183 npix -= rep;
00184 }
00185 }
00186 return true;
00187 }
00188
00189
00190 TGAImageFileType TGAImageFileType::_the("tga",
00191 suffixArray, sizeof(suffixArray));
00192
00193
00194
00199 bool TGAImageFileType::read( ImagePtr &image,
00200 const Char8 *fileName)
00201 {
00202 std::ifstream in(fileName, std::ios::in | std::ios::binary);
00203
00204 if(! in.rdbuf()->is_open())
00205 {
00206 FWARNING(("Error opening TGA file %s!\n", fileName));
00207 return false;
00208 }
00209
00210 TGAHeader header;
00211 readHeader(in, header);
00212
00213 Image::PixelFormat format = Image::OSG_INVALID_PF;
00214
00215 bool compressed = (header.imageType & 0x8) != 0;
00216
00217 switch(header.imageType & ~0x8)
00218 {
00219 case 1: FWARNING(("TGA: 8-bit image not supported!\n"));
00220 break;
00221
00222 case 2: switch(header.depth)
00223 {
00224 case 24: format = Image::OSG_RGB_PF;
00225 break;
00226 case 32: format = Image::OSG_RGBA_PF;
00227 break;
00228 default: FWARNING(("TGA: Unknown pixel depth %d!\n",
00229 header.depth));
00230 break;
00231 }
00232 break;
00233
00234 case 3: format = Image::OSG_L_PF;
00235 break;
00236 }
00237
00238 if(format == Image::OSG_INVALID_PF)
00239 {
00240 FWARNING(("Unsupported image type for TGA file %s!\n", fileName));
00241 return false;
00242 }
00243
00244 image->set(format, header.width, header.height);
00245
00246
00247 UInt8 imageid[256];
00248 in.read(reinterpret_cast<char *>(imageid), header.idLength);
00249 imageid[header.idLength] = 0;
00250
00251 FDEBUG(("TGA: Image ID '%s'\n", imageid));
00252
00253
00254 if(header.colorMapType == 1)
00255 {
00256 UInt32 len = osgMin(header.cmapEntrySize / 3, 8) * header.cmapLength;
00257
00258 UInt8 * dum = new UInt8 [len];
00259
00260 in.read(reinterpret_cast<char *>(dum), len);
00261
00262 delete [] dum;
00263 }
00264
00265
00266 if(compressed)
00267 {
00268 if(!readCompressedImageData(in, image))
00269 {
00270 FWARNING(("Unsupported image type for TGA file %s!\n", fileName));
00271 return false;
00272 }
00273 }
00274 else
00275 {
00276 in.read(reinterpret_cast<char *>(image->getData()),
00277 static_cast<int>(image->getSize()));
00278 }
00279
00280
00281 switch(header.descriptor & 0x30)
00282 {
00283 case 0x00:
00284 break;
00285 case 0x10:
00286 case 0x20:
00287 case 0x30:
00288 FWARNING(("TGA: origin 0x%d not supported!\n",
00289 header.descriptor & 0x30));
00290 return false;
00291 }
00292
00293
00294 if(image->getPixelFormat() == Image::OSG_RGB_PF ||
00295 image->getPixelFormat() == Image::OSG_RGBA_PF)
00296 {
00297 UChar8 *d = image->getData(), dum;
00298 UInt32 npix = image->getWidth() * image->getHeight();
00299 UInt8 bpp = image->getBpp();
00300
00301 while(npix--)
00302 {
00303 dum = d[2];
00304 d[2] = d[0];
00305 d[0] = dum;
00306 d += bpp;
00307 }
00308 }
00309
00310 return true;
00311 }
00312
00313
00318 bool TGAImageFileType::write(const ImagePtr &,
00319 const Char8 *OSG_CHECK_ARG(fileName))
00320 {
00321 SWARNING <<
00322 getMimeType() <<
00323 " write is not compiled into the current binary " <<
00324 std::endl;
00325
00326 return true;
00327 }
00328
00329
00333 TGAImageFileType::TGAImageFileType(const Char8 *mimeType,
00334 const Char8 *suffixArray[],
00335 UInt16 suffixByteCount) :
00336 ImageFileType(mimeType,suffixArray, suffixByteCount)
00337 {
00338 return;
00339 }
00340
00341
00345 TGAImageFileType::TGAImageFileType(const TGAImageFileType &obj) :
00346 ImageFileType(obj)
00347 {
00348 return;
00349 }
00350
00351
00355 TGAImageFileType::~TGAImageFileType(void)
00356 {
00357 return;
00358 }