diff --git a/dffwrite.cpp b/dffwrite.cpp index 80cca3e..39074cf 100644 --- a/dffwrite.cpp +++ b/dffwrite.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -25,10 +26,15 @@ main(int argc, char *argv[]) ifstream in(argv[1], ios::binary); Rw::FindChunk(in, Rw::ID_CLUMP, NULL, NULL); c = Rw::Clump::streamRead(in); + assert(c != NULL); in.close(); - for(Rw::int32 i = 0; i < c->numAtomics; i++) - Rw::Gl::Instance(c->atomicList[i]); + Rw::Image *tga = Rw::readTGA("b.tga"); + assert(tga != NULL); + Rw::writeTGA(tga, "out.tga"); + +// for(Rw::int32 i = 0; i < c->numAtomics; i++) +// Rw::Gl::Instance(c->atomicList[i]); ofstream out(argv[2], ios::binary); c->streamWrite(out); diff --git a/src/image.cpp b/src/image.cpp index 3f6a94b..31c4457 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -10,6 +10,8 @@ #include "rwplugin.h" #include "rwobjects.h" +using namespace std; + namespace Rw { Image::Image(int32 width, int32 height, int32 depth) @@ -32,13 +34,13 @@ void Image::allocate(void) { if(this->pixels == NULL){ - this->pixels = new uint8[this->width*this->height* - (this->depth==4) ? 1 : this->depth/8]; + this->stride = this->width*(this->depth==4 ? 1 : this->depth/8); + this->pixels = new uint8[this->stride*this->height]; this->flags |= 1; } if(this->palette == NULL){ if(this->depth == 4 || this->depth == 8) - this->palette = new uint8[this->depth == 4 ? 16 : 256]; + this->palette = new uint8[(this->depth==4? 16 : 256)*4]; this->flags |= 2; } } @@ -66,4 +68,145 @@ Image::setPalette(uint8 *palette) this->flags |= 2; } +// +// TGA I/O +// + +#pragma pack(push) +#pragma pack(1) +struct TGAHeader +{ + int8 IDlen; + int8 colorMapType; + int8 imageType; + int16 colorMapOrigin; + int16 colorMapLength; + int8 colorMapDepth; + int16 xOrigin, yOrigin; + int16 width, height; + uint8 depth; + uint8 descriptor; +}; +#pragma pack(push) + +Image* +readTGA(const char *filename) +{ + TGAHeader header; + Image *image; + int depth = 0, palDepth = 0; + // TODO: open from image path + ifstream file(filename, ios::binary); + file.read((char*)&header, sizeof(header)); + + assert(header.imageType == 1 || header.imageType == 2); + file.seekg(header.IDlen, ios::cur); + if(header.colorMapType){ + assert(header.colorMapOrigin == 0); + depth = (header.colorMapLength <= 16) ? 4 : 8; + palDepth = header.colorMapDepth; + assert(palDepth == 24 || palDepth == 32); + }else{ + depth = header.depth; + assert(depth == 24 || depth == 32); + } + + image = new Image(header.width, header.height, depth); + image->allocate(); + uint8 *palette = header.colorMapType ? image->palette : NULL; + uint8 (*color)[4] = NULL; + if(palette){ + int maxlen = depth == 4 ? 16 : 256; + color = (uint8(*)[4])palette; + int i; + for(i = 0; i < header.colorMapLength; i++){ + color[i][2] = readUInt8(file); + color[i][1] = readUInt8(file); + color[i][0] = readUInt8(file); + color[i][3] = 0xFF; + if(palDepth == 32) + color[i][3] = readUInt8(file); + } + for(; i < maxlen; i++){ + color[i][0] = color[i][1] = color[i][2] = 0; + color[i][3] = 0xFF; + } + } + + uint8 *pixels = image->pixels; + if(!(header.descriptor & 0x20)) + pixels += (image->height-1)*image->stride; + for(int y = 0; y < image->height; y++){ + uint8 *line = pixels; + for(int x = 0; x < image->width; x++){ + if(palette) + *line++ = readUInt8(file); + else{ + line[2] = readUInt8(file); + line[1] = readUInt8(file); + line[0] = readUInt8(file); + line += 3; + if(depth == 32) + *line++ = readUInt8(file); + } + } + pixels += (header.descriptor&0x20) ? + image->stride : -image->stride; + } + + file.close(); + return image; +} + +void +writeTGA(Image *image, const char *filename) +{ + TGAHeader header; + // TODO: open from image path + ofstream file(filename, ios::binary); + header.IDlen = 0; + header.imageType = image->palette != NULL ? 1 : 2; + header.colorMapType = image->palette != NULL; + header.colorMapOrigin = 0; + header.colorMapLength = image->depth == 4 ? 16 : + image->depth == 8 ? 256 : 0; + header.colorMapDepth = image->palette ? 32 : 0; + header.xOrigin = 0; + header.yOrigin = 0; + header.width = image->width; + header.height = image->height; + header.depth = image->depth == 4 ? 8 : image->depth; + header.descriptor = 0x20 | (image->depth == 32 ? 8 : 0); + file.write((char*)&header, sizeof(header)); + + uint8 *pixels = image->pixels; + uint8 *palette = header.colorMapType ? image->palette : NULL; + uint8 (*color)[4] = (uint8(*)[4])palette;; + if(palette) + for(int i = 0; i < header.colorMapLength; i++){ + writeUInt8(color[i][2], file); + writeUInt8(color[i][1], file); + writeUInt8(color[i][0], file); + writeUInt8(color[i][3], file); + } + + for(int y = 0; y < image->height; y++){ + uint8 *line = pixels; + for(int x = 0; x < image->width; x++){ + if(palette) + writeUInt8(*line++, file); + else{ + writeUInt8(line[2], file); + writeUInt8(line[1], file); + writeUInt8(line[0], file); + line += 3; + if(image->depth == 32) + writeUInt8(*line++, file); + } + } + pixels += image->stride; + } + file.close(); +} + } diff --git a/src/rwobjects.h b/src/rwobjects.h index 7e7caa7..d91503e 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -24,6 +24,8 @@ struct Image void setPixels(uint8 *pixels); void setPalette(uint8 *palette); }; +Image *readTGA(const char *filename); +void writeTGA(Image *image, const char *filename); // TODO: raster, link into texdict struct Texture : PluginBase