From 1095e353594ff0e5a5099955acadb37c6db5506d Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Thu, 11 Jul 2024 04:42:46 +0200 Subject: [PATCH] stb_image: support horizontally flipped TGA images The TGA format is a bottom-left format by default: the first byte of the first column is expected to be displayed at the bottom-left of the screen, this behavior is inherited from devices painting the screen from the bottom left to the top right. The TGA format provides two bits in the image descriptor byte to paint the data from other sides. The 4th bit tells the device to paint the screen from right-to left and the 5th bit tells the device to paint the screen from top to bottom. So basically: - 00: from bottom-left to top-right - 01: from top-left to bottom-right - 10: from bottom-right to top-left - 11: from top-right to bottom-left Previously stb_image only read the 5th bit and then only supported the loading of vertically flipped images, stb_image was ignoring the 4th bit coding the horizontal flip. Now both flipping directions are supported for both raw and RLE storage. --- stb_image.h | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/stb_image.h b/stb_image.h index 9eedabedc..884a29ca0 100644 --- a/stb_image.h +++ b/stb_image.h @@ -5884,8 +5884,8 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req int tga_height = stbi__get16le(s); int tga_bits_per_pixel = stbi__get8(s); int tga_comp, tga_rgb16=0; - int tga_inverted = stbi__get8(s); - // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + int tga_descriptor = stbi__get8(s); + // int tga_alpha_bits = tga_descriptor & 15; // the 4 lowest bits - unused (useless?) // image data unsigned char *tga_data; unsigned char *tga_palette = NULL; @@ -5907,7 +5907,8 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req tga_image_type -= 8; tga_is_RLE = 1; } - tga_inverted = 1 - ((tga_inverted >> 5) & 1); + int tga_x_inverted = ((tga_descriptor >> 4) & 1); + int tga_y_inverted = 1 - ((tga_descriptor >> 5) & 1); // If I'm paletted, then I'll use the number of bits from the palette if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); @@ -5932,9 +5933,16 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { for (i=0; i < tga_height; ++i) { - int row = tga_inverted ? tga_height -i - 1 : i; + int row = tga_y_inverted ? tga_height - i - 1 : i; stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; - stbi__getn(s, tga_row, tga_width * tga_comp); + if (tga_x_inverted) { + for (j = 0; j < tga_width; j++) { + int index = (tga_width - j - 1) * tga_comp; + stbi__getn(s, tga_row + index, tga_comp); + } + } else { + stbi__getn(s, tga_row, tga_width * tga_comp); + } } } else { // do I need to load a palette? @@ -6024,7 +6032,22 @@ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req --RLE_count; } // do I need to invert the image? - if ( tga_inverted ) + if (tga_x_inverted) + { + for (j = 0; j < tga_height; j++) { + stbi_uc *row = tga_data + (j * tga_width * tga_comp); + for (int s = 0, d = tga_width - 1; s * 2 < tga_width; s++, d--) { + stbi_uc *src = row + (s * tga_comp); + stbi_uc *dest = row + (d * tga_comp); + for (i = 0; i < tga_comp; i++) { + stbi_uc temp = src[i]; + src[i] = dest[i]; + dest[i] = temp; + } + } + } + } + if (tga_y_inverted) { for (j = 0; j*2 < tga_height; ++j) {