MegaGlest/source/shared_lib/sources/graphics/TGAReader.cpp

158 lines
3.9 KiB
C++

// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2010 Martiño Figueroa and others
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "TGAReader.h"
#include "types.h"
#include "pixmap.h"
#include <stdexcept>
#include <iostream>
#include "leak_dumper.h"
using std::runtime_error;
namespace Shared{ namespace Graphics{
#pragma pack(push, 1)
/**Copied from pixmap.cpp*/
// =====================================================
// Information for reading the targa-file
// =====================================================
struct TargaFileHeader{
int8 idLength;
int8 colourMapType;
int8 dataTypeCode;
int16 colourMapOrigin;
int16 colourMapLength;
int8 colourMapDepth;
int16 xOrigin;
int16 yOrigin;
int16 width;
int16 height;
int8 bitsPerPixel;
int8 imageDescriptor;
};
#pragma pack(pop)
static const int tgaUncompressedRgb= 2;
static const int tgaUncompressedBw= 3;
// =====================================================
// class TGAReader
// =====================================================
/**Get Extension array, initialised*/
//static inline const string* getExtensionStrings() {
static inline std::vector<string> getExtensionStrings() {
//static const string extensions[] = {"tga", ""};
static std::vector<string> extensions;
if(extensions.size() == 0) {
extensions.push_back("tga");
}
return extensions;
}
TGAReader::TGAReader(): FileReader<Pixmap2D>(getExtensionStrings()) {}
Pixmap2D* TGAReader::read(ifstream& in, const string& path, Pixmap2D* ret) const {
//read header
TargaFileHeader fileHeader;
in.read((char*)&fileHeader, sizeof(TargaFileHeader));
if (!in.good()) {
throw runtime_error(path + " could not be read");
}
//check that we can load this tga file
if(fileHeader.idLength!=0){
throw runtime_error(path + ": id field is not 0");
}
if(fileHeader.dataTypeCode!=tgaUncompressedRgb && fileHeader.dataTypeCode!=tgaUncompressedBw){
throw runtime_error(path + ": only uncompressed BW and RGB targa images are supported");
}
//check bits per pixel
if(fileHeader.bitsPerPixel!=8 && fileHeader.bitsPerPixel!=24 && fileHeader.bitsPerPixel!=32){
throw runtime_error(path + ": only 8, 24 and 32 bit targa images are supported");
}
const int h = fileHeader.height;
const int w = fileHeader.width;
const int fileComponents= fileHeader.bitsPerPixel/8;
const int picComponents = (ret->getComponents()==-1)?fileComponents:ret->getComponents();
//std::cout << "TGA-Components: Pic: " << picComponents << " old: " << (ret->getComponents()) << " File: " << fileComponents << std::endl;
ret->init(w,h,picComponents);
uint8* pixels = ret->getPixels();
//read file
for(int i=0; i<h*w*picComponents; i+=picComponents){
uint8 r, g, b, a, l;
if(fileComponents==1){
in.read((char*)&l,1);
r= l;
g= l;
b= l;
a= 255;
}
else{
in.read((char*)&b, 1);
in.read((char*)&g, 1);
in.read((char*)&r, 1);
if(fileComponents==4){
in.read((char*)&a, 1);
} else {
a= 255;
}
l= (r+g+b)/3;
}
if (!in.good()) {
return NULL;
}
switch(picComponents){
case 1:
pixels[i]= l;
break;
case 3:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
break;
case 4:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
pixels[i+3]= a;
break;
}
}
/*for(int i = 0; i < w*h*picComponents; ++i) {
if (i%39 == 0) std::cout << std::endl;
int first = pixels[i]/16;
if (first < 10)
std:: cout << first;
else
std::cout << (char)('A'+(first-10));
first = pixels[i]%16;
if (first < 10)
std:: cout << first;
else
std::cout << (char)('A'+(first-10));
std::cout << " ";
}*/
return ret;
}
}} //end namespace