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