plug-ins: bmp import - simplify dest/offset handling

the offset to the dest buffer passed to the line-reading functions
wasn't counting bytes but items/values, which was slightly confusing.
Changed to not pass the offset at all, but rather a pointer to the
start of a line inside the buffer.
Also made rowstride count bytes, not values.
Made dest and rowstride local vars, as they are not used anywhere else.
This commit is contained in:
Rupert 2024-12-22 13:35:18 +01:00 committed by Jacob Boerema
parent 373f4821c3
commit 565ead32b8

View file

@ -68,8 +68,6 @@ struct Fileinfo
guchar *rowbuf; guchar *rowbuf;
guint64 bytes_per_row; guint64 bytes_per_row;
gint bpp; gint bpp;
guchar *dest;
gsize rowstride;
gint channels; gint channels;
gint bytesperchannel; gint bytesperchannel;
gint ncolors; gint ncolors;
@ -94,15 +92,15 @@ static GimpImage * ReadImage (struct Fileinfo *fi,
GError **error); GError **error);
static gint load_rgb_64 (struct Fileinfo *fi, static gint load_rgb_64 (struct Fileinfo *fi,
gsize offset); guchar *dest);
static gint load_rgb (struct Fileinfo *fi, static gint load_rgb (struct Fileinfo *fi,
gsize offset); guchar *dest);
static gint load_indexed (struct Fileinfo *fi, static gint load_indexed (struct Fileinfo *fi,
gsize offset); guchar *dest);
static gint load_rle (struct Fileinfo *fi, static gint load_rle (struct Fileinfo *fi,
gsize offset); guchar *dest);
static gint load_huffman (struct Fileinfo *fi, static gint load_huffman (struct Fileinfo *fi,
gsize offset); guchar *dest);
static gint huff_decode (guint32 *bitbuf, static gint huff_decode (guint32 *bitbuf,
gint *buflen, gint *buflen,
@ -679,7 +677,9 @@ ReadImage (struct Fileinfo *fi,
GimpImageType image_type; GimpImageType image_type;
GimpPrecision precision_type = GIMP_PRECISION_U8_NON_LINEAR; GimpPrecision precision_type = GIMP_PRECISION_U8_NON_LINEAR;
const Babl *format = NULL; const Babl *format = NULL;
guchar *dest = NULL;
gsize dest_size = 0; gsize dest_size = 0;
gsize rowstride;
gint maxbits; gint maxbits;
gint eof = FALSE; gint eof = FALSE;
enum Bmpformat bmpfmt = 0; enum Bmpformat bmpfmt = 0;
@ -790,16 +790,16 @@ ReadImage (struct Fileinfo *fi,
if ((guint64) fi->width * fi->tile_height < G_MAXSIZE / (fi->channels * fi->bytesperchannel)) if ((guint64) fi->width * fi->tile_height < G_MAXSIZE / (fi->channels * fi->bytesperchannel))
{ {
dest_size = (gsize) fi->width * fi->tile_height * fi->channels * fi->bytesperchannel; dest_size = (gsize) fi->width * fi->tile_height * fi->channels * fi->bytesperchannel;
fi->dest = g_try_malloc0 (dest_size); dest = g_try_malloc0 (dest_size);
fi->rowbuf = g_try_malloc (MAX (4, fi->bytes_per_row)); fi->rowbuf = g_try_malloc (MAX (4, fi->bytes_per_row));
} }
if (! (fi->dest && fi->rowbuf)) if (! (dest && fi->rowbuf))
{ {
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
_("Image dimensions too large: width %d x height %d"), _("Image dimensions too large: width %d x height %d"),
fi->width, fi->height); fi->width, fi->height);
g_free (fi->dest); g_free (dest);
g_free (fi->rowbuf); g_free (fi->rowbuf);
return NULL; return NULL;
} }
@ -813,7 +813,7 @@ ReadImage (struct Fileinfo *fi,
gimp_image_insert_layer (image, layer, NULL, 0); gimp_image_insert_layer (image, layer, NULL, 0);
buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
fi->rowstride = (gsize) fi->width * fi->channels; rowstride = (gsize) fi->width * fi->channels * fi->bytesperchannel;
cur_progress = 0; cur_progress = 0;
max_progress = fi->height; max_progress = fi->height;
@ -823,22 +823,22 @@ ReadImage (struct Fileinfo *fi,
for (ypos = fi->height - 1; ypos >= 0 && ! eof; ypos--) for (ypos = fi->height - 1; ypos >= 0 && ! eof; ypos--)
{ {
gsize offset = (fi->tile_height - fi->tile_n - 1) * fi->rowstride; gsize offset = (fi->tile_height - fi->tile_n - 1) * rowstride;
switch (bmpfmt) switch (bmpfmt)
{ {
case BMPFMT_RGB: case BMPFMT_RGB:
if (! load_rgb (fi, offset)) if (! load_rgb (fi, dest + offset))
eof = TRUE; eof = TRUE;
break; break;
case BMPFMT_RGB_64: case BMPFMT_RGB_64:
if (! load_rgb_64 (fi, offset)) if (! load_rgb_64 (fi, dest + offset))
eof = TRUE; eof = TRUE;
break; break;
case BMPFMT_INDEXED: case BMPFMT_INDEXED:
if (! load_indexed (fi, offset)) if (! load_indexed (fi, dest + offset))
eof = TRUE; eof = TRUE;
break; break;
@ -846,12 +846,12 @@ ReadImage (struct Fileinfo *fi,
if (fi->file_ypos < ypos) if (fi->file_ypos < ypos)
break; break;
if (! load_rle (fi, offset)) if (! load_rle (fi, dest + offset))
eof = TRUE; eof = TRUE;
break; break;
case BMPFMT_HUFFMAN: case BMPFMT_HUFFMAN:
if (! load_huffman (fi, offset)) if (! load_huffman (fi, dest + offset))
eof = TRUE; eof = TRUE;
break; break;
} }
@ -865,18 +865,18 @@ ReadImage (struct Fileinfo *fi,
/* we are filling the dest buffer backwards, so we need an offset to dest in /* we are filling the dest buffer backwards, so we need an offset to dest in
* case the tile_height isn't fully used (when tile_n < tile_height) * case the tile_height isn't fully used (when tile_n < tile_height)
*/ */
gsize offs = (fi->tile_height - fi->tile_n) * fi->rowstride * fi->bytesperchannel; offset = (fi->tile_height - fi->tile_n) * rowstride;
gegl_buffer_set (buffer, GEGL_RECTANGLE (0, ypos, fi->width, fi->tile_n), 0, format, gegl_buffer_set (buffer, GEGL_RECTANGLE (0, ypos, fi->width, fi->tile_n), 0, format,
fi->dest + offs, GEGL_AUTO_ROWSTRIDE); dest + offset, GEGL_AUTO_ROWSTRIDE);
memset (fi->dest, 0, dest_size); memset (dest, 0, dest_size);
fi->tile_n = 0; fi->tile_n = 0;
} }
} }
g_object_unref (buffer); g_object_unref (buffer);
g_free (fi->dest); g_free (dest);
if (! fi->gray && fi->bpp <= 8) if (! fi->gray && fi->bpp <= 8)
gimp_palette_set_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"), gimp_palette_set_colormap (gimp_image_get_palette (image), babl_format ("R'G'B' u8"),
@ -891,21 +891,19 @@ ReadImage (struct Fileinfo *fi,
} }
static gint static gint
load_rgb (struct Fileinfo *fi, gsize offset) load_rgb (struct Fileinfo *fi, guchar *dest)
{ {
gint xpos, i; gint xpos, i;
gint32 px; gint32 px;
gdouble d; gdouble d;
guchar *dest8;
guint16 *dest16; guint16 *dest16;
guint32 *dest32; guint32 *dest32;
if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row)) if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row))
return FALSE; return FALSE;
dest8 = fi->dest + fi->bytesperchannel * offset; dest16 = (guint16 *) dest;
dest16 = (guint16 *) dest8; dest32 = (guint32 *) dest;
dest32 = (guint32 *) dest8;
for (xpos = 0; xpos < fi->width; xpos++) for (xpos = 0; xpos < fi->width; xpos++)
{ {
@ -915,7 +913,7 @@ load_rgb (struct Fileinfo *fi, gsize offset)
d = ((px & fi->masks[i].mask) >> fi->masks[i].shiftin) / fi->masks[i].max_value; d = ((px & fi->masks[i].mask) >> fi->masks[i].shiftin) / fi->masks[i].max_value;
if (fi->bytesperchannel == 1) if (fi->bytesperchannel == 1)
*dest8++ = d * 0x00ff + 0.5; *dest++ = d * 0x00ff + 0.5;
else if (fi->bytesperchannel == 2) else if (fi->bytesperchannel == 2)
*dest16++ = d * 0xffffUL + 0.5; *dest16++ = d * 0xffffUL + 0.5;
else else
@ -926,7 +924,7 @@ load_rgb (struct Fileinfo *fi, gsize offset)
} }
static gint static gint
load_rgb_64 (struct Fileinfo *fi, gsize offset) load_rgb_64 (struct Fileinfo *fi, guchar *dest)
{ {
gint xpos, i; gint xpos, i;
gfloat *destflt; gfloat *destflt;
@ -934,7 +932,7 @@ load_rgb_64 (struct Fileinfo *fi, gsize offset)
if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row)) if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row))
return FALSE; return FALSE;
destflt = (gfloat *) fi->dest + offset; destflt = (gfloat *) dest;
for (xpos = 0; xpos < fi->width; ++xpos) for (xpos = 0; xpos < fi->width; ++xpos)
{ {
@ -953,15 +951,13 @@ load_rgb_64 (struct Fileinfo *fi, gsize offset)
} }
static gint static gint
load_indexed (struct Fileinfo *fi, gsize offset) load_indexed (struct Fileinfo *fi, guchar *dest)
{ {
gint xpos, val, shift; gint xpos, val, shift;
guchar *dest;
if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row)) if (! ReadOK (fi->file, fi->rowbuf, fi->bytes_per_row))
return FALSE; return FALSE;
dest = fi->dest + offset;
for (xpos = 0; xpos < fi->width; xpos++) for (xpos = 0; xpos < fi->width; xpos++)
{ {
val = fi->rowbuf[xpos / (8 / fi->bpp)]; val = fi->rowbuf[xpos / (8 / fi->bpp)];
@ -977,7 +973,7 @@ load_indexed (struct Fileinfo *fi, gsize offset)
} }
static gint static gint
load_rle (struct Fileinfo *fi, gsize offset) load_rle (struct Fileinfo *fi, guchar *basedest)
{ {
gint shift, i, j; gint shift, i, j;
guchar *dest; guchar *dest;
@ -1005,13 +1001,13 @@ load_rle (struct Fileinfo *fi, gsize offset)
i++, fi->xpos++, j++) i++, fi->xpos++, j++)
{ {
shift = 8 - i * fi->bpp; shift = 8 - i * fi->bpp;
dest = fi->dest + offset + fi->xpos * fi->channels; dest = basedest + fi->xpos * fi->channels;
dest[0] = (fi->rowbuf[1] & (((1 << fi->bpp) - 1) << shift)) >> shift; dest[0] = (fi->rowbuf[1] & (((1 << fi->bpp) - 1) << shift)) >> shift;
dest[0] = MIN (dest[0], fi->ncolors - 1); dest[0] = MIN (dest[0], fi->ncolors - 1);
if (fi->gray) if (fi->gray)
dest[0] = fi->colormap[dest[0] * 3]; dest[0] = fi->colormap[dest[0] * 3];
dest[1] = 0xff; /* alpha */ dest[1] = 0xff; /* alpha */
} }
} }
} }
@ -1026,11 +1022,9 @@ load_rle (struct Fileinfo *fi, gsize offset)
} }
for (i = 0; (i < fi->rowbuf[0]) && (fi->xpos < fi->width); i++, fi->xpos++) for (i = 0; (i < fi->rowbuf[0]) && (fi->xpos < fi->width); i++, fi->xpos++)
{ {
dest = fi->dest + offset + fi->xpos * fi->channels; dest = basedest + fi->xpos * fi->channels;
for (gint c = 0; c < 3; c++) for (gint c = 0; c < 3; c++)
{ dest[2 - c] = fi->rowbuf[1 + c];
dest[2 - c] = fi->rowbuf[c + 1];
}
dest[3] = 0xff; /* alpha */ dest[3] = 0xff; /* alpha */
} }
} }
@ -1053,7 +1047,7 @@ load_rle (struct Fileinfo *fi, gsize offset)
} }
} }
dest = fi->dest + offset + fi->xpos * fi->channels; dest = basedest + fi->xpos * fi->channels;
switch (fi->bpp) switch (fi->bpp)
{ {
case 8: case 8:
@ -1063,10 +1057,8 @@ load_rle (struct Fileinfo *fi, gsize offset)
dest[0] = (fi->rowbuf[0] >> (4 * ((i + 1) % 2))) & 0x0f; dest[0] = (fi->rowbuf[0] >> (4 * ((i + 1) % 2))) & 0x0f;
break; break;
case 24: case 24:
for (int c = 0; c < 3; c++) for (gint c = 0; c < 3; c++)
{
dest[2 - c] = fi->rowbuf[c]; dest[2 - c] = fi->rowbuf[c];
}
break; break;
} }
dest[fi->channels - 1] = 0xff; /* alpha */ dest[fi->channels - 1] = 0xff; /* alpha */
@ -1133,10 +1125,9 @@ load_rle (struct Fileinfo *fi, gsize offset)
} }
static gint static gint
load_huffman (struct Fileinfo *fi, gsize offset) load_huffman (struct Fileinfo *fi, guchar *dest)
{ {
gint xpos = 0, len, i; gint xpos = 0, len, i;
guchar *dest;
while (xpos < fi->width) while (xpos < fi->width)
{ {
@ -1158,11 +1149,8 @@ load_huffman (struct Fileinfo *fi, gsize offset)
len = huff_decode (&fi->bitbuf, &fi->buflen, fi->file, fi->black); len = huff_decode (&fi->bitbuf, &fi->buflen, fi->file, fi->black);
if (len >= 0 && len <= fi->width - xpos) if (len >= 0 && len <= fi->width - xpos)
{ {
dest = fi->dest + offset + xpos;
for (i = 0; i < len; i++, xpos++) for (i = 0; i < len; i++, xpos++)
{ *dest++ = fi->black;
dest[i] = fi->black;
}
fi->black = ! fi->black; fi->black = ! fi->black;
continue; continue;
} }