Home | History | Annotate | Download | only in deimage
      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