Skip to content

Commit

Permalink
stb_image: support horizontally flipped TGA images
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
illwieckz committed Jul 11, 2024
1 parent cf279c6 commit a276c16
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions crnlib/stb_image.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 3 lowest bits - unused (useless?)
// image data
unsigned char *tga_data;
unsigned char *tga_palette = NULL;
Expand All @@ -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);
Expand All @@ -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?
Expand Down Expand Up @@ -6024,19 +6032,27 @@ 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 || tga_y_inverted )
{
for (j = 0; j*2 < tga_height; ++j)
{
int index1 = j * tga_width * tga_comp;
int index2 = (tga_height - 1 - j) * tga_width * tga_comp;
for (i = tga_width * tga_comp; i > 0; --i)
{
unsigned char temp = tga_data[index1];
tga_data[index1] = tga_data[index2];
tga_data[index2] = temp;
++index1;
++index2;
int col_start = tga_x_inverted ? tga_width - 1 : 0;
int col_iter = tga_x_inverted ? -1 : 1;
int row_start = tga_y_inverted ? tga_height - 1 : 0;
int row_iter = tga_y_inverted ? -1 : 1;
int row = row_start;
for (i = 0; i * 2 < tga_height; i++, row += row_iter) {
int src_row_index = i * tga_width * tga_comp;
int dest_row_index = row * tga_width * tga_comp;
int col = col_start;
for (j = 0; j * 2 < tga_width; j++, col += col_iter) {
int src_col_index = j * tga_comp;
int dest_col_index = col * tga_comp;
for (int k = 0; k < tga_comp; k++) {
stbi_uc *src = tga_data + src_row_index + src_col_index + k;
stbi_uc *dest = tga_data + dest_row_index + dest_col_index + k;
stbi_uc temp = *src;
*src = *dest;
*dest = temp;
}
}
}
}
Expand Down

0 comments on commit a276c16

Please sign in to comment.