// // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "tga_utils.h" #include #include #include #include #include TGAImage::TGAImage() : width(0), height(0), data(0) { } struct TGAHeader { uint8_t idSize; uint8_t mapType; uint8_t imageType; uint16_t paletteStart; uint16_t paletteSize; uint8_t paletteEntryDepth; uint16_t x; uint16_t y; uint16_t width; uint16_t height; uint8_t colorDepth; uint8_t descriptor; }; #define INVERTED_BIT (1 << 5) template void readBinary(std::ifstream &stream, dataType &item) { stream.read(reinterpret_cast(&item), sizeof(dataType)); } template void readBinary(std::ifstream &stream, std::vector &items) { stream.read(reinterpret_cast(items.data()), sizeof(dataType) * items.size()); } bool LoadTGAImageFromFile(const std::string &path, TGAImage *image) { std::ifstream stream(path, std::ios::binary); if (!stream) { std::cerr << "error opening tga file " << path << " for reading.\n"; return false; } TGAHeader header; readBinary(stream, header.idSize); readBinary(stream, header.mapType); readBinary(stream, header.imageType); readBinary(stream, header.paletteStart); readBinary(stream, header.paletteSize); readBinary(stream, header.paletteEntryDepth); readBinary(stream, header.x); readBinary(stream, header.y); readBinary(stream, header.width); readBinary(stream, header.height); readBinary(stream, header.colorDepth); readBinary(stream, header.descriptor); image->width = header.width; image->height = header.height; size_t pixelComponentCount = header.colorDepth / CHAR_BIT; std::vector buffer(header.width * header.height * pixelComponentCount); readBinary(stream, buffer); image->data.reserve(header.width * header.height); for (size_t y = 0; y < header.height; y++) { size_t rowIdx = ((header.descriptor & INVERTED_BIT) ? (header.height - 1 - y) : y) * header.width * pixelComponentCount; for (size_t x = 0; x < header.width; x++) { size_t pixelIdx = rowIdx + x * pixelComponentCount; Byte4 pixel; pixel[0] = (pixelComponentCount > 2) ? buffer[pixelIdx + 2] : 0; pixel[2] = (pixelComponentCount > 0) ? buffer[pixelIdx + 0] : 0; pixel[1] = (pixelComponentCount > 1) ? buffer[pixelIdx + 1] : 0; pixel[3] = (pixelComponentCount > 3) ? buffer[pixelIdx + 3] : 255; image->data.push_back(pixel); } } std::cout << "loaded image " << path << ".\n"; return true; } GLuint LoadTextureFromTGAImage(const TGAImage &image) { if (image.width > 0 && image.height > 0) { GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast(image.width), static_cast(image.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.data.data()); glGenerateMipmap(GL_TEXTURE_2D); return texture; } else { return 0; } }