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 #include <iostream>
00060
00061
00062 OSG_USING_NAMESPACE
00063
00064
00077
00078 static const Char8 *suffixArray[] = {
00079 "tga", "targa"
00080 };
00081
00082
00086 TGAImageFileType& TGAImageFileType::the (void)
00087 {
00088 return _the;
00089 }
00090
00091 bool TGAImageFileType::readHeader(std::istream &is, TGAHeader &header)
00092 {
00093 UInt8 dum[18];
00094 is.read(reinterpret_cast<char *>(dum), 18);
00095 if (is.gcount() != 18)
00096 return false;
00097
00098 header.idLength = dum[ 0];
00099 header.colorMapType = dum[ 1];
00100 header.imageType = dum[ 2];
00101 header.cmapFirst = dum[ 3] | (dum[ 4] << 8);
00102 header.cmapLength = dum[ 5] | (dum[ 6] << 8);
00103 header.cmapEntrySize = dum[ 7];
00104 header.xOrigin = dum[ 8] | (dum[ 9] << 8);
00105 header.yOrigin = dum[10] | (dum[11] << 8);
00106 header.width = dum[12] | (dum[13] << 8);
00107 header.height = dum[14] | (dum[15] << 8);
00108 header.depth = dum[16];
00109 header.descriptor = dum[17];
00110
00111 return true;
00112 }
00113
00114 bool TGAImageFileType::readCompressedImageData(std::istream &is,
00115 ImagePtr &image)
00116 {
00117 UInt32 npix = image->getWidth() * image->getHeight();
00118 Int32 rep, len;
00119 UChar8 *data = image->getData();
00120 UInt16 bpp = image->getBpp();
00121 Char8 c[4];
00122
00123 while (npix > 0)
00124 {
00125 rep = is.get();
00126 if (rep == EOF)
00127 return false;
00128 bool repFlag = (rep & 0x80) != 0;
00129 rep = (rep & 0x7f) + 1;
00130 if (static_cast<UInt32>(rep) > npix)
00131 return false;
00132 npix -= rep;
00133
00134 if (repFlag == true)
00135 {
00136 switch (image->getPixelFormat())
00137 {
00138 case Image::OSG_L_PF:
00139 is.read(c, 1);
00140 if (is.gcount() != 1)
00141 return false;
00142 for (; rep > 0; --rep)
00143 *data++ = c[0];
00144 break;
00145 case Image::OSG_RGB_PF:
00146 is.read(c, 3);
00147 if (is.gcount() != 3)
00148 return false;
00149 for (; rep > 0; --rep)
00150 {
00151 *data++ = c[0];
00152 *data++ = c[1];
00153 *data++ = c[2];
00154 }
00155 break;
00156 case Image::OSG_RGBA_PF:
00157 is.read(c, 4);
00158 if (is.gcount() != 4)
00159 return false;
00160 for (; rep > 0; --rep)
00161 {
00162 *data++ = c[0];
00163 *data++ = c[1];
00164 *data++ = c[2];
00165 *data++ = c[3];
00166 }
00167 break;
00168 default:
00169 FWARNING(("TGA: unknown pixel "
00170 "format!?!\n"));
00171 return false;
00172 }
00173 }
00174 else
00175 {
00176 len = bpp * rep;
00177 is.read(reinterpret_cast<char *>(data), len);
00178 if (is.gcount() != len)
00179 return false;
00180 data += len;
00181 }
00182 }
00183 return true;
00184 }
00185
00186
00187 TGAImageFileType TGAImageFileType::_the("image/x-targa",
00188 suffixArray, sizeof(suffixArray));
00189
00190
00191
00196 bool TGAImageFileType::read(ImagePtr &image, std::istream &is, const std::string &mimetype)
00197 {
00198
00199 TGAHeader header;
00200 if (readHeader(is, header) == false)
00201 return false;
00202
00203
00204 Image::PixelFormat format = Image::OSG_INVALID_PF;
00205 switch (header.imageType & ~0x8)
00206 {
00207 case 1: FWARNING(("TGA: 8-bit image not supported!\n"));
00208 break;
00209
00210 case 2: switch (header.depth)
00211 {
00212 case 24: format = Image::OSG_RGB_PF;
00213 break;
00214 case 32: format = Image::OSG_RGBA_PF;
00215 break;
00216 default: FWARNING(("TGA: Unknown pixel depth %d!\n",
00217 header.depth));
00218 break;
00219 }
00220 break;
00221
00222 case 3: format = Image::OSG_L_PF;
00223 break;
00224 }
00225 if (format == Image::OSG_INVALID_PF)
00226 {
00227 FWARNING(("Unsupported image type for TGA file!\n"));
00228 return false;
00229 }
00230
00231
00232 UInt8 imageid[256];
00233 is.read(reinterpret_cast<char *>(imageid), header.idLength);
00234 if (is.gcount() != header.idLength)
00235 return false;
00236 imageid[header.idLength] = 0;
00237 FDEBUG(("TGA: Image ID '%s'\n", imageid));
00238
00239
00240 if (header.colorMapType == 1)
00241 {
00242 Int32 len = osgMin(header.cmapEntrySize / 3, 8) * header.cmapLength;
00243
00244
00245
00246
00247 is.ignore(len);
00248 if (is.gcount() != len)
00249 return false;
00250 }
00251
00252
00253 image->set(format, header.width, header.height);
00254 if ((header.imageType & 0x8) != 0)
00255 {
00256 if (readCompressedImageData(is, image) == false)
00257 {
00258 FWARNING(("Unsupported image type for TGA file!\n"));
00259 return false;
00260 }
00261 }
00262 else
00263 {
00264 Int32 len = image->getSize();
00265 is.read(reinterpret_cast<char *>(image->getData()), len);
00266 if (is.gcount() != len)
00267 return false;
00268 }
00269
00270
00271 switch (header.descriptor & 0x30)
00272 {
00273 case 0x00:
00274 break;
00275 case 0x20:
00276
00277 {
00278 UInt32 bpl = image->getBpp() * image->getWidth();
00279 UChar8 *t = image->getData(),
00280 *b = t + (image->getHeight() - 1) * bpl,
00281 dum;
00282
00283 for(UInt32 y = image->getHeight() / 2; y > 0; --y)
00284 {
00285 for(UInt32 x = bpl; x > 0; --x, ++t, ++b)
00286 {
00287 dum = *t;
00288 *t = *b;
00289 *b = dum;
00290 }
00291 b -= bpl * 2;
00292 }
00293 }
00294 break;
00295 case 0x10:
00296 case 0x30:
00297 FWARNING(("TGA: origin 0x%d not supported!\n",
00298 header.descriptor & 0x30));
00299 return false;
00300 }
00301
00302
00303 if (image->getPixelFormat() == Image::OSG_RGB_PF ||
00304 image->getPixelFormat() == Image::OSG_RGBA_PF)
00305 {
00306 UChar8 *d = image->getData(), dum;
00307 UInt32 npix = image->getWidth() * image->getHeight();
00308 UInt8 bpp = image->getBpp();
00309
00310 while (npix--)
00311 {
00312 dum = d[2];
00313 d[2] = d[0];
00314 d[0] = dum;
00315 d += bpp;
00316 }
00317 }
00318
00319 return true;
00320 }
00321
00322
00326 TGAImageFileType::TGAImageFileType(const Char8 *mimeType,
00327 const Char8 *suffixArray[],
00328 UInt16 suffixByteCount) :
00329 ImageFileType(mimeType, suffixArray, suffixByteCount)
00330 {}
00331
00332
00336 TGAImageFileType::~TGAImageFileType(void) {}