1// 2// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7#include "tga_utils.h" 8 9#include <iostream> 10#include <fstream> 11#include <string> 12#include <cstdint> 13 14TGAImage::TGAImage() 15 : data(0), width(0), height(0) 16{ 17} 18 19struct TGAHeader 20{ 21 uint8_t idSize; 22 uint8_t mapType; 23 uint8_t imageType; 24 uint16_t paletteStart; 25 uint16_t paletteSize; 26 uint8_t paletteEntryDepth; 27 uint16_t x; 28 uint16_t y; 29 uint16_t width; 30 uint16_t height; 31 uint8_t colorDepth; 32 uint8_t descriptor; 33}; 34 35#define INVERTED_BIT (1 << 5) 36 37template <typename dataType> 38void readBinary(std::ifstream &stream, dataType &item) 39{ 40 stream.read(reinterpret_cast<char *>(&item), sizeof(dataType)); 41} 42 43template <typename dataType> 44void readBinary(std::ifstream &stream, std::vector<dataType> &items) 45{ 46 stream.read(reinterpret_cast<char *>(items.data()), sizeof(dataType) * items.size()); 47} 48 49bool LoadTGAImageFromFile(const std::string &path, TGAImage *image) 50{ 51 std::ifstream stream(path, std::ios::binary); 52 if (!stream) 53 { 54 std::cerr << "error opening tga file " << path << " for reading.\n"; 55 return false; 56 } 57 58 TGAHeader header; 59 readBinary(stream, header.idSize); 60 readBinary(stream, header.mapType); 61 readBinary(stream, header.imageType); 62 readBinary(stream, header.paletteStart); 63 readBinary(stream, header.paletteSize); 64 readBinary(stream, header.paletteEntryDepth); 65 readBinary(stream, header.x); 66 readBinary(stream, header.y); 67 readBinary(stream, header.width); 68 readBinary(stream, header.height); 69 readBinary(stream, header.colorDepth); 70 readBinary(stream, header.descriptor); 71 72 image->width = header.width; 73 image->height = header.height; 74 75 size_t pixelComponentCount = header.colorDepth / CHAR_BIT; 76 std::vector<unsigned char> buffer(header.width * header.height * pixelComponentCount); 77 readBinary(stream, buffer); 78 79 image->data.reserve(header.width * header.height); 80 81 for (size_t y = 0; y < header.height; y++) 82 { 83 size_t rowIdx = ((header.descriptor & INVERTED_BIT) ? (header.height - 1 - y) : y) * header.width * pixelComponentCount; 84 for (size_t x = 0; x < header.width; x++) 85 { 86 size_t pixelIdx = rowIdx + x * pixelComponentCount; 87 88 Byte4 pixel; 89 pixel[0] = (pixelComponentCount > 2) ? buffer[pixelIdx + 2] : 0; 90 pixel[2] = (pixelComponentCount > 0) ? buffer[pixelIdx + 0] : 0; 91 pixel[1] = (pixelComponentCount > 1) ? buffer[pixelIdx + 1] : 0; 92 pixel[3] = (pixelComponentCount > 3) ? buffer[pixelIdx + 3] : 255; 93 94 image->data.push_back(pixel); 95 } 96 } 97 98 std::cout << "loaded image " << path << ".\n"; 99 100 return true; 101} 102 103GLuint LoadTextureFromTGAImage(const TGAImage &image) 104{ 105 if (image.width > 0 && image.height > 0) 106 { 107 GLuint texture; 108 glGenTextures(1, &texture); 109 glBindTexture(GL_TEXTURE_2D, texture); 110 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); 111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 112 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 113 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(image.width), static_cast<GLsizei>(image.height), 0, 114 GL_RGBA, GL_UNSIGNED_BYTE, image.data.data()); 115 glGenerateMipmap(GL_TEXTURE_2D); 116 return texture; 117 } 118 else 119 { 120 return 0; 121 } 122} 123