1 /* -*- mode: C; c-file-style: "linux" -*- */
3 * GdkPixbuf library - TGA image loader
4 * Copyright (C) 1999 Nicola Girardi <nikke@swlibero.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
24 * Some NOTES about the TGA loader (2001/06/07, nikke@swlibero.org)
26 * - The TGAFooter isn't present in all TGA files. In fact, there's an older
27 * format specification, still in use, which doesn't cover the TGAFooter.
28 * Actually, most TGA files I have are of the older type. Anyway I put the
29 * struct declaration here for completeness.
31 * - Error handling was designed to be very paranoid.
38 #include "gdk-pixbuf-private.h"
39 #include "gdk-pixbuf-io.h"
43 #define TGA_INTERLEAVE_MASK 0xc0
44 #define TGA_INTERLEAVE_NONE 0x00
45 #define TGA_INTERLEAVE_2WAY 0x40
46 #define TGA_INTERLEAVE_4WAY 0x80
48 #define TGA_ORIGIN_MASK 0x30
49 #define TGA_ORIGIN_RIGHT 0x10
50 #define TGA_ORIGIN_UPPER 0x20
54 TGA_TYPE_PSEUDOCOLOR = 1,
55 TGA_TYPE_TRUECOLOR = 2,
56 TGA_TYPE_GRAYSCALE = 3,
57 TGA_TYPE_RLE_PSEUDOCOLOR = 9,
58 TGA_TYPE_RLE_TRUECOLOR = 10,
59 TGA_TYPE_RLE_GRAYSCALE = 11
62 #define LE16(p) ((p)[0] + ((p)[1] << 8))
64 typedef struct _IOBuffer IOBuffer;
66 typedef struct _TGAHeader TGAHeader;
67 typedef struct _TGAFooter TGAFooter;
69 typedef struct _TGAColormap TGAColormap;
70 typedef struct _TGAColor TGAColor;
72 typedef struct _TGAContext TGAContext;
80 guint8 cmap_n_colors[2];
94 guint32 extension_area_offset;
95 guint32 developer_directory_offset;
97 /* Standard TGA signature, "TRUEVISION-XFILE.\0". */
107 struct _TGAColormap {
119 guint completed_lines;
120 gboolean run_length_encoded;
127 guint pbuf_bytes_done;
132 gboolean skipped_info;
136 GdkPixbufModuleSizeFunc sfunc;
137 GdkPixbufModulePreparedFunc pfunc;
138 GdkPixbufModuleUpdatedFunc ufunc;
147 static IOBuffer *io_buffer_new(GError **err)
150 buffer = g_try_malloc(sizeof(IOBuffer));
152 g_set_error_literal(err, GDK_PIXBUF_ERROR,
153 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
154 _("Cannot allocate memory for IOBuffer struct"));
162 static IOBuffer *io_buffer_append(IOBuffer *buffer,
163 const guchar *data, guint len,
169 buffer->data = g_try_malloc(len);
171 g_set_error_literal(err, GDK_PIXBUF_ERROR,
172 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
173 _("Cannot allocate memory for IOBuffer data"));
177 g_memmove(buffer->data, data, len);
180 guchar *tmp = g_try_realloc (buffer->data, buffer->size + len);
182 g_set_error_literal(err, GDK_PIXBUF_ERROR,
183 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
184 _("Cannot realloc IOBuffer data"));
189 g_memmove(&buffer->data[buffer->size], data, len);
195 static IOBuffer *io_buffer_free_segment(IOBuffer *buffer,
199 g_return_val_if_fail(buffer != NULL, NULL);
200 g_return_val_if_fail(buffer->data != NULL, NULL);
201 if (count == buffer->size) {
202 g_free(buffer->data);
209 new_size = buffer->size - count;
210 new_buf = g_try_malloc(new_size);
212 g_set_error_literal(err, GDK_PIXBUF_ERROR,
213 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
214 _("Cannot allocate temporary IOBuffer data"));
215 g_free(buffer->data);
220 g_memmove(new_buf, &buffer->data[count], new_size);
221 g_free(buffer->data);
222 buffer->data = new_buf;
223 buffer->size = new_size;
228 static void io_buffer_free(IOBuffer *buffer)
230 g_return_if_fail(buffer != NULL);
231 g_free(buffer->data);
235 static void free_buffer(guchar *pixels, gpointer data)
240 static GdkPixbuf *get_contiguous_pixbuf (guint width,
245 guint channels, rowstride, bytes;
252 rowstride = width * channels;
254 if (rowstride / channels != width)
257 bytes = height * rowstride;
259 if (bytes / rowstride != height)
262 pixels = g_try_malloc (bytes);
267 return gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, has_alpha, 8,
268 width, height, rowstride, free_buffer, NULL);
271 static void pixbuf_flip_row (GdkPixbuf *pixbuf, guchar *ph)
278 s = p + pixbuf->n_channels * (pixbuf->width - 1);
280 for (count = pixbuf->n_channels; count > 0; count--, p++, s++) {
285 s -= 2 * pixbuf->n_channels;
289 static void pixbuf_flip_vertically (GdkPixbuf *pixbuf)
291 guchar *ph, *sh, *p, *s;
296 sh = pixbuf->pixels + pixbuf->height*pixbuf->rowstride;
297 while (ph < sh - pixbuf->rowstride) {
299 s = sh - pixbuf->rowstride;
300 for (count = pixbuf->n_channels * pixbuf->width; count > 0; count--, p++, s++) {
305 sh -= pixbuf->rowstride;
306 ph += pixbuf->rowstride;
310 static gboolean fill_in_context(TGAContext *ctx, GError **err)
315 g_return_val_if_fail(ctx != NULL, FALSE);
317 ctx->run_length_encoded =
318 ((ctx->hdr->type == TGA_TYPE_RLE_PSEUDOCOLOR)
319 || (ctx->hdr->type == TGA_TYPE_RLE_TRUECOLOR)
320 || (ctx->hdr->type == TGA_TYPE_RLE_GRAYSCALE));
322 if (ctx->hdr->has_cmap)
323 ctx->cmap_size = ((ctx->hdr->cmap_bpp + 7) >> 3) *
324 LE16(ctx->hdr->cmap_n_colors);
326 alpha = ((ctx->hdr->bpp == 16) ||
327 (ctx->hdr->bpp == 32) ||
328 (ctx->hdr->has_cmap && (ctx->hdr->cmap_bpp == 32)));
330 w = LE16(ctx->hdr->width);
331 h = LE16(ctx->hdr->height);
337 (*ctx->sfunc) (&wi, &hi, ctx->udata);
339 if (wi == 0 || hi == 0)
343 ctx->pbuf = get_contiguous_pixbuf (w, h, alpha);
346 g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
347 _("Cannot allocate new pixbuf"));
351 ctx->pbuf_bytes = ctx->pbuf->rowstride * ctx->pbuf->height;
352 if ((ctx->hdr->flags & TGA_ORIGIN_UPPER) || ctx->run_length_encoded)
353 ctx->pptr = ctx->pbuf->pixels;
355 ctx->pptr = ctx->pbuf->pixels + (ctx->pbuf->height - 1)*ctx->pbuf->rowstride;
357 if (ctx->hdr->type == TGA_TYPE_PSEUDOCOLOR)
358 ctx->rowstride = ctx->pbuf->width;
359 else if (ctx->hdr->type == TGA_TYPE_GRAYSCALE)
360 ctx->rowstride = (alpha ? ctx->pbuf->width * 2 : ctx->pbuf->width);
361 else if (ctx->hdr->type == TGA_TYPE_TRUECOLOR)
362 ctx->rowstride = ctx->pbuf->rowstride;
364 ctx->completed_lines = 0;
368 static void parse_data_for_row_pseudocolor(TGAContext *ctx)
370 guchar *s = ctx->in->data;
371 guint upper_bound = ctx->pbuf->width;
372 guchar *p = ctx->pptr;
374 for (; upper_bound; upper_bound--, s++) {
375 *p++ = ctx->cmap->cols[*s].r;
376 *p++ = ctx->cmap->cols[*s].g;
377 *p++ = ctx->cmap->cols[*s].b;
378 if (ctx->hdr->cmap_bpp == 32)
379 *p++ = ctx->cmap->cols[*s].a;
383 static void swap_channels(TGAContext *ctx)
387 guchar *p = ctx->pptr;
388 for (count = ctx->pbuf->width; count; count--) {
392 p += ctx->pbuf->n_channels;
396 static void parse_data_for_row_truecolor(TGAContext *ctx)
398 g_memmove(ctx->pptr, ctx->in->data, ctx->pbuf->rowstride);
402 static void parse_data_for_row_grayscale(TGAContext *ctx)
404 guchar *s = ctx->in->data;
405 guint upper_bound = ctx->pbuf->width;
407 guchar *p = ctx->pptr;
408 for (; upper_bound; upper_bound--) {
409 p[0] = p[1] = p[2] = *s++;
410 if (ctx->pbuf->n_channels == 4)
412 p += ctx->pbuf->n_channels;
416 static gboolean parse_data_for_row(TGAContext *ctx, GError **err)
420 if (ctx->hdr->type == TGA_TYPE_PSEUDOCOLOR)
421 parse_data_for_row_pseudocolor(ctx);
422 else if (ctx->hdr->type == TGA_TYPE_TRUECOLOR)
423 parse_data_for_row_truecolor(ctx);
424 else if (ctx->hdr->type == TGA_TYPE_GRAYSCALE)
425 parse_data_for_row_grayscale(ctx);
427 if (ctx->hdr->flags & TGA_ORIGIN_RIGHT)
428 pixbuf_flip_row (ctx->pbuf, ctx->pptr);
429 if (ctx->hdr->flags & TGA_ORIGIN_UPPER)
430 ctx->pptr += ctx->pbuf->rowstride;
432 ctx->pptr -= ctx->pbuf->rowstride;
433 ctx->pbuf_bytes_done += ctx->pbuf->rowstride;
434 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes)
437 ctx->in = io_buffer_free_segment(ctx->in, ctx->rowstride, err);
440 row = (ctx->pptr - ctx->pbuf->pixels) / ctx->pbuf->rowstride - 1;
442 (*ctx->ufunc) (ctx->pbuf, 0, row, ctx->pbuf->width, 1, ctx->udata);
446 static void write_rle_data(TGAContext *ctx, TGAColor *color, guint *rle_count)
448 for (; *rle_count; (*rle_count)--) {
449 g_memmove(ctx->pptr, (guchar *) color, ctx->pbuf->n_channels);
450 ctx->pptr += ctx->pbuf->n_channels;
451 ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
452 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes)
457 static guint parse_rle_data_pseudocolor(TGAContext *ctx)
459 guint rle_num, raw_num;
463 g_return_val_if_fail(ctx->in->size > 0, 0);
466 for (n = 0; n < ctx->in->size; ) {
470 if (n == ctx->in->size) {
473 rle_num = (tag & 0x7f) + 1;
474 write_rle_data(ctx, &ctx->cmap->cols[*s], &rle_num);
476 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
483 if (n + raw_num >= ctx->in->size) {
486 for (; raw_num; raw_num--) {
488 ctx->cmap->cols[*s].r;
490 ctx->cmap->cols[*s].g;
492 ctx->cmap->cols[*s].b;
493 if (ctx->pbuf->n_channels == 4)
494 *ctx->pptr++ = ctx->cmap->cols[*s].a;
496 ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
497 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
506 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes)
512 static guint parse_rle_data_truecolor(TGAContext *ctx)
515 guint rle_num, raw_num;
519 g_return_val_if_fail(ctx->in->size > 0, 0);
522 for (n = 0; n < ctx->in->size; ) {
526 if (n + ctx->pbuf->n_channels >= ctx->in->size) {
529 rle_num = (tag & 0x7f) + 1;
533 if (ctx->hdr->bpp == 32)
535 n += ctx->pbuf->n_channels;
536 write_rle_data(ctx, &col, &rle_num);
537 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
544 if (n + (raw_num * ctx->pbuf->n_channels) >= ctx->in->size) {
547 for (; raw_num; raw_num--) {
551 if (ctx->hdr->bpp == 32)
553 n += ctx->pbuf->n_channels;
554 ctx->pptr += ctx->pbuf->n_channels;
555 ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
556 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
562 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
569 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes)
574 static guint parse_rle_data_grayscale(TGAContext *ctx)
577 guint rle_num, raw_num;
581 g_return_val_if_fail(ctx->in->size > 0, 0);
584 for (n = 0; n < ctx->in->size; ) {
588 if (n + (ctx->pbuf->n_channels == 4 ? 2 : 1) >= ctx->in->size) {
591 rle_num = (tag & 0x7f) + 1;
592 tone.r = tone.g = tone.b = *s;
594 if (ctx->pbuf->n_channels == 4) {
598 write_rle_data(ctx, &tone, &rle_num);
599 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
606 if (n + raw_num * (ctx->pbuf->n_channels == 4 ? 2 : 1) >= ctx->in->size) {
609 for (; raw_num; raw_num--) {
610 ctx->pptr[0] = ctx->pptr[1] = ctx->pptr[2] = *s;
612 if (ctx->pbuf->n_channels == 4) {
616 ctx->pptr += ctx->pbuf->n_channels;
617 ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
618 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
626 if (ctx->pbuf_bytes_done == ctx->pbuf_bytes)
631 static gboolean parse_rle_data(TGAContext *ctx, GError **err)
635 guint bytes_done_before = ctx->pbuf_bytes_done;
637 if (ctx->hdr->type == TGA_TYPE_RLE_PSEUDOCOLOR)
638 count = parse_rle_data_pseudocolor(ctx);
639 else if (ctx->hdr->type == TGA_TYPE_RLE_TRUECOLOR)
640 count = parse_rle_data_truecolor(ctx);
641 else if (ctx->hdr->type == TGA_TYPE_RLE_GRAYSCALE)
642 count = parse_rle_data_grayscale(ctx);
644 if (ctx->hdr->flags & TGA_ORIGIN_RIGHT) {
645 guchar *row = ctx->pbuf->pixels + (bytes_done_before / ctx->pbuf->rowstride) * ctx->pbuf->rowstride;
646 guchar *row_after = ctx->pbuf->pixels + (ctx->pbuf_bytes_done / ctx->pbuf->rowstride) * ctx->pbuf->rowstride;
647 for (; row < row_after; row += ctx->pbuf->rowstride)
648 pixbuf_flip_row (ctx->pbuf, row);
651 ctx->in = io_buffer_free_segment(ctx->in, count, err);
656 /* FIXME doing the vertical flipping afterwards is not
657 * perfect, but doing it during the rle decoding in place
658 * is considerably more work.
660 if (!(ctx->hdr->flags & TGA_ORIGIN_UPPER)) {
661 pixbuf_flip_vertically (ctx->pbuf);
662 ctx->hdr->flags |= TGA_ORIGIN_UPPER;
667 rows = ctx->pbuf_bytes_done / ctx->pbuf->rowstride - bytes_done_before / ctx->pbuf->rowstride;
669 (*ctx->ufunc) (ctx->pbuf, 0, bytes_done_before / ctx->pbuf->rowstride,
670 ctx->pbuf->width, rows,
676 static gboolean try_colormap(TGAContext *ctx, GError **err)
681 g_return_val_if_fail(ctx != NULL, FALSE);
682 g_return_val_if_fail(ctx->cmap_size > 0, TRUE);
684 ctx->cmap = g_try_malloc(sizeof(TGAColormap));
686 g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
687 _("Cannot allocate colormap structure"));
690 ctx->cmap->size = LE16(ctx->hdr->cmap_n_colors);
691 ctx->cmap->cols = g_try_malloc(sizeof(TGAColor) * ctx->cmap->size);
692 if (!ctx->cmap->cols) {
693 g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
694 _("Cannot allocate colormap entries"));
699 for (n = 0; n < ctx->cmap->size; n++) {
700 if ((ctx->hdr->cmap_bpp == 15) || (ctx->hdr->cmap_bpp == 16)) {
701 guint16 col = p[0] + (p[1] << 8);
702 ctx->cmap->cols[n].b = (col >> 7) & 0xf8;
703 ctx->cmap->cols[n].g = (col >> 2) & 0xf8;
704 ctx->cmap->cols[n].r = col << 3;
707 else if ((ctx->hdr->cmap_bpp == 24) || (ctx->hdr->cmap_bpp == 32)) {
708 ctx->cmap->cols[n].b = *p++;
709 ctx->cmap->cols[n].g = *p++;
710 ctx->cmap->cols[n].r = *p++;
711 if (ctx->hdr->cmap_bpp == 32)
712 ctx->cmap->cols[n].a = *p++;
714 g_set_error_literal(err, GDK_PIXBUF_ERROR,
715 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
716 _("Unexpected bitdepth for colormap entries"));
720 ctx->in = io_buffer_free_segment(ctx->in, ctx->cmap_size, err);
726 static gboolean try_preload(TGAContext *ctx, GError **err)
729 if (ctx->in->size >= sizeof(TGAHeader)) {
730 ctx->hdr = g_try_malloc(sizeof(TGAHeader));
732 g_set_error_literal(err, GDK_PIXBUF_ERROR,
733 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
734 _("Cannot allocate TGA header memory"));
737 g_memmove(ctx->hdr, ctx->in->data, sizeof(TGAHeader));
738 ctx->in = io_buffer_free_segment(ctx->in, sizeof(TGAHeader), err);
740 g_print ("infolen %d "
746 "x %d y %d width %d height %d bpp %d "
751 LE16(ctx->hdr->cmap_start),
752 LE16(ctx->hdr->cmap_n_colors),
754 LE16(ctx->hdr->x_origin),
755 LE16(ctx->hdr->y_origin),
756 LE16(ctx->hdr->width),
757 LE16(ctx->hdr->height),
763 if (LE16(ctx->hdr->width) == 0 ||
764 LE16(ctx->hdr->height) == 0) {
765 g_set_error_literal(err, GDK_PIXBUF_ERROR,
766 GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
767 _("TGA image has invalid dimensions"));
770 if ((ctx->hdr->flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE) {
771 g_set_error_literal(err, GDK_PIXBUF_ERROR,
772 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
773 _("TGA image type not supported"));
776 switch (ctx->hdr->type) {
777 case TGA_TYPE_PSEUDOCOLOR:
778 case TGA_TYPE_RLE_PSEUDOCOLOR:
779 if (ctx->hdr->bpp != 8) {
780 g_set_error_literal(err, GDK_PIXBUF_ERROR,
781 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
782 _("TGA image type not supported"));
786 case TGA_TYPE_TRUECOLOR:
787 case TGA_TYPE_RLE_TRUECOLOR:
788 if (ctx->hdr->bpp != 24 &&
789 ctx->hdr->bpp != 32) {
790 g_set_error_literal(err, GDK_PIXBUF_ERROR,
791 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
792 _("TGA image type not supported"));
796 case TGA_TYPE_GRAYSCALE:
797 case TGA_TYPE_RLE_GRAYSCALE:
798 if (ctx->hdr->bpp != 8 &&
799 ctx->hdr->bpp != 16) {
800 g_set_error_literal(err, GDK_PIXBUF_ERROR,
801 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
802 _("TGA image type not supported"));
807 g_set_error_literal(err, GDK_PIXBUF_ERROR,
808 GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
809 _("TGA image type not supported"));
812 if (!fill_in_context(ctx, err))
818 if (!ctx->skipped_info) {
819 if (ctx->in->size >= ctx->hdr->infolen) {
820 ctx->in = io_buffer_free_segment(ctx->in, ctx->hdr->infolen, err);
823 ctx->skipped_info = TRUE;
828 if (ctx->hdr->has_cmap && !ctx->cmap) {
829 if (ctx->in->size >= ctx->cmap_size) {
830 if (!try_colormap(ctx, err))
836 if (!ctx->prepared) {
838 (*ctx->pfunc) (ctx->pbuf, NULL, ctx->udata);
839 ctx->prepared = TRUE;
841 /* We shouldn't get here anyway. */
845 static gpointer gdk_pixbuf__tga_begin_load(GdkPixbufModuleSizeFunc f0,
846 GdkPixbufModulePreparedFunc f1,
847 GdkPixbufModuleUpdatedFunc f2,
848 gpointer udata, GError **err)
852 ctx = g_try_malloc(sizeof(TGAContext));
854 g_set_error_literal(err, GDK_PIXBUF_ERROR,
855 GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
856 _("Cannot allocate memory for TGA context struct"));
862 ctx->run_length_encoded = FALSE;
869 ctx->pbuf_bytes_done = 0;
872 ctx->in = io_buffer_new(err);
878 ctx->skipped_info = FALSE;
879 ctx->prepared = FALSE;
890 static gboolean gdk_pixbuf__tga_load_increment(gpointer data,
891 const guchar *buffer,
895 TGAContext *ctx = (TGAContext*) data;
896 g_return_val_if_fail(ctx != NULL, FALSE);
901 g_return_val_if_fail(buffer != NULL, TRUE);
902 ctx->in = io_buffer_append(ctx->in, buffer, size, err);
905 if (!ctx->prepared) {
906 if (!try_preload(ctx, err))
910 if (ctx->in->size == 0)
914 if (ctx->run_length_encoded) {
915 if (!parse_rle_data(ctx, err))
918 while (ctx->in->size >= ctx->rowstride) {
919 if (ctx->completed_lines >= ctx->pbuf->height) {
920 g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED,
921 _("Excess data in file"));
924 if (!parse_data_for_row(ctx, err))
926 ctx->completed_lines++;
933 static gboolean gdk_pixbuf__tga_stop_load(gpointer data, GError **err)
935 TGAContext *ctx = (TGAContext *) data;
936 g_return_val_if_fail(ctx != NULL, FALSE);
939 (ctx->hdr->flags & TGA_ORIGIN_UPPER) == 0 &&
940 ctx->run_length_encoded &&
942 pixbuf_flip_vertically (ctx->pbuf);
944 (*ctx->ufunc) (ctx->pbuf, 0, 0,
945 ctx->pbuf->width, ctx->pbuf->height,
950 g_free (ctx->cmap->cols);
954 g_object_unref (ctx->pbuf);
955 if (ctx->in && ctx->in->size)
956 ctx->in = io_buffer_free_segment (ctx->in, ctx->in->size, err);
961 io_buffer_free (ctx->in);
967 #define MODULE_ENTRY(function) G_MODULE_EXPORT void function
969 #define MODULE_ENTRY(function) void _gdk_pixbuf__tga_ ## function
972 MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
974 module->begin_load = gdk_pixbuf__tga_begin_load;
975 module->stop_load = gdk_pixbuf__tga_stop_load;
976 module->load_increment = gdk_pixbuf__tga_load_increment;
979 MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
981 static GdkPixbufModulePattern signature[] = {
982 { " \x1\x1", "x ", 100 },
983 { " \x1\x9", "x ", 100 },
984 { " \x2", "xz ", 99 }, /* only 99 since .CUR also matches this */
985 { " \x3", "xz ", 100 },
986 { " \xa", "xz ", 100 },
987 { " \xb", "xz ", 100 },
990 static gchar * mime_types[] = {
994 static gchar * extensions[] = {
1001 info->signature = signature;
1002 info->description = N_("The Targa image format");
1003 info->mime_types = mime_types;
1004 info->extensions = extensions;
1005 info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
1006 info->license = "LGPL";