Commit edf6fb8d authored by Benjamin Otte's avatar Benjamin Otte

tga: Wrap TGAColormap struct in its own API

Instead of poking into it directly.
parent 19f9685d
......@@ -63,8 +63,8 @@ typedef struct _IOBuffer IOBuffer;
typedef struct _TGAHeader TGAHeader;
typedef struct _TGAFooter TGAFooter;
typedef struct _TGAColormap TGAColormap;
typedef struct _TGAColor TGAColor;
typedef struct _TGAColormap TGAColormap;
typedef struct _TGAContext TGAContext;
......@@ -101,15 +101,15 @@ struct _TGAFooter {
} sig;
};
struct _TGAColormap {
gint size;
TGAColor *cols;
};
struct _TGAColor {
guchar r, g, b, a;
};
struct _TGAColormap {
guint n_colors;
TGAColor colors[1];
};
struct _TGAContext {
TGAHeader *hdr;
guint rowstride;
......@@ -234,6 +234,51 @@ static void free_buffer(guchar *pixels, gpointer data)
g_free(pixels);
}
static TGAColormap *
colormap_new (guint n_colors)
{
TGAColormap *cmap;
g_assert (n_colors <= G_MAXUINT16);
cmap = g_try_malloc0 (sizeof (TGAColormap) + (MAX (n_colors, 1) - 1) * sizeof (TGAColor));
if (cmap == NULL)
return NULL;
cmap->n_colors = n_colors;
return cmap;
}
static const TGAColor *
colormap_get_color (TGAColormap *cmap,
guint id)
{
static const TGAColor transparent_black = { 0, 0, 0, 0 };
if (id >= cmap->n_colors)
return &transparent_black;
return &cmap->colors[id];
}
static void
colormap_set_color (TGAColormap *cmap,
guint id,
const TGAColor *color)
{
if (id >= cmap->n_colors)
return;
cmap->colors[id] = *color;
}
static void
colormap_free (TGAColormap *cmap)
{
g_free (cmap);
}
static GdkPixbuf *get_contiguous_pixbuf (guint width,
guint height,
gboolean has_alpha)
......@@ -364,11 +409,12 @@ static void parse_data_for_row_pseudocolor(TGAContext *ctx)
guchar *p = ctx->pptr;
for (; upper_bound; upper_bound--, s++) {
*p++ = ctx->cmap->cols[*s].r;
*p++ = ctx->cmap->cols[*s].g;
*p++ = ctx->cmap->cols[*s].b;
const TGAColor *color = colormap_get_color (ctx->cmap, *s);
*p++ = color->r;
*p++ = color->g;
*p++ = color->b;
if (ctx->hdr->cmap_bpp == 32)
*p++ = ctx->cmap->cols[*s].a;
*p++ = color->a;
}
}
......@@ -435,7 +481,7 @@ static gboolean parse_data_for_row(TGAContext *ctx, GError **err)
return TRUE;
}
static void write_rle_data(TGAContext *ctx, TGAColor *color, guint *rle_count)
static void write_rle_data(TGAContext *ctx, const TGAColor *color, guint *rle_count)
{
for (; *rle_count; (*rle_count)--) {
g_memmove(ctx->pptr, (guchar *) color, ctx->pbuf->n_channels);
......@@ -463,7 +509,7 @@ static guint parse_rle_data_pseudocolor(TGAContext *ctx)
return --n;
} else {
rle_num = (tag & 0x7f) + 1;
write_rle_data(ctx, &ctx->cmap->cols[*s], &rle_num);
write_rle_data(ctx, colormap_get_color (ctx->cmap, *s), &rle_num);
s++, n++;
if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
ctx->done = TRUE;
......@@ -476,14 +522,12 @@ static guint parse_rle_data_pseudocolor(TGAContext *ctx)
return --n;
} else {
for (; raw_num; raw_num--) {
*ctx->pptr++ =
ctx->cmap->cols[*s].r;
*ctx->pptr++ =
ctx->cmap->cols[*s].g;
*ctx->pptr++ =
ctx->cmap->cols[*s].b;
const TGAColor *color = colormap_get_color (ctx->cmap, *s);
*ctx->pptr++ = color->r;
*ctx->pptr++ = color->g;
*ctx->pptr++ = color->b;
if (ctx->pbuf->n_channels == 4)
*ctx->pptr++ = ctx->cmap->cols[*s].a;
*ctx->pptr++ = color->a;
s++, n++;
ctx->pbuf_bytes_done += ctx->pbuf->n_channels;
if (ctx->pbuf_bytes_done == ctx->pbuf_bytes) {
......@@ -667,8 +711,9 @@ static gboolean parse_rle_data(TGAContext *ctx, GError **err)
static gboolean try_colormap(TGAContext *ctx, GError **err)
{
static guchar *p;
static guint n;
TGAColor color;
guchar *p;
guint i, n_colors;
g_return_val_if_fail(ctx != NULL, FALSE);
......@@ -679,41 +724,38 @@ static gboolean try_colormap(TGAContext *ctx, GError **err)
return FALSE;
}
ctx->cmap = g_try_malloc(sizeof(TGAColormap));
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 structure"));
return FALSE;
}
ctx->cmap->size = LE16(ctx->hdr->cmap_n_colors);
ctx->cmap->cols = g_try_malloc(sizeof(TGAColor) * ctx->cmap->size);
if (!ctx->cmap->cols) {
g_set_error_literal(err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
_("Cannot allocate colormap entries"));
_("Cannot allocate colormap"));
return FALSE;
}
p = ctx->in->data;
for (n = 0; n < ctx->cmap->size; n++) {
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);
ctx->cmap->cols[n].b = (col >> 7) & 0xf8;
ctx->cmap->cols[n].g = (col >> 2) & 0xf8;
ctx->cmap->cols[n].r = col << 3;
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)) {
ctx->cmap->cols[n].b = *p++;
ctx->cmap->cols[n].g = *p++;
ctx->cmap->cols[n].r = *p++;
color.b = *p++;
color.g = *p++;
color.r = *p++;
if (ctx->hdr->cmap_bpp == 32)
ctx->cmap->cols[n].a = *p++;
color.a = *p++;
} else {
g_set_error_literal(err, GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
_("Unexpected bitdepth for colormap entries"));
return FALSE;
}
colormap_set_color (ctx->cmap, i, &color);
}
ctx->in = io_buffer_free_segment(ctx->in, ctx->cmap_size, err);
if (!ctx->in)
......@@ -944,10 +986,8 @@ static gboolean gdk_pixbuf__tga_stop_load(gpointer data, GError **err)
ctx->udata);
}
g_free (ctx->hdr);
if (ctx->cmap) {
g_free (ctx->cmap->cols);
g_free (ctx->cmap);
}
if (ctx->cmap)
colormap_free (ctx->cmap);
if (ctx->pbuf)
g_object_unref (ctx->pbuf);
if (ctx->in && ctx->in->size)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment