source: mainline/uspace/lib/gfximage/src/tga.c@ 901b302

ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 901b302 was fd05ea6, checked in by Jiri Svoboda <jiri@…>, 3 years ago

Fix doxygen group

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/*
2 * Copyright (c) 2011 Martin Decky
3 * Copyright (c) 2011 Petr Koupy
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libgfximage
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdlib.h>
38#include <byteorder.h>
39#include <align.h>
40#include <stdbool.h>
41#include <pixconv.h>
42#include <gfx/bitmap.h>
43#include <gfximage/tga.h>
44#include <io/pixelmap.h>
45
46typedef struct {
47 uint8_t id_length;
48 uint8_t cmap_type;
49 uint8_t img_type;
50
51 uint16_t cmap_first_entry;
52 uint16_t cmap_entries;
53 uint8_t cmap_bpp;
54
55 uint16_t startx;
56 uint16_t starty;
57 uint16_t width;
58 uint16_t height;
59 uint8_t img_bpp;
60 uint8_t img_descr;
61} __attribute__((packed)) tga_header_t;
62
63typedef enum {
64 CMAP_NOT_PRESENT = 0,
65 CMAP_PRESENT = 1,
66 CMAP_RESERVED_START = 2,
67 CMAP_PRIVATE_START = 128
68} cmap_type_t;
69
70typedef enum {
71 IMG_EMTPY = 0,
72 IMG_CMAP = 1,
73 IMG_BGRA = 2,
74 IMG_GRAY = 3,
75 IMG_CMAP_RLE = 9,
76 IMG_BGRA_RLE = 10,
77 IMG_GRAY_RLE = 11
78} img_type_t;
79
80typedef struct {
81 cmap_type_t cmap_type;
82 img_type_t img_type;
83
84 uint16_t cmap_first_entry;
85 uint16_t cmap_entries;
86 uint8_t cmap_bpp;
87
88 uint16_t startx;
89 uint16_t starty;
90 uint16_t width;
91 uint16_t height;
92 uint8_t img_bpp;
93 uint8_t img_alpha_bpp;
94 uint8_t img_alpha_dir;
95
96 void *id_data;
97 size_t id_length;
98
99 void *cmap_data;
100 size_t cmap_length;
101
102 void *img_data;
103 size_t img_length;
104} tga_t;
105
106/** Decode Truevision TGA header
107 *
108 * @param[in] data Memory representation of TGA.
109 * @param[in] size Size of the representation (in bytes).
110 * @param[out] tga Decoded TGA.
111 *
112 * @return True on succesful decoding.
113 * @return False on failure.
114 *
115 */
116static bool decode_tga_header(void *data, size_t size, tga_t *tga)
117{
118 /* Header sanity check */
119 if (size < sizeof(tga_header_t))
120 return false;
121
122 tga_header_t *head = (tga_header_t *) data;
123
124 /* Image ID field */
125 tga->id_data = data + sizeof(tga_header_t);
126 tga->id_length = head->id_length;
127
128 if (size < sizeof(tga_header_t) + tga->id_length)
129 return false;
130
131 /* Color map type */
132 tga->cmap_type = head->cmap_type;
133
134 /* Image type */
135 tga->img_type = head->img_type;
136
137 /* Color map specification */
138 tga->cmap_first_entry = uint16_t_le2host(head->cmap_first_entry);
139 tga->cmap_entries = uint16_t_le2host(head->cmap_entries);
140 tga->cmap_bpp = head->cmap_bpp;
141 tga->cmap_data = tga->id_data + tga->id_length;
142 tga->cmap_length = ALIGN_UP(tga->cmap_entries * tga->cmap_bpp, 8) >> 3;
143
144 if (size < sizeof(tga_header_t) + tga->id_length +
145 tga->cmap_length)
146 return false;
147
148 /* Image specification */
149 tga->startx = uint16_t_le2host(head->startx);
150 tga->starty = uint16_t_le2host(head->starty);
151 tga->width = uint16_t_le2host(head->width);
152 tga->height = uint16_t_le2host(head->height);
153 tga->img_bpp = head->img_bpp;
154 tga->img_alpha_bpp = head->img_descr & 0x0f;
155 tga->img_alpha_dir = (head->img_descr & 0xf0) >> 4;
156 tga->img_data = tga->cmap_data + tga->cmap_length;
157 tga->img_length = ALIGN_UP(tga->width * tga->height * tga->img_bpp, 8) >> 3;
158
159 if (size < sizeof(tga_header_t) + tga->id_length +
160 tga->cmap_length + tga->img_length)
161 return false;
162
163 return true;
164}
165
166/** Decode Truevision TGA format
167 *
168 * Decode Truevision TGA format and create a surface
169 * from it. The supported variants of TGA are currently
170 * limited to uncompressed 24 bit true-color images without
171 * alpha channel.
172 *
173 * @param gc Graphic context
174 * @param data Memory representation of gzipped TGA.
175 * @param size Size of the representation (in bytes).
176 * @param rbitmap Place to store pointer to new bitmap
177 * @param rrect Place to store bitmap rectangle
178 *
179 * @return EOK un success or an error code
180 */
181errno_t decode_tga(gfx_context_t *gc, void *data, size_t size,
182 gfx_bitmap_t **rbitmap, gfx_rect_t *rrect)
183{
184 gfx_bitmap_params_t params;
185 gfx_bitmap_alloc_t alloc;
186 gfx_bitmap_t *bitmap = NULL;
187 pixelmap_t pixelmap;
188 errno_t rc;
189
190 tga_t tga;
191 if (!decode_tga_header(data, size, &tga))
192 return EINVAL;
193
194 /*
195 * Check for unsupported features.
196 */
197
198 switch (tga.cmap_type) {
199 case CMAP_NOT_PRESENT:
200 break;
201 default:
202 /* Unsupported */
203 return ENOTSUP;
204 }
205
206 switch (tga.img_type) {
207 case IMG_BGRA:
208 if (tga.img_bpp != 24)
209 return ENOTSUP;
210 break;
211 case IMG_GRAY:
212 if (tga.img_bpp != 8)
213 return ENOTSUP;
214 break;
215 default:
216 /* Unsupported */
217 return ENOTSUP;
218 }
219
220 if (tga.img_alpha_bpp != 0)
221 return ENOTSUP;
222
223 sysarg_t twidth = tga.startx + tga.width;
224 sysarg_t theight = tga.starty + tga.height;
225
226 gfx_bitmap_params_init(&params);
227 params.rect.p1.x = twidth;
228 params.rect.p1.y = theight;
229
230 rc = gfx_bitmap_create(gc, &params, NULL, &bitmap);
231 if (rc != EOK)
232 return rc;
233
234 rc = gfx_bitmap_get_alloc(bitmap, &alloc);
235 if (rc != EOK) {
236 gfx_bitmap_destroy(bitmap);
237 return rc;
238 }
239
240 pixelmap.width = twidth;
241 pixelmap.height = theight;
242 pixelmap.data = alloc.pixels;
243
244 /*
245 * TGA is encoded in a bottom-up manner, the true-color
246 * variant is in BGR 8:8:8 encoding.
247 */
248
249 switch (tga.img_type) {
250 case IMG_BGRA:
251 for (sysarg_t y = tga.starty; y < theight; y++) {
252 for (sysarg_t x = tga.startx; x < twidth; x++) {
253 size_t offset =
254 ((y - tga.starty) * tga.width + (x - tga.startx)) * 3;
255
256 pixel_t pixel =
257 bgr_888_2pixel(((uint8_t *) tga.img_data) + offset);
258 pixelmap_put_pixel(&pixelmap, x, theight - y - 1, pixel);
259 }
260 }
261 break;
262 case IMG_GRAY:
263 for (sysarg_t y = tga.starty; y < theight; y++) {
264 for (sysarg_t x = tga.startx; x < twidth; x++) {
265 size_t offset =
266 (y - tga.starty) * tga.width + (x - tga.startx);
267
268 pixel_t pixel =
269 gray_8_2pixel(((uint8_t *) tga.img_data) + offset);
270 pixelmap_put_pixel(&pixelmap, x, theight - y - 1, pixel);
271 }
272 }
273 break;
274 default:
275 break;
276 }
277
278 *rbitmap = bitmap;
279 *rrect = params.rect;
280 return EOK;
281}
282
283/** @}
284 */
Note: See TracBrowser for help on using the repository browser.