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