Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't premultiply cached/vanilla images #37

Open
Dregu opened this issue Oct 23, 2022 · 0 comments
Open

Don't premultiply cached/vanilla images #37

Dregu opened this issue Oct 23, 2022 · 0 comments

Comments

@Dregu
Copy link
Contributor

Dregu commented Oct 23, 2022

Thoughts from Discord:

  1. DDS files in the game are premultiplied alpha, but extraction does not un-premultiply when making PNGs (premultiplied PNG is not even a thing but whatever)
  2. Multiplying/Dividing the alpha is lossy and we can't really get an original PNG back that could be both loaded in PL and look right in an editor
  3. Playlunky is premultiplying all images from mods, cause they are likely PNG and not premultiplied
  4. Playlunky is also premultiplying the cached vanilla files it extracted when stitching entity sheets or sprite maps, which is bad and any unmodified parts get premultiplied twice in the end
  5. Using any mods that custom sprite map to items.png will break all the other items because of 4
  6. There might even be a feedback loop so files in the cache get premultiplied again and again

Solutions:

  • Modlunky could predivide alphas when extracting, but it's not going to look the same when premultiplying again
    • We could just say the extracted PNG files are premultiplied and anyone who uses very transparent parts as base for their mods is stupid
  • Playlunky definitely shouldn't divide or premultiply cached (vanilla) files ever, only premultiply user-provided files once before caching or stitching
    • Disabling premultiplication in PL will load extracted vanilla PNG files correctly, but this is obviously a useless feature

I tried to undo the premultiplication and then load the textures again in PL https://imgur.com/a/Z4ToeAS
I extracted the divided textures with this modification but nothing looks quite right either way...

def dds_to_png(data):
    """Takes a .DDS `Image` and returns .png data."""
    img = Image.open(io.BytesIO(data))
    px = img.load()
    width, height = img.size
    for i in range(width):
        for j in range(height):
            if px[i, j][3] != 0:
                R = int(255.0 * px[i, j][0] / px[i, j][3] + 0.5)
                G = int(255.0 * px[i, j][1] / px[i, j][3] + 0.5)
                B = int(255.0 * px[i, j][2] / px[i, j][3] + 0.5)
                a = px[i, j][3]
                px[i, j] = (R, G, B, a)
    new_data = io.BytesIO()
    img.save(new_data, format="PNG")
    return new_data.getvalue()

Originally posted by @Dregu in spelunky-fyi/modlunky2#304 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant