We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2840 - Wrong colors in TGA files from GTA2
Summary: Wrong colors in TGA files from GTA2
Status: RESOLVED FIXED
Alias: None
Product: SDL_image
Classification: Unclassified
Component: misc (show other bugs)
Version: 2.0.0
Hardware: x86_64 All
: P2 normal
Assignee: Sam Lantinga
QA Contact: Sam Lantinga
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-01-10 00:11 UTC by robotanarchy
Modified: 2017-09-12 06:42 UTC (History)
3 users (show)

See Also:


Attachments
source code to reproduce this, with an example tga file and screenshots (1.11 MB, application/zip)
2015-01-10 00:11 UTC, robotanarchy
Details
Swapping of bits happened for SDL_LIL_ENDIAN system which is wrong. It should be for SDL_BIG_ENDIAN system. (457 bytes, patch)
2015-08-21 09:33 UTC, Amit Jain
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description robotanarchy 2015-01-10 00:11:11 UTC
Created attachment 1987 [details]
source code to reproduce this, with an example tga file and screenshots

When trying to load a TGA file from GTA2, the colors are all wrong (not inverted, it looks like a completely wrong color palette).

Versions:
- SDL2: 2.0.3
- SDL2_image: 2.0.0

Tested on:
- Windows 7 (MinGW i686 Toolchain)
- Arch Linux x86_64

GTA2 can be downloaded legally from:
- http://www.rockstargames.com/classics/
- http://www.chip.de/downloads/Grand-Theft-Auto-GTA-2_13015291.html


I've attached a complete example that reproduces this bug (source code and a sample GTA2 TGA file), and a screenshot of how it looks in SDL_Image and how it should look like (libreoffice draw opened it correctly).

Here is the main.c (as in the zip file):


#include <stdio.h>
#include <stdlib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

int main(int argc, char* argv[])
{
    SDL_Window* win;
    SDL_Renderer* renderer;
    SDL_Surface* img_surface;
    SDL_Texture* img_texture;
    SDL_Rect dest_rect = { 0, 0, 320, 480 };

    if(SDL_Init(SDL_INIT_VIDEO)<0)
        exit(printf("SDL_ERROR: %s\n",SDL_GetError()));

    win = SDL_CreateWindow("SDL_Image TGA Display",
        SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
        640, 480, SDL_WINDOW_SHOWN);
    if(!win) exit(printf("SDL_ERROR: %s\n", SDL_GetError()));


    // Load the image into a texture
    renderer = SDL_CreateRenderer(win,-1,0);
    img_surface = IMG_Load("1_Play.tga");
    img_texture = SDL_CreateTextureFromSurface(renderer,
        img_surface);


    // Show it until the window gets closed
    while(1)
    {
        SDL_Event event;

        SDL_RenderClear(renderer);
        SDL_RenderCopy(renderer, img_texture, NULL, &dest_rect);
        SDL_RenderPresent(renderer);


        SDL_WaitEvent(&event);
        if(event.type == SDL_QUIT) break;
    }


    // Clean up
    SDL_DestroyTexture(img_texture);
    SDL_FreeSurface(img_surface);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return 0;
}
Comment 1 Philipp Wiesemann 2015-01-13 20:13:19 UTC
Thank you for reporting this problem and providing an example.

It seems that the colors for this image are wrong because the bytes in img_surface->pixels are in the wrong order. There are two bytes for every pixel and if they are swapped it looks correct.

A similar problem was fixed in bug 1886. The changeset which introduced this bug [1] also changed the swapping for little endian platforms. It could be the cause.

[1] https://hg.libsdl.org/SDL_image/rev/5bf0f0d6a74e
Comment 2 robotanarchy 2015-01-19 21:26:13 UTC
Thanks for finding out the exact issue! Do you have any idea when this will be fixed?
Comment 3 robotanarchy 2015-02-03 19:57:05 UTC
I can confirm that Philipp Wisemann's theory is right: When I switch the bytes with the following code, the images are displayed correctly.


char* pixels = surface->pixels;
for(int y=0;y < surface->h;y++)
	for(int x=0;x < surface->w;x++)
{
	int  left_byte_addr = y*surface->w*2 + x*2;
	char left_old = pixels[ left_byte_addr ];
	
	pixels[left_byte_addr +0] = pixels[left_byte_addr +1];
	pixels[left_byte_addr +1] = left_old;
}

I've added this workaround code to my project, because the target platforms are x86 and x86_64 only, but it would still be best if this was fixed upstream. Thanks!
Comment 4 Amit Jain 2015-08-21 09:33:37 UTC
Created attachment 2248 [details]
Swapping of bits happened for SDL_LIL_ENDIAN system which is wrong. It should be for SDL_BIG_ENDIAN system.

Hi Robotanarchy
Proper solution patch has been attached.

Hi Philipp Wiesemann
That fix given for  bug 1886 is not exactly same as this bug. This issue was not fixed with that solution.
That bug was coming for selection of incorrect masking color for 24 bits per pixel image format. But here in this case, it is being selected correctly. But it was swapping for little endian system, that should be big endian instead.
Comment 5 Pankaj 2017-09-11 07:17:39 UTC
Hi Sam,

Any update on this ?
Comment 6 Sam Lantinga 2017-09-12 06:42:28 UTC
Fixed, thanks!
https://hg.libsdl.org/SDL_image/rev/64a10bd1598c