diff options
author | Benjamin Otte <otte@redhat.com> | 2015-09-20 21:44:19 +0200 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2015-10-13 02:56:47 +0200 |
commit | b5577265295a7a631b7467a5d6fe7091a92f4ea8 (patch) | |
tree | 9de01bd15e4210c6e6712341f77087596148232e | |
parent | 40b3cd309ba68d1a3b4179015aeb5df92d0dc93d (diff) | |
download | gdk-pixbuf-b5577265295a7a631b7467a5d6fe7091a92f4ea8.tar.gz |
tga: Redo colormap handling
Always allocate a colormap struct, but only parse colors into
the colormap if the has_colormap flag is set in the header.
Allocating the colormap is important to not get failures when people
provide broken images - like a header indicating a pseudocolor image
but without a colormap.
-rw-r--r-- | gdk-pixbuf/io-tga.c | 108 |
1 files changed, 58 insertions, 50 deletions
diff --git a/gdk-pixbuf/io-tga.c b/gdk-pixbuf/io-tga.c index 58dba063e..8e950d504 100644 --- a/gdk-pixbuf/io-tga.c +++ b/gdk-pixbuf/io-tga.c @@ -327,6 +327,12 @@ static gboolean fill_in_context(TGAContext *ctx, GError **err) ctx->cmap_size = ((ctx->hdr->cmap_bpp + 7) >> 3) * LE16(ctx->hdr->cmap_n_colors); + ctx->cmap = colormap_new (LE16(ctx->hdr->cmap_n_colors)); + if (!ctx->cmap) { + g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, + _("Cannot allocate colormap")); + return FALSE; + } alpha = ((ctx->hdr->bpp == 16) || (ctx->hdr->bpp == 32) || @@ -461,60 +467,62 @@ static gboolean tga_load_colormap (TGAContext *ctx, GError **err) { - GBytes *bytes; - TGAColor color; - const guchar *p; - guint i, n_colors; - - g_return_val_if_fail(ctx != NULL, FALSE); - - bytes = gdk_pixbuf_buffer_queue_pull (ctx->input, ctx->cmap_size); - if (bytes == NULL) - return TRUE; + GBytes *bytes; + TGAColor color; + const guchar *p; + guint i, n_colors; - n_colors = LE16(ctx->hdr->cmap_n_colors); - ctx->cmap = colormap_new (n_colors); - if (!ctx->cmap) { - g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, - _("Cannot allocate colormap")); - return FALSE; - } + if (ctx->hdr->has_cmap) + { + bytes = gdk_pixbuf_buffer_queue_pull (ctx->input, ctx->cmap_size); + if (bytes == NULL) + return TRUE; - p = g_bytes_get_data (bytes, NULL); - color.a = 255; + n_colors = LE16(ctx->hdr->cmap_n_colors); + + p = g_bytes_get_data (bytes, NULL); + color.a = 255; + + for (i = 0; i < n_colors; i++) + { + if ((ctx->hdr->cmap_bpp == 15) || (ctx->hdr->cmap_bpp == 16)) + { + guint16 col = p[0] + (p[1] << 8); + color.b = (col >> 7) & 0xf8; + color.g = (col >> 2) & 0xf8; + color.r = col << 3; + p += 2; + } + else if ((ctx->hdr->cmap_bpp == 24) || (ctx->hdr->cmap_bpp == 32)) + { + color.b = *p++; + color.g = *p++; + color.r = *p++; + if (ctx->hdr->cmap_bpp == 32) + color.a = *p++; + } + else + { + g_set_error_literal (err, GDK_PIXBUF_ERROR, + GDK_PIXBUF_ERROR_CORRUPT_IMAGE, + _("Unexpected bitdepth for colormap entries")); + g_bytes_unref (bytes); + return FALSE; + } + colormap_set_color (ctx->cmap, i, &color); + } - for (i = 0; i < n_colors; i++) { - if ((ctx->hdr->cmap_bpp == 15) || (ctx->hdr->cmap_bpp == 16)) { - guint16 col = p[0] + (p[1] << 8); - color.b = (col >> 7) & 0xf8; - color.g = (col >> 2) & 0xf8; - color.r = col << 3; - p += 2; - } - else if ((ctx->hdr->cmap_bpp == 24) || (ctx->hdr->cmap_bpp == 32)) { - color.b = *p++; - color.g = *p++; - color.r = *p++; - if (ctx->hdr->cmap_bpp == 32) - color.a = *p++; - } else { - g_set_error_literal(err, GDK_PIXBUF_ERROR, - GDK_PIXBUF_ERROR_CORRUPT_IMAGE, - _("Unexpected bitdepth for colormap entries")); - g_bytes_unref (bytes); - return FALSE; - } - colormap_set_color (ctx->cmap, i, &color); - } - - if ((ctx->hdr->type == TGA_TYPE_RLE_PSEUDOCOLOR) - || (ctx->hdr->type == TGA_TYPE_RLE_TRUECOLOR) - || (ctx->hdr->type == TGA_TYPE_RLE_GRAYSCALE)) - ctx->process = tga_load_rle_image; - else - ctx->process = tga_load_image; + g_bytes_unref (bytes); + } + + if ((ctx->hdr->type == TGA_TYPE_RLE_PSEUDOCOLOR) + || (ctx->hdr->type == TGA_TYPE_RLE_TRUECOLOR) + || (ctx->hdr->type == TGA_TYPE_RLE_GRAYSCALE)) + ctx->process = tga_load_rle_image; + else + ctx->process = tga_load_image; - return TRUE; + return TRUE; } static gboolean |