discord / gamesdk-and-dispatch

Public issue tracker for the Discord Game SDK and Dispatch
22 stars 7 forks source link

Using the SDK to retrieve user avatar is inverted #108

Open shadowfox87 opened 3 years ago

shadowfox87 commented 3 years ago

Describe the bug There are currently two ways of retrieving the discord user avatar - the discord api or the sdk. Using the api works: https://discord.com/developers/docs/resources/user

Using the sdk will lead to an inverted avatar (upside down) and also the avatar becomes brighter. https://discord.com/developers/docs/game-sdk/images

This is because some of the bytes were inverted. We inverted the bytes to make it right-side up but the brightness of the avatar could not be fixed. I'm sure that this is an easy fix.

The reason we use the sdk instead of the api is because for Unity games, it has better performance.

Expected behavior The avatar retrieved from the sdk should not be inverted and should not be brighter.

Screenshots Original: image

SDK: image

Implementation specifics

sylveon commented 3 years ago

The following code gives me the right image:

imageManager.Fetch(Discord.ImageHandle.User(userId, 128), (result, handle) =>
{
    var data = imageManager.GetData(handle);

    // Discord returns BGRA but Bitmap expects RGBA
    for (int i = 0; i < data.Length; i += 4)
    {
        var r = data[i + 2];
        var b = data[i];

        data[i] = r;
        data[i + 2] = b;
    }

    var pinnedArray = GCHandle.Alloc(data, GCHandleType.Pinned);
    try
    {
        using (var bmp = new Bitmap(128, 128, 128 * 4, PixelFormat.Format32bppArgb, pinnedArray.AddrOfPinnedObject()))
        {
            bmp.Save("test.bmp", ImageFormat.Bmp);
        }
    }
    finally
    {
        pinnedArray.Free();
    }
});

and the GetTexture method (for Unity) is a very bogus implementation:

public Texture2D GetTexture(ImageHandle handle)
{
    var dimensions = GetDimensions(handle);
    var texture = new Texture2D((int)dimensions.Width, (int)dimensions.Height, TextureFormat.RGBA32, false, true);
    texture.LoadRawTextureData(GetData(handle));
    texture.Apply();
    return texture;
}

For the reversed image, it seems that Unity uses a negative stride, resulting in it being interpreted as bottom-up (from a quick skimming of the docs, it seems Unity does that everywhere) when the bitmap is top-down (positive stride).

As for the coloring issue, I suspect that it's a similar issue than the one I worked around with my for loop here - could you give that a try?

shadowfox87 commented 3 years ago

Hi!

We gave your code a try. The RGBA32 still gives a brighter image. We already fixed the inversion on the positive stride, but the brightness is still wrong. It seems your code converts it to bmp which is probably why you see correct colors but Unity accepts rgb32 I think.

PixelNinja132 commented 3 years ago

Hi!

We gave your code a try. The RGBA32 still gives a brighter image. We already fixed the inversion on the positive stride, but the brightness is still wrong. It seems your code converts it to bmp which is probably why you see correct colors but Unity accepts rgb32 I think.

Could you not just use the URL to get it, then use the user Id and avatar hash?

shadowfox87 commented 3 years ago

Url directly to the avatar? Yes you can do that, but the point is that we are using SDK so it's actually better to use the SDK since it will be less request and less expensive.

PixelNinja132 commented 3 years ago

I don't have unity, but can you get someone on another system to repro?