You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.3 KiB
177 lines
4.3 KiB
4 months ago
|
/*-------------------------------------------------------------------------
|
||
|
* 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;
|
||
|
}
|