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