xref: /aosp_15_r20/external/deqp/framework/delibs/deimage/deTarga.c (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 
deImage_loadTarga(const char * fileName)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         uint8_t *buffer;
46         deImageFormat format;
47         bool yFlipped;
48 
49         uint8_t 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 ||
55                        tgaHeader[17] == 0x20); /* both y-directions supported, non-interlaced */
56 
57         yFlipped = (tgaHeader[17] & 0x20) == 0;
58 
59         /* Decode header. */
60         width        = (int)(tgaHeader[12]) | ((int)(tgaHeader[13]) << 8);
61         height       = (int)(tgaHeader[14]) | ((int)(tgaHeader[15]) << 8);
62         bitsPerPixel = tgaHeader[16];
63         stride       = width * bitsPerPixel / 8;
64 
65         /* Allocate buffer. */
66         bufSize = stride;
67         buffer  = deMalloc(bufSize);
68         DE_TEST_ASSERT(buffer);
69 
70         /* Figure out format. */
71         DE_TEST_ASSERT(bitsPerPixel == 24 || bitsPerPixel == 32);
72         format = (bitsPerPixel == 32) ? DE_IMAGEFORMAT_ARGB8888 : DE_IMAGEFORMAT_XRGB8888;
73 
74         /* Create image. */
75         image = deImage_create(width, height, format);
76         DE_TEST_ASSERT(image);
77 
78         /* Copy pixel data. */
79         {
80             int bpp = 4;
81             int x, y;
82 
83             for (y = 0; y < height; y++)
84             {
85                 const uint8_t *src = buffer;
86                 int dstY           = yFlipped ? (height - 1 - y) : y;
87                 deARGB *dst        = (uint32_t *)((uint8_t *)image->pixels + dstY * image->width * bpp);
88                 fread(buffer, 1, bufSize, file);
89 
90                 if (bitsPerPixel == 24)
91                 {
92                     for (x = 0; x < width; x++)
93                     {
94                         uint8_t b = *src++;
95                         uint8_t g = *src++;
96                         uint8_t r = *src++;
97                         *dst++    = deARGB_set(r, g, b, 0xFF);
98                     }
99                 }
100                 else
101                 {
102                     /* \todo [petri] Component order? */
103                     uint8_t a = *src++;
104                     uint8_t b = *src++;
105                     uint8_t g = *src++;
106                     uint8_t r = *src++;
107                     DE_ASSERT(bitsPerPixel == 32);
108                     *dst++ = deARGB_set(r, g, b, a);
109                 }
110             }
111         }
112 
113         deFree(buffer);
114         fclose(file);
115     }
116 
117     return image;
118 }
119 
deImage_saveTarga(const deImage * image,const char * fileName)120 bool deImage_saveTarga(const deImage *image, const char *fileName)
121 {
122     deImage *imageCopy = DE_NULL;
123     int width          = image->width;
124     int height         = image->height;
125     char tgaHeader[18];
126     FILE *file;
127 
128     /* \todo [petri] Handle non-alpha images. */
129     if (image->format != DE_IMAGEFORMAT_ARGB8888)
130     {
131         imageCopy = deImage_convertFormat(image, DE_IMAGEFORMAT_ARGB8888);
132         if (!imageCopy)
133             return false;
134 
135         image = imageCopy;
136     }
137 
138     file = fopen(fileName, "wb");
139     if (!file)
140         return false;
141 
142     /* Set unused fields of header to 0 */
143     memset(tgaHeader, 0, sizeof(tgaHeader));
144 
145     tgaHeader[1] = 0; /* no palette */
146     tgaHeader[2] = 2; /* uncompressed RGB */
147 
148     tgaHeader[12] = (char)(width & 0xFF);
149     tgaHeader[13] = (char)(width >> 8);
150     tgaHeader[14] = (char)(height & 0xFF);
151     tgaHeader[15] = (char)(height >> 8);
152     tgaHeader[16] = 24;   /* bytes per pixel */
153     tgaHeader[17] = 0x20; /* Top-down, non-interlaced */
154 
155     fwrite(tgaHeader, 1, 18, file);
156 
157     /* Store pixels. */
158     {
159         const uint32_t *pixels = image->pixels;
160         int ndx;
161 
162         for (ndx = 0; ndx < width * height; ndx++)
163         {
164             uint32_t c = pixels[ndx];
165             fputc((uint8_t)(c >> 0), file);
166             fputc((uint8_t)(c >> 8), file);
167             fputc((uint8_t)(c >> 16), file);
168         }
169     }
170 
171     /* Cleanup and return. */
172     fclose(file);
173     if (imageCopy)
174         deImage_destroy(imageCopy);
175 
176     return true;
177 }
178