aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c')
-rw-r--r--libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c596
1 files changed, 596 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c b/libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c
new file mode 100644
index 0000000..61b99f6
--- /dev/null
+++ b/libraries/evas/src/modules/loaders/tga/evas_image_load_tga.c
@@ -0,0 +1,596 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <sys/types.h>
7#include <fcntl.h>
8
9#ifdef HAVE_EVIL
10# include <Evil.h>
11#endif
12
13#include "evas_common.h"
14#include "evas_private.h"
15
16/* TGA pixel formats */
17#define TGA_TYPE_MAPPED 1 // handle
18#define TGA_TYPE_COLOR 2
19#define TGA_TYPE_GRAY 3
20#define TGA_TYPE_MAPPED_RLE 9 // handle
21#define TGA_TYPE_COLOR_RLE 10
22#define TGA_TYPE_GRAY_RLE 11
23
24/* TGA header flags */
25#define TGA_DESC_ABITS 0x0f
26#define TGA_DESC_HORIZONTAL 0x10
27#define TGA_DESC_VERTICAL 0x20
28
29#define TGA_SIGNATURE "TRUEVISION-XFILE"
30
31typedef struct _tga_header tga_header;
32typedef struct _tga_footer tga_footer;
33
34struct _tga_header
35{
36 unsigned char idLength;
37 unsigned char colorMapType;
38 unsigned char imageType;
39 unsigned char colorMapIndexLo, colorMapIndexHi;
40 unsigned char colorMapLengthLo, colorMapLengthHi;
41 unsigned char colorMapSize;
42 unsigned char xOriginLo, xOriginHi;
43 unsigned char yOriginLo, yOriginHi;
44 unsigned char widthLo, widthHi;
45 unsigned char heightLo, heightHi;
46 unsigned char bpp;
47 unsigned char descriptor;
48} __attribute__((packed));
49
50struct _tga_footer
51{
52 unsigned int extensionAreaOffset;
53 unsigned int developerDirectoryOffset;
54 char signature[16];
55 char dot;
56 char null;
57} __attribute__((packed));
58
59
60static Eina_Bool evas_image_load_file_head_tga(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
61static Eina_Bool evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
62
63static Evas_Image_Load_Func evas_image_load_tga_func =
64{
65 EINA_TRUE,
66 evas_image_load_file_head_tga,
67 evas_image_load_file_data_tga,
68 NULL
69};
70
71static Eina_Bool
72evas_image_load_file_head_tga(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
73{
74 Eina_File *f;
75 unsigned char *seg = NULL, *filedata;
76 tga_header *header;
77 tga_footer *footer, tfooter;
78 char hasa = 0, footer_present = 0, vinverted = 0;
79 int w = 0, h = 0, bpp;
80 int x, y;
81 int abits;
82
83 f = eina_file_open(file, EINA_FALSE);
84 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
85 if (f == NULL) return EINA_FALSE;
86
87 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
88 if (eina_file_size_get(f) < (off_t)(sizeof(tga_header) + sizeof(tga_footer)))
89 goto close_file;
90 seg = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
91 if (seg == NULL) goto close_file;
92 filedata = seg;
93
94 header = (tga_header *)filedata;
95 // no unaligned data accessed, so ok
96 footer = (tga_footer *)(filedata + (eina_file_size_get(f) - sizeof(tga_footer)));
97 memcpy((unsigned char *)(&tfooter),
98 (unsigned char *)footer,
99 sizeof(tga_footer));
100 printf("0\n");
101 if (!memcmp(tfooter.signature, TGA_SIGNATURE, sizeof(tfooter.signature)))
102 {
103 if ((tfooter.dot == '.') && (tfooter.null == 0))
104 {
105 // footer is there and matches. this is a tga file - any problems now
106 // are a corrupt file
107 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
108 footer_present = 1;
109 }
110 }
111// else goto close_file;
112 printf("1\n");
113
114 filedata = (unsigned char *)filedata + sizeof(tga_header);
115 vinverted = !(header->descriptor & TGA_DESC_VERTICAL);
116 switch (header->imageType)
117 {
118 case TGA_TYPE_COLOR_RLE:
119 case TGA_TYPE_GRAY_RLE:
120// rle = 1;
121 break;
122 case TGA_TYPE_COLOR:
123 case TGA_TYPE_GRAY:
124// rle = 0;
125 break;
126 default:
127 goto close_file;
128 }
129 bpp = header->bpp;
130 if (!((bpp == 32) || (bpp == 24) || (bpp == 16) || (bpp == 8)))
131 goto close_file;
132 if ((bpp == 32) && (header->descriptor & TGA_DESC_ABITS)) hasa = 1;
133 abits = header->descriptor & TGA_DESC_ABITS;
134 // don't handle colormapped images
135 if ((header->colorMapType) != 0)
136 goto close_file;
137 // if colormap size is anything other than legal sizes or 0 - not real tga
138 if (!((header->colorMapSize == 0) ||
139 (header->colorMapSize == 15) ||
140 (header->colorMapSize == 16) ||
141 (header->colorMapSize == 24) ||
142 (header->colorMapSize == 32)))
143 goto close_file;
144 x = (header->xOriginHi << 8) | (header->xOriginLo);
145 y = (header->yOriginHi << 8) | (header->yOriginLo);
146 w = (header->widthHi << 8) | header->widthLo;
147 h = (header->heightHi << 8) | header->heightLo;
148 // x origin gerater that width, y origin greater than height - wrong file
149 if ((x >= w) || (y >= h))
150 goto close_file;
151 // if descriptor has either of the top 2 bits set... not tga
152 if (header->descriptor & 0xc0)
153 goto close_file;
154
155 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
156 IMG_TOO_BIG(w, h))
157 goto close_file;
158
159 ie->w = w;
160 ie->h = h;
161 if (hasa) ie->flags.alpha = 1;
162
163 eina_file_map_free(f, seg);
164 eina_file_close(f);
165 *error = EVAS_LOAD_ERROR_NONE;
166 return EINA_TRUE;
167
168close_file:
169 if (seg != NULL) eina_file_map_free(f, seg);
170 eina_file_close(f);
171 return EINA_FALSE;
172}
173
174static Eina_Bool
175evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
176{
177 Eina_File *f;
178 unsigned char *seg = NULL, *filedata;
179 tga_header *header;
180 tga_footer *footer, tfooter;
181 char hasa = 0, footer_present = 0, vinverted = 0, rle = 0;
182 int w = 0, h = 0, x, y, bpp;
183 off_t size;
184 unsigned int *surface, *dataptr;
185 unsigned int datasize;
186 unsigned char *bufptr, *bufend;
187 int abits;
188
189 f = eina_file_open(file, EINA_FALSE);
190 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
191 if (f == NULL) return EINA_FALSE;
192
193 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
194 if (eina_file_size_get(f) < (off_t)(sizeof(tga_header) + sizeof(tga_footer)))
195 goto close_file;
196 seg = eina_file_map_all(f, EINA_FILE_SEQUENTIAL);
197 if (seg == NULL) goto close_file;
198 filedata = seg;
199 size = eina_file_size_get(f);
200
201 header = (tga_header *)filedata;
202 // no unaligned data accessed, so ok
203 footer = (tga_footer *)(filedata + (size - sizeof(tga_footer)));
204 memcpy((unsigned char *)&tfooter,
205 (unsigned char *)footer,
206 sizeof(tga_footer));
207 if (!memcmp(tfooter.signature, TGA_SIGNATURE, sizeof(tfooter.signature)))
208 {
209 if ((tfooter.dot == '.') && (tfooter.null == 0))
210 {
211 // footer is there and matches. this is a tga file - any problems now
212 // are a corrupt file
213 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
214 footer_present = 1;
215 }
216 }
217
218 filedata = (unsigned char *)filedata + sizeof(tga_header);
219 vinverted = !(header->descriptor & TGA_DESC_VERTICAL);
220 switch (header->imageType)
221 {
222 case TGA_TYPE_COLOR_RLE:
223 case TGA_TYPE_GRAY_RLE:
224 rle = 1;
225 break;
226 case TGA_TYPE_COLOR:
227 case TGA_TYPE_GRAY:
228 rle = 0;
229 break;
230 default:
231 goto close_file;
232 }
233 bpp = header->bpp;
234 if (!((bpp == 32) || (bpp == 24) || (bpp == 16) || (bpp == 8)))
235 goto close_file;
236 if ((bpp == 32) && (header->descriptor & TGA_DESC_ABITS)) hasa = 1;
237 abits = header->descriptor & TGA_DESC_ABITS;
238 // don't handle colormapped images
239 if ((header->colorMapType) != 0)
240 goto close_file;
241 // if colormap size is anything other than legal sizes or 0 - not real tga
242 if (!((header->colorMapSize == 0) ||
243 (header->colorMapSize == 15) ||
244 (header->colorMapSize == 16) ||
245 (header->colorMapSize == 24) ||
246 (header->colorMapSize == 32)))
247 goto close_file;
248 x = (header->xOriginHi << 8) | (header->xOriginLo);
249 y = (header->yOriginHi << 8) | (header->yOriginLo);
250 w = (header->widthHi << 8) | header->widthLo;
251 h = (header->heightHi << 8) | header->heightLo;
252 // x origin gerater that width, y origin greater than height - wrong file
253 if ((x >= w) || (y >= h))
254 goto close_file;
255 // if descriptor has either of the top 2 bits set... not tga
256 if (header->descriptor & 0xc0)
257 goto close_file;
258
259 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
260 IMG_TOO_BIG(w, h))
261 goto close_file;
262
263 if ((w != (int)ie->w) || (h != (int)ie->h))
264 {
265 *error = EVAS_LOAD_ERROR_GENERIC;
266 goto close_file;
267 }
268 evas_cache_image_surface_alloc(ie, w, h);
269 surface = evas_cache_image_pixels(ie);
270 if (!surface)
271 {
272 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
273 goto close_file;
274 }
275
276 datasize = size - sizeof(tga_header) - header->idLength;
277 if (footer_present)
278 datasize = size - sizeof(tga_header) - header->idLength -
279 sizeof(tga_footer);
280
281 bufptr = filedata + header->idLength;
282 bufend = filedata + datasize;
283
284 if (!rle)
285 {
286 for (y = 0; y < h; y++)
287 {
288 if (vinverted)
289 /* some TGA's are stored upside-down! */
290 dataptr = surface + ((h - y - 1) * w);
291 else
292 dataptr = surface + (y * w);
293 switch (bpp)
294 {
295 case 32:
296 for (x = 0; (x < w) && ((bufptr + 4) <= bufend); x++)
297 {
298 if (hasa)
299 {
300 int a = bufptr[3];
301
302 switch (abits)
303 {
304 case 1:
305 a = (a << 7) | (a << 6) | (a << 5) | (a << 4) | (a << 3) | (a << 2) | (a << 1) | (a);
306 case 2:
307 a = (a << 6) | (a << 4) | (a << 2) | (a);
308 case 3:
309 a = (a << 5) | (a << 2) | (a >> 1);
310 case 4:
311 a = (a << 4) | (a);
312 case 5:
313 a = (a << 3) | (a >> 2);
314 case 6:
315 a = (a << 2) | (a >> 4);
316 case 7:
317 a = (a << 1) | (a >> 6);
318 default:
319 break;
320 }
321 *dataptr = ARGB_JOIN(a, bufptr[2], bufptr[1], bufptr[0]);
322 }
323 else
324 *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
325 dataptr++;
326 bufptr += 4;
327 }
328 break;
329 case 24:
330 for (x = 0; (x < w) && ((bufptr + 3) <= bufend); x++)
331 {
332 *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
333 dataptr++;
334 bufptr += 3;
335 }
336 break;
337 case 16:
338 for (x = 0; (x < w) && ((bufptr + 3) <= bufend); x++)
339 {
340 unsigned char r, g, b, a;
341 unsigned short tmp;
342
343 tmp =
344 (((unsigned short)bufptr[1]) << 8) |
345 (((unsigned short)bufptr[0]));
346 r = (tmp >> 7) & 0xf8; r |= r >> 5;
347 g = (tmp >> 2) & 0xf8; g |= g >> 5;
348 b = (tmp << 3) & 0xf8; b |= b >> 5;
349 a = 0xff;
350 if ((hasa) && (tmp & 0x8000)) a = 0;
351 *dataptr = ARGB_JOIN(a, r, g, b);
352 dataptr++;
353 bufptr += 2;
354 }
355 break;
356 case 8:
357 for (x = 0; (x < w) && ((bufptr + 1) <= bufend); x++)
358 {
359 *dataptr = ARGB_JOIN(0xff, bufptr[0], bufptr[0], bufptr[0]);
360 dataptr++;
361 bufptr += 1;
362 }
363 break;
364 default:
365 break;
366 }
367 }
368 }
369 else
370 {
371 int count, i;
372 unsigned char val;
373 unsigned int *dataend;
374
375 dataptr = surface;
376 dataend = dataptr + (w * h);
377 while ((bufptr < bufend) && (dataptr < dataend))
378 {
379 val = *bufptr;
380 bufptr++;
381 count = (val & 0x7f) + 1;
382 if (val & 0x80) // rel packet
383 {
384 switch (bpp)
385 {
386 case 32:
387 if (bufptr < (bufend - 4))
388 {
389 unsigned char r, g, b;
390 int a = bufptr[3];
391
392 switch (abits)
393 {
394 case 1:
395 a = (a << 7) | (a << 6) | (a << 5) | (a << 4) | (a << 3) | (a << 2) | (a << 1) | (a);
396 case 2:
397 a = (a << 6) | (a << 4) | (a << 2) | (a);
398 case 3:
399 a = (a << 5) | (a << 2) | (a >> 1);
400 case 4:
401 a = (a << 4) | (a);
402 case 5:
403 a = (a << 3) | (a >> 2);
404 case 6:
405 a = (a << 2) | (a >> 4);
406 case 7:
407 a = (a << 1) | (a >> 6);
408 default:
409 break;
410 }
411 r = bufptr[2];
412 g = bufptr[1];
413 b = bufptr[0];
414 if (!hasa) a = 0xff;
415 bufptr += 4;
416 for (i = 0; (i < count) && (dataptr < dataend); i++)
417 {
418 *dataptr = ARGB_JOIN(a, r, g, b);
419 dataptr++;
420 }
421 }
422 break;
423 case 24:
424 if (bufptr < (bufend - 3))
425 {
426 unsigned char r, g, b;
427
428 r = bufptr[2];
429 g = bufptr[1];
430 b = bufptr[0];
431 bufptr += 3;
432 for (i = 0; (i < count) && (dataptr < dataend); i++)
433 {
434 *dataptr = ARGB_JOIN(0xff, r, g, b);
435 dataptr++;
436 }
437 }
438 break;
439 case 16:
440 if (bufptr < (bufend - 2))
441 {
442 unsigned char r, g, b, a;
443 unsigned short tmp;
444
445 tmp =
446 (((unsigned short)bufptr[1]) << 8) |
447 (((unsigned short)bufptr[0]));
448 r = (tmp >> 7) & 0xf8; r |= r >> 5;
449 g = (tmp >> 2) & 0xf8; g |= g >> 5;
450 b = (tmp << 3) & 0xf8; b |= b >> 5;
451 a = 0xff;
452 if ((hasa) && (tmp & 0x8000)) a = 0;
453 bufptr += 2;
454 for (i = 0; (i < count) && (dataptr < dataend); i++)
455 {
456 *dataptr = ARGB_JOIN(a, r, g, b);
457 dataptr++;
458 }
459 }
460 break;
461 case 8:
462 if (bufptr < (bufend - 1))
463 {
464 unsigned char g;
465
466 g = bufptr[0];
467 bufptr += 1;
468 for (i = 0; (i < count) && (dataptr < dataend); i++)
469 {
470 *dataptr = ARGB_JOIN(0xff, g, g, g);
471 dataptr++;
472 }
473 }
474 break;
475 default:
476 break;
477 }
478 }
479 else // raw
480 {
481 switch (bpp)
482 {
483 case 32:
484 for (i = 0; (i < count) && (bufptr < (bufend - 4)) && (dataptr < dataend); i++)
485 {
486 if (hasa)
487// *dataptr = ARGB_JOIN(255 - bufptr[3], bufptr[2], bufptr[1], bufptr[0]);
488 *dataptr = ARGB_JOIN(bufptr[3], bufptr[2], bufptr[1], bufptr[0]);
489 else
490 *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
491 dataptr++;
492 bufptr += 4;
493 }
494 break;
495 case 24:
496 for (i = 0; (i < count) && (bufptr < (bufend - 3)) && (dataptr < dataend); i++)
497 {
498 *dataptr = ARGB_JOIN(0xff, bufptr[2], bufptr[1], bufptr[0]);
499 dataptr++;
500 bufptr += 3;
501 }
502 break;
503 case 16:
504 for (i = 0; (i < count) && (bufptr < (bufend - 2)) && (dataptr < dataend); i++)
505 {
506 unsigned char r, g, b, a;
507 unsigned short tmp;
508
509 tmp =
510 (((unsigned short)bufptr[1]) << 8) |
511 (((unsigned short)bufptr[0]));
512 r = (tmp >> 7) & 0xf8; r |= r >> 5;
513 g = (tmp >> 2) & 0xf8; g |= g >> 5;
514 b = (tmp << 3) & 0xf8; b |= b >> 5;
515 a = 0xff;
516 if ((hasa) && (tmp & 0x8000)) a = 0;
517 *dataptr = ARGB_JOIN(a, r, g, b);
518 dataptr++;
519 bufptr += 2;
520 }
521 break;
522 case 8:
523 for (i = 0; (i < count) && (bufptr < (bufend - 1)) && (dataptr < dataend); i++)
524 {
525 *dataptr = ARGB_JOIN(0xff, bufptr[0], bufptr[0], bufptr[0]);
526 dataptr++;
527 bufptr += 1;
528 }
529 break;
530 default:
531 break;
532 }
533 }
534 }
535 if (vinverted)
536 {
537 unsigned int *adv, *adv2, tmp;
538
539 adv = surface;
540 adv2 = surface + (w * (h - 1));
541 for (y = 0; y < (h / 2); y++)
542 {
543 for (x = 0; x < w; x++)
544 {
545 tmp = adv[x];
546 adv[x] = adv2[x];
547 adv2[x] = tmp;
548 }
549 adv2 -= w;
550 adv += w;
551 }
552 }
553 }
554
555 evas_common_image_premul(ie);
556
557 eina_file_map_free(f, seg);
558 eina_file_close(f);
559 *error = EVAS_LOAD_ERROR_NONE;
560 return EINA_TRUE;
561
562close_file:
563 if (seg != NULL) eina_file_map_free(f, seg);
564 eina_file_close(f);
565 return EINA_FALSE;
566}
567
568static int
569module_open(Evas_Module *em)
570{
571 if (!em) return 0;
572 em->functions = (void *)(&evas_image_load_tga_func);
573 return 1;
574}
575
576static void
577module_close(Evas_Module *em __UNUSED__)
578{
579}
580
581static Evas_Module_Api evas_modapi =
582{
583 EVAS_MODULE_API_VERSION,
584 "tga",
585 "none",
586 {
587 module_open,
588 module_close
589 }
590};
591
592EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, tga);
593
594#ifndef EVAS_STATIC_BUILD_TGA
595EVAS_EINA_MODULE_DEFINE(image_loader, tga);
596#endif