From 773c1bafe0f1d8b706e0f72e235f8466e7a9ccf5 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Tue, 11 Nov 2008 19:11:57 +0000 Subject: cleanups --- src/render/tga.cc | 367 ------------------------------------------------------ 1 file changed, 367 deletions(-) delete mode 100644 src/render/tga.cc (limited to 'src/render/tga.cc') diff --git a/src/render/tga.cc b/src/render/tga.cc deleted file mode 100644 index a7a2356..0000000 --- a/src/render/tga.cc +++ /dev/null @@ -1,367 +0,0 @@ -/* - render/tga.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -/* - Documentation and examples on the TGA file format: - - http://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf - http://www.fileformat.info/format/tga/egff.htm - http://www.morrowland.com/apron/tut_gl.php - - Notes - - TGA image type Colormap RLE - 0 No image data included in file No No - 1 Colormapped image data Yes No - 2 Truecolor image data No No - 3 Monochrome image data No No - 9 Colormapped image data Yes Yes - 10 Truecolor image data No Yes - 11 Monochrome image data No Yes - - TGA multi-byte integer values have LSB first -*/ - -#include - -#include -#include -#include - -#include "filesystem/filesystem.h" -#include "render/tga.h" -#include "sys/sys.h" - -const unsigned char TGA_NONE = 0; -const unsigned char TGA_TRUECOLOR = 2; -const unsigned char TGA_TRUECOLOR_RLE = 10; - -namespace render -{ - -Image *TGA::load(const char *filename) -{ - Image *image = 0; - - if (!filename) - return 0; - - filesystem::File *tga_file = filesystem::open(filename); - if (!tga_file) { - //con_warn << "Could not open " << filename << std::endl; - return 0; - } - - // TGA header - unsigned char header[18]; - memset(header, 0, sizeof(header)); - - if (!tga_file->read(header, 18)) { - con_warn << "Error reading " << filename << std::endl; - filesystem::close(tga_file); - return 0; - } - - // byte 0 - image ID field length - unsigned int tga_idlength = header[0]; - - // byte 1 - color map type - unsigned int tga_colormap = header[1]; - - // byte 2 - image type - unsigned int tga_type = header[2]; - - // byte 3+4 - color map first entry index - //unsigned int tga_colormap_first = header[3] + (header[4] << 8 ); - - // byte 5+6 - color map length (in bits) - unsigned int tga_color_map_length = header[5] +(header[6] << 8 ); - - // byte 7 - color map entry length - unsigned int tga_colormap_entry = header[7]; - - // byte 8+9 - image x origin - // byte 10+11 - image y origin - // byte 12+13 - image width (LSB first) - unsigned int tga_width = header[12] + (header[13] << 8); - - // byte 14+15 - image height (LSB first) - unsigned int tga_height = header[14] + (header[15] << 8); - - // byte 16 - image color depth (in bits) - unsigned int tga_depth = header[16]; - - // byte 17 - image descriptor byte - unsigned int tga_descriptor = header[17]; - - // read the image id if there is one - if (tga_idlength) - tga_file->skip(tga_idlength); - - // read color map data (even for non-color mapped images) - if (tga_colormap) { - if (tga_colormap > 1) - con_warn << filename << ": invalid color map type!" << std::endl; - - tga_file->skip(tga_color_map_length*tga_colormap_entry); - } - - unsigned int index = 0; - unsigned int channels = tga_depth / 8; - - switch(tga_type) { - - case TGA_NONE: - con_warn << "Error reading " << filename - << ": no image data!" << std::endl; - filesystem::close(tga_file); - return 0; - break; - - case TGA_TRUECOLOR: - if ((tga_depth == 24) || (tga_depth == 32)) { - - image = new Image(tga_width, tga_height, channels); - - for (size_t i = 0; i < tga_width * tga_height; i++) { - tga_file->read((void *)(*image)[i*(size_t)channels], channels); - } - - image->swap_channels(); - - } else if (tga_depth == 16) { - - channels = 3; - image = new Image(tga_width, tga_height,channels); - - for (size_t i =0; i < tga_width * tga_height; i++) { - // unpack one pixel - unsigned char pixel_data[2]; - tga_file->read((void *)pixel_data, 2); - unsigned int unpacked = pixel_data[0] + pixel_data[1]* 0xff; - - unsigned int b = (unpacked & 0x1f) << 3; - unsigned int g = ((unpacked >> 5) & 0x1f) << 3; - unsigned int r = ((unpacked >> 10) & 0x1f) << 3; - - // store it - image->data()[i * channels] = (unsigned char) b; - image->data()[i * channels+1] = (unsigned char) g; - image->data()[i * channels+2] = (unsigned char) r; - } - } else { - con_warn << "Error reading " << filename - << ": unsupported image depth '" << tga_depth << "'!" << std::endl; - filesystem::close(tga_file); - return 0; - } - - break; - - case TGA_TRUECOLOR_RLE: - - image = new Image(tga_width, tga_height, channels); - - while (index < tga_width * tga_height) { - unsigned char rle = 0; - unsigned char pixel_data[3]; - - // read RLE packet byte - tga_file->read(&rle, 1); - - if (rle < 128) { - rle++; // rle contains the number of pixels-1 - tga_file->read((void *)(*image)[index*channels], rle*channels); - index += rle; - - } else { - rle -= 127; // rle contains 128 + the number of identical pixels-1 - tga_file->read(pixel_data, channels); - - while (rle) { - memcpy((void *)(*image)[index*channels], (void *)pixel_data, channels); - index++; - rle--; - } - } - } - - image->swap_channels(); - - break; - - default: - con_warn << "Error reading " << filename - << ": unsupported TGA type '" << (int) tga_type << "'!" << std::endl; - filesystem::close(tga_file); - return 0; - } - - filesystem::close(tga_file); - - if ((tga_descriptor & 0x20) == 0x0) { - // origin at bottom left - image->flip(); - } - - if ((tga_descriptor & 0x10) == 0x10) { - con_warn << filename << ": descriptor bit 4 (left-right) set!" << std::endl; - } - - con_debug << " " << filename << " " << image->width() << "x" << image->height() << "x" << image->bpp() << "bpp" << std::endl; - return image; -} - -void TGA::save(const char *filename, Image & image) -{ - if (!filename) - return; - - std::ofstream ofs(filename, std::ios_base::out | std::ios_base::binary ); - - if (!ofs.is_open()) { - con_warn << "Could not write " << filename << std::endl; - return; - } - - // write TGA header - unsigned char header[18]; - memset(header, 0, sizeof(header)); - - // byte 0 - image ID field length = 0 (no image ID field present) - // byte 1 - color map type = 0 (no palette present) - // byte 2 - image type = 10 (truecolor RLE encoded) - header[2] = TGA_TRUECOLOR_RLE; - // byte 3-11 - palette data (not used) - // byte 12+13 - image width - header[12] = (image.width() & 0xff); - header[13] = ((image.width() >> 8) & 0xff); - // byte 14+15 - image height - header[14] = (image.height() & 0xff); - header[15] = ((image.height() >> 8) & 0xff); - // byte 16 - image color depth = 24 (RGB) or 32 (RGBA) - header[16] = image.channels() * 8; - // byte 17 - image descriptor byte = 0x20 (origin at bottom left) - header[17] = 0x20; - - // write header - ofs.write((char *)header, sizeof(header)); - - // write image data - // TGA has the R and B channels switched - unsigned char pixel_data[image.channels()]; - unsigned char block_data[image.channels()*128]; - unsigned char rle_packet; - bool compress = false; - size_t block_length = 0; - - for (int y = image.height()-1; y >= 0; y--) { - for (size_t x = 0; x < image.width(); x++) { - size_t index = y*image.width()*image.channels() + x * image.channels(); - - pixel_data[0] = *image[index+2]; - pixel_data[1] = *image[index+1]; - pixel_data[2] = *image[index]; - if (image.channels() == 4) - pixel_data[3] = *image[index+3]; - - if (block_length == 0) { - memcpy(block_data, pixel_data, image.channels()); - block_length++; - compress = false; - } else { - if (!compress) { - - // uncompressed block and pixel_data differs from the last pixel - if (memcmp(&block_data[(block_length-1)*image.channels()], pixel_data, image.channels()) != 0) { - // append pixel - memcpy(&block_data[block_length*image.channels()], pixel_data, image.channels()); - - block_length++; - } else { - - // uncompressed block and pixel data is identical - if (block_length > 1 ) { - // write the uncompressed block - rle_packet = block_length - 2; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, (block_length-1) * image.channels()); - block_length = 1; - } - memcpy(block_data, pixel_data, image.channels()); - block_length++; - compress = true; - } - - } else { - - // compressed block and pixel data is identical - if (memcmp(block_data, pixel_data, image.channels()) == 0) { - block_length++; - - } else { - - // compressed block and pixel data differs - if (block_length > 1) { - // write the compressed block - rle_packet = block_length + 127; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - block_length = 0; - } - memcpy(&block_data[block_length * image.channels()], pixel_data, image.channels()); - block_length++; - compress = false; - } - } - } - - if (block_length == 128) { - rle_packet = block_length - 1; - if (!compress) { - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, 128 * image.channels()); - } else { - rle_packet += 128; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - } - - block_length = 0; - compress = false; - } - } - } - - // write remaining bytes - if (block_length) { - rle_packet = block_length - 1; - if (!compress) { - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, block_length * image.channels()); - } else { - rle_packet += 128; - ofs.write((char *)&rle_packet, 1); - ofs.write((char *)block_data, image.channels()); - } - } - - - // write footer (optional, but the specification recommends it) - char footer[26]; - memset(footer, 0, sizeof(footer)); - strncpy(&footer[8] , "TRUEVISION-XFILE", 16); - footer[24] = '.'; - footer[25] = 0; - ofs.write(footer, sizeof(footer)); - - // close file - ofs.close(); - - con_print << "Wrote " << filename << std::endl; -} - -} -- cgit v1.2.3