1 /*------------------------------------------------------------------------- 2 * drawElements Image Library 3 * -------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Targa file operations. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "deImage.h" 25 #include "deMemory.h" 26 #include "deInt32.h" 27 28 #include <stdio.h> 29 30 deImage* deImage_loadTarga (const char* fileName) 31 { 32 deImage* image = DE_NULL; 33 FILE* file; 34 35 file = fopen(fileName, "rb"); 36 37 if (file != DE_NULL) 38 { 39 int bytesRead; 40 int width; 41 int height; 42 int bufSize; 43 int stride; 44 int bitsPerPixel; 45 deUint8* buffer; 46 deImageFormat format; 47 deBool yFlipped; 48 49 deUint8 tgaHeader[18]; 50 51 bytesRead = (int)fread(&tgaHeader, 1, 18, file); 52 DE_TEST_ASSERT(bytesRead == 18); 53 DE_TEST_ASSERT(tgaHeader[2] == 2); /* truecolor, no encoding */ 54 DE_TEST_ASSERT(tgaHeader[17] == 0x00 || tgaHeader[17] == 0x20); /* both y-directions supported, non-interlaced */ 55 56 yFlipped = (tgaHeader[17] & 0x20) == 0; 57 58 /* Decode header. */ 59 width = (int)(tgaHeader[12]) | ((int)(tgaHeader[13]) << 8); 60 height = (int)(tgaHeader[14]) | ((int)(tgaHeader[15]) << 8); 61 bitsPerPixel = tgaHeader[16]; 62 stride = width * bitsPerPixel / 8; 63 64 /* Allocate buffer. */ 65 bufSize = stride; 66 buffer = deMalloc(bufSize); 67 DE_TEST_ASSERT(buffer); 68 69 /* Figure out format. */ 70 DE_TEST_ASSERT(bitsPerPixel == 24 || bitsPerPixel == 32); 71 format = (bitsPerPixel == 32) ? DE_IMAGEFORMAT_ARGB8888 : DE_IMAGEFORMAT_XRGB8888; 72 73 /* Create image. */ 74 image = deImage_create(width, height, format); 75 DE_TEST_ASSERT(image); 76 77 /* Copy pixel data. */ 78 { 79 int bpp = 4; 80 int x, y; 81 82 for (y = 0; y < height; y++) 83 { 84 const deUint8* src = buffer; 85 int dstY = yFlipped ? (height-1 - y) : y; 86 deARGB* dst = (deUint32*)((deUint8*)image->pixels + dstY*image->width*bpp); 87 fread(buffer, 1, bufSize, file); 88 89 if (bitsPerPixel == 24) 90 { 91 for (x = 0; x < width; x++) 92 { 93 deUint8 b = *src++; 94 deUint8 g = *src++; 95 deUint8 r = *src++; 96 *dst++ = deARGB_set(r, g, b, 0xFF); 97 } 98 } 99 else 100 { 101 /* \todo [petri] Component order? */ 102 deUint8 a = *src++; 103 deUint8 b = *src++; 104 deUint8 g = *src++; 105 deUint8 r = *src++; 106 DE_ASSERT(bitsPerPixel == 32); 107 *dst++ = deARGB_set(r, g, b, a); 108 } 109 } 110 } 111 112 deFree(buffer); 113 fclose(file); 114 } 115 116 return image; 117 } 118 119 deBool deImage_saveTarga (const deImage* image, const char* fileName) 120 { 121 deImage* imageCopy = DE_NULL; 122 int width = image->width; 123 int height = image->height; 124 char tgaHeader[18]; 125 FILE* file; 126 127 /* \todo [petri] Handle non-alpha images. */ 128 if (image->format != DE_IMAGEFORMAT_ARGB8888) 129 { 130 imageCopy = deImage_convertFormat(image, DE_IMAGEFORMAT_ARGB8888); 131 if (!imageCopy) 132 return DE_FALSE; 133 134 image = imageCopy; 135 } 136 137 file = fopen(fileName, "wb"); 138 if (!file) 139 return DE_FALSE; 140 141 /* Set unused fields of header to 0 */ 142 memset(tgaHeader, 0, sizeof(tgaHeader)); 143 144 tgaHeader[1] = 0; /* no palette */ 145 tgaHeader[2] = 2; /* uncompressed RGB */ 146 147 tgaHeader[12] = (char)(width & 0xFF); 148 tgaHeader[13] = (char)(width >> 8); 149 tgaHeader[14] = (char)(height & 0xFF); 150 tgaHeader[15] = (char)(height >> 8); 151 tgaHeader[16] = 24; /* bytes per pixel */ 152 tgaHeader[17] = 0x20; /* Top-down, non-interlaced */ 153 154 fwrite(tgaHeader, 1, 18, file); 155 156 /* Store pixels. */ 157 { 158 const deUint32* pixels = image->pixels; 159 int ndx; 160 161 for (ndx = 0; ndx < width * height; ndx++) 162 { 163 deUint32 c = pixels[ndx]; 164 fputc((deUint8)(c>>0), file); 165 fputc((deUint8)(c>>8), file); 166 fputc((deUint8)(c>>16), file); 167 } 168 } 169 170 /* Cleanup and return. */ 171 fclose(file); 172 if (imageCopy) 173 deImage_destroy(imageCopy); 174 175 return DE_TRUE; 176 } 177