13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*------------------------------------------------------------------------- 23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Image Library 33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * -------------------------- 43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project 63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License"); 83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License. 93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at 103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * http://www.apache.org/licenses/LICENSE-2.0 123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software 143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS, 153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and 173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License. 183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * 193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*! 203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file 213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief Targa file operations. 223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/ 233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deImage.h" 253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deMemory.h" 263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h" 273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include <stdio.h> 293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 303c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeImage* deImage_loadTarga (const char* fileName) 313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage* image = DE_NULL; 333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FILE* file; 343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry file = fopen(fileName, "rb"); 363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (file != DE_NULL) 383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bytesRead; 403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int width; 413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int height; 423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bufSize; 433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int stride; 443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bitsPerPixel; 453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8* buffer; 463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImageFormat format; 473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deBool yFlipped; 483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 tgaHeader[18]; 503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bytesRead = (int)fread(&tgaHeader, 1, 18, file); 523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(bytesRead == 18); 533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(tgaHeader[2] == 2); /* truecolor, no encoding */ 543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(tgaHeader[17] == 0x00 || tgaHeader[17] == 0x20); /* both y-directions supported, non-interlaced */ 553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry yFlipped = (tgaHeader[17] & 0x20) == 0; 573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Decode header. */ 593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry width = (int)(tgaHeader[12]) | ((int)(tgaHeader[13]) << 8); 603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry height = (int)(tgaHeader[14]) | ((int)(tgaHeader[15]) << 8); 613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bitsPerPixel = tgaHeader[16]; 623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry stride = width * bitsPerPixel / 8; 633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Allocate buffer. */ 653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry bufSize = stride; 663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry buffer = deMalloc(bufSize); 673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(buffer); 683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Figure out format. */ 703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(bitsPerPixel == 24 || bitsPerPixel == 32); 713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry format = (bitsPerPixel == 32) ? DE_IMAGEFORMAT_ARGB8888 : DE_IMAGEFORMAT_XRGB8888; 723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Create image. */ 743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image = deImage_create(width, height, format); 753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_TEST_ASSERT(image); 763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Copy pixel data. */ 783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int bpp = 4; 803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int x, y; 813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (y = 0; y < height; y++) 833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint8* src = buffer; 853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int dstY = yFlipped ? (height-1 - y) : y; 863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deARGB* dst = (deUint32*)((deUint8*)image->pixels + dstY*image->width*bpp); 873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fread(buffer, 1, bufSize, file); 883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (bitsPerPixel == 24) 903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (x = 0; x < width; x++) 923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 b = *src++; 943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 g = *src++; 953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 r = *src++; 963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *dst++ = deARGB_set(r, g, b, 0xFF); 973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry else 1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* \todo [petri] Component order? */ 1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 a = *src++; 1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 b = *src++; 1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 g = *src++; 1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint8 r = *src++; 1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry DE_ASSERT(bitsPerPixel == 32); 1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *dst++ = deARGB_set(r, g, b, a); 1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deFree(buffer); 1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fclose(file); 1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return image; 1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1193c827367444ee418f129b2c238299f49d3264554Jarkko PoyrydeBool deImage_saveTarga (const deImage* image, const char* fileName) 1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{ 1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage* imageCopy = DE_NULL; 1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int width = image->width; 1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int height = image->height; 1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry char tgaHeader[18]; 1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry FILE* file; 1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* \todo [petri] Handle non-alpha images. */ 1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (image->format != DE_IMAGEFORMAT_ARGB8888) 1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry imageCopy = deImage_convertFormat(image, DE_IMAGEFORMAT_ARGB8888); 1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!imageCopy) 1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_FALSE; 1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry image = imageCopy; 1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry file = fopen(fileName, "wb"); 1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (!file) 1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_FALSE; 1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Set unused fields of header to 0 */ 1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry memset(tgaHeader, 0, sizeof(tgaHeader)); 1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[1] = 0; /* no palette */ 1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[2] = 2; /* uncompressed RGB */ 1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[12] = (char)(width & 0xFF); 1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[13] = (char)(width >> 8); 1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[14] = (char)(height & 0xFF); 1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[15] = (char)(height >> 8); 1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[16] = 24; /* bytes per pixel */ 1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry tgaHeader[17] = 0x20; /* Top-down, non-interlaced */ 1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fwrite(tgaHeader, 1, 18, file); 1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Store pixels. */ 1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry const deUint32* pixels = image->pixels; 1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry int ndx; 1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry for (ndx = 0; ndx < width * height; ndx++) 1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry { 1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deUint32 c = pixels[ndx]; 1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fputc((deUint8)(c>>0), file); 1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fputc((deUint8)(c>>8), file); 1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fputc((deUint8)(c>>16), file); 1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry } 1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry /* Cleanup and return. */ 1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry fclose(file); 1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry if (imageCopy) 1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry deImage_destroy(imageCopy); 1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry 1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry return DE_TRUE; 1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} 177