| /*------------------------------------------------------------------------- |
| * drawElements Image Library |
| * -------------------------- |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file |
| * \brief Targa file operations. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "deImage.h" |
| #include "deMemory.h" |
| #include "deInt32.h" |
| |
| #include <stdio.h> |
| |
| deImage* deImage_loadTarga (const char* fileName) |
| { |
| deImage* image = DE_NULL; |
| FILE* file; |
| |
| file = fopen(fileName, "rb"); |
| |
| if (file != DE_NULL) |
| { |
| int bytesRead; |
| int width; |
| int height; |
| int bufSize; |
| int stride; |
| int bitsPerPixel; |
| deUint8* buffer; |
| deImageFormat format; |
| deBool yFlipped; |
| |
| deUint8 tgaHeader[18]; |
| |
| bytesRead = (int)fread(&tgaHeader, 1, 18, file); |
| DE_TEST_ASSERT(bytesRead == 18); |
| DE_TEST_ASSERT(tgaHeader[2] == 2); /* truecolor, no encoding */ |
| DE_TEST_ASSERT(tgaHeader[17] == 0x00 || tgaHeader[17] == 0x20); /* both y-directions supported, non-interlaced */ |
| |
| yFlipped = (tgaHeader[17] & 0x20) == 0; |
| |
| /* Decode header. */ |
| width = (int)(tgaHeader[12]) | ((int)(tgaHeader[13]) << 8); |
| height = (int)(tgaHeader[14]) | ((int)(tgaHeader[15]) << 8); |
| bitsPerPixel = tgaHeader[16]; |
| stride = width * bitsPerPixel / 8; |
| |
| /* Allocate buffer. */ |
| bufSize = stride; |
| buffer = deMalloc(bufSize); |
| DE_TEST_ASSERT(buffer); |
| |
| /* Figure out format. */ |
| DE_TEST_ASSERT(bitsPerPixel == 24 || bitsPerPixel == 32); |
| format = (bitsPerPixel == 32) ? DE_IMAGEFORMAT_ARGB8888 : DE_IMAGEFORMAT_XRGB8888; |
| |
| /* Create image. */ |
| image = deImage_create(width, height, format); |
| DE_TEST_ASSERT(image); |
| |
| /* Copy pixel data. */ |
| { |
| int bpp = 4; |
| int x, y; |
| |
| for (y = 0; y < height; y++) |
| { |
| const deUint8* src = buffer; |
| int dstY = yFlipped ? (height-1 - y) : y; |
| deARGB* dst = (deUint32*)((deUint8*)image->pixels + dstY*image->width*bpp); |
| fread(buffer, 1, bufSize, file); |
| |
| if (bitsPerPixel == 24) |
| { |
| for (x = 0; x < width; x++) |
| { |
| deUint8 b = *src++; |
| deUint8 g = *src++; |
| deUint8 r = *src++; |
| *dst++ = deARGB_set(r, g, b, 0xFF); |
| } |
| } |
| else |
| { |
| /* \todo [petri] Component order? */ |
| deUint8 a = *src++; |
| deUint8 b = *src++; |
| deUint8 g = *src++; |
| deUint8 r = *src++; |
| DE_ASSERT(bitsPerPixel == 32); |
| *dst++ = deARGB_set(r, g, b, a); |
| } |
| } |
| } |
| |
| deFree(buffer); |
| fclose(file); |
| } |
| |
| return image; |
| } |
| |
| deBool deImage_saveTarga (const deImage* image, const char* fileName) |
| { |
| deImage* imageCopy = DE_NULL; |
| int width = image->width; |
| int height = image->height; |
| char tgaHeader[18]; |
| FILE* file; |
| |
| /* \todo [petri] Handle non-alpha images. */ |
| if (image->format != DE_IMAGEFORMAT_ARGB8888) |
| { |
| imageCopy = deImage_convertFormat(image, DE_IMAGEFORMAT_ARGB8888); |
| if (!imageCopy) |
| return DE_FALSE; |
| |
| image = imageCopy; |
| } |
| |
| file = fopen(fileName, "wb"); |
| if (!file) |
| return DE_FALSE; |
| |
| /* Set unused fields of header to 0 */ |
| memset(tgaHeader, 0, sizeof(tgaHeader)); |
| |
| tgaHeader[1] = 0; /* no palette */ |
| tgaHeader[2] = 2; /* uncompressed RGB */ |
| |
| tgaHeader[12] = (char)(width & 0xFF); |
| tgaHeader[13] = (char)(width >> 8); |
| tgaHeader[14] = (char)(height & 0xFF); |
| tgaHeader[15] = (char)(height >> 8); |
| tgaHeader[16] = 24; /* bytes per pixel */ |
| tgaHeader[17] = 0x20; /* Top-down, non-interlaced */ |
| |
| fwrite(tgaHeader, 1, 18, file); |
| |
| /* Store pixels. */ |
| { |
| const deUint32* pixels = image->pixels; |
| int ndx; |
| |
| for (ndx = 0; ndx < width * height; ndx++) |
| { |
| deUint32 c = pixels[ndx]; |
| fputc((deUint8)(c>>0), file); |
| fputc((deUint8)(c>>8), file); |
| fputc((deUint8)(c>>16), file); |
| } |
| } |
| |
| /* Cleanup and return. */ |
| fclose(file); |
| if (imageCopy) |
| deImage_destroy(imageCopy); |
| |
| return DE_TRUE; |
| } |