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 4798

Summary: PNG w/transparency breaks in SDL 2.0.10 but works in SDL 2.0.9
Product: SDL Reporter: Hugo Hromic <hhromic>
Component: videoAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: major    
Priority: P2 CC: sylvain.becker
Version: 2.0.10Keywords: target-2.0.12
Hardware: x86_64   
OS: Windows 7   
Attachments: First Sample: Mr Grump test image
Second Sample: Dialog box test image
Screenshot of wrong output of first image in SDL 2.0.10

Description Hugo Hromic 2019-09-09 21:33:03 UTC
Created attachment 3960 [details]
First Sample: Mr Grump test image

Hello,

I recently discovered a problem with SDL 2.0.10 that does not occur with SDL 2.0.9 regarding displaying PNG images with latest SDL_image 2.0.5. Some PNG images with transparency look incorrect in 2.0.10 while they used to work in 2.0.9.

I prepared the following very simple test C program for MSYS2 MinGW (Windows but confirmed it also happens in Linux) to showcase the problem with a sample PNG file attached to this issue:

---8<---8<---8<---8<---8<---8<---8<---8<---

// Build: x86_64-w64-mingw32-gcc sdl-show.c -o sdl-show -lmingw32 -lSDL2main -lSDL2 -lSDL2_image
//   Run: ./sdl-show.exe <IMAGE_FILE>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <stdio.h>

#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 240

int main(int argc, char* args[]) {
  SDL_Init(SDL_INIT_VIDEO);
  SDL_Window *window     = SDL_CreateWindow("SDL Image Test",
    SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
    SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
  SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
  SDL_Surface *image     = IMG_Load(args[1]);
  SDL_Texture *texture   = SDL_CreateTextureFromSurface(renderer, image);
  SDL_FreeSurface(image);

  SDL_Rect pos = {
    .x=(SCREEN_WIDTH - image->w) / 2,
    .y=(SCREEN_HEIGHT - image->h) / 2,
    .w=image->w, .h=image->h
  };

  SDL_SetRenderDrawColor(renderer, 0x40, 0x40, 0x40, SDL_ALPHA_OPAQUE);
  SDL_RenderClear(renderer);
  SDL_RenderCopy(renderer, texture, NULL, &pos);
  SDL_RenderPresent(renderer);

  SDL_Delay(5000);
  SDL_DestroyTexture(texture);
  SDL_DestroyRenderer(renderer);
  SDL_DestroyWindow(window);
  SDL_Quit();
  return 0;
}

---8<---8<---8<---8<---8<---8<---8<---8<---

For the text below, see this Imgur album: https://imgur.com/a/Jg2EXc0

When you run this sample program with the first attached PNG file using SDL 2.0.9 or below and SDL_image 2.0.5 you get the expected output (image 1 in album)

However when the same program is run with the same image under SDL 2.0.10 with the same SDL_image 2.0.5, you get an incorrect output (image 2 in album)

As you can observe, the transparency data of the PNG file gets messed up. This only started to happen since I upgraded to SDL 2.0.10 on my machine.

If you process the affected PNG files with pngcrush [1] using the following command then they display correctly in SDL 2.0.10:

$ pngcrush.exe -c 6 title_grump.png title_grump_fix.png
$ pngcrush.exe -c 6 dialog_box.png dialog_box_fix.png

The "-c 6" option changes the PNG color-type to 6 (each pixel is an R,G,B triple, followed by an alpha sample).


More information and another sample image affected can be found in the SDL forum: https://discourse.libsdl.org/t/png-w-transparency-breaks-in-sdl-2-0-10-but-works-in-sdl-2-0-9/
Comment 1 Hugo Hromic 2019-09-09 23:27:15 UTC
Created attachment 3961 [details]
Second Sample: Dialog box test image

I attached now a second example image that is also affected.

The black area is supposed to be opaque and displays correctly in SDL 2.0.9 (or below), however when you display it using SDL 2.0.10 the black area becomes transparent because the black color is treated as a transparent color.
Comment 2 Sylvain 2019-09-10 09:34:26 UTC
You image has a palette (index8 pixel format), and a colorkey (40).
So your image has some transparent zone (where color is 40) and you see the background color.
This seems expected to me.


Log: format=SDL_PIXELFORMAT_INDEX8 key=40 ret=0

int key = 0;
int ret = SDL_GetColorKey(image, &key);
SDL_Log("format=%s key=%d ret=%d", SDL_GetPixelFormatName(image->format->format), key, ret);
    


if  you want to remove the colorkey, you can add: SDL_SetColorKey(image, SDL_FALSE, 0);
Comment 3 Hugo Hromic 2019-09-10 10:11:04 UTC
Created attachment 3963 [details]
Screenshot of wrong output of first image in SDL 2.0.10
Comment 4 Hugo Hromic 2019-09-10 10:14:08 UTC
Hello Sylvain,

Thanks for your reply. Indeed the sample images have indexed palette and have color keys because they are supposed to have transparency pixels. However, pixels inside the character in the image are not supposed to be transparent, only the background around the character.

I now attached a screenshot where you can see how it looks in SDL 2.0.10. If you compare that to how it looks for example in your browser or in SDL < 2.0.10 you will see that the character doesn't have any transparent pixels inside, for example in his shirt.

Therefore we don't want to remove the color key information, which is necessary to render the transparent background around the character. It feels like a rendering bug to me, specially because it doesn't occur in SDL < 2.0.10 nor other software that displays the same image.

I'm not certain is this is an SDL rendering issue or maybe SDL_image is not reading the image correctly and it was "obscured" in previous versions of SDL.
Comment 5 Sylvain 2019-09-10 11:37:56 UTC
I don't think this is a sdl_image (I have tried to various combination of libs).

In fact: 
- palette color 40 is r=255 g=255 b=255 a=255 (the surrounding)
- palette color 1 is also r=255 g=255 b=255 a=255 (the inside, the shirt)
- colorkey is 40.

In the end both regions, with 40 and 1, ends up being transparent.

because there is an intermediate conversion to argb, also for the colorkey. First the image is resolved, then the resolved colour key is transformed to transparency.

Indeed, it's an issue ...
Comment 6 Sylvain 2019-09-10 12:18:22 UTC
I think this is introduced in https://hg.libsdl.org/SDL/rev/884f99b039f0 (bug 3827)

because, with previous version palette color 40 was reported as r=255 g=255 b=255 a=0.
Comment 7 Hugo Hromic 2019-09-10 13:06:36 UTC
Thanks for looking into this so promptly. Appreciated.
Let me know of any action needed from my side to help resolving this issue.
Comment 8 Sylvain 2019-09-10 15:13:20 UTC
I think this is fixed now in: https://hg.libsdl.org/SDL/rev/0c66be754e29
Comment 9 Hugo Hromic 2019-09-10 19:50:27 UTC
I just compiled a test SDL library with your change and I'm happy to confirm it fully solves the reported issue. Many thanks!

I will patiently wait for SDL 2.0.11 to migrate from SDL 2.0.9.

This bug can be closed as resolved. Thanks again.
Comment 10 Sylvain 2019-09-10 19:51:15 UTC
Great, marked as resolved!
Comment 11 Ryan C. Gordon 2019-09-20 20:47:39 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.
Comment 12 Ryan C. Gordon 2019-09-20 20:48:44 UTC
We're changing how we do SDL release versions; now releases will be even numbers (2.0.10, 2.0.12, etc), and as soon as we tag a release, we'll move the internal version number to an odd number (2.0.12 ships, we tag the latest in revision control as 2.0.13 immediately, which will become 2.0.14 on release, etc).

As such, I'm moving the bugs tagged with target-2.0.11 to target 2.0.12. Sorry if you get a lot of email from this change!

Thanks,
--ryan.