UnderminersTeam / UndertaleModTool

The most complete tool for modding, decompiling and unpacking Undertale (and other GameMaker games!)
GNU General Public License v3.0
1.19k stars 233 forks source link

Rewrite texture handling #1870

Closed colinator27 closed 3 months ago

colinator27 commented 3 months ago

Description

Rewrites all of the core texture code to use a new immutable GMImage class, which can be one of four texture types: PNG, raw BGRA pixel data, QOI, or BZip2 + QOI. This class is used as a replacement to the existing byte[] containing compressed PNG data always.

The major benefit of this is that load/save times on games using non-PNG textures are now much faster (some games are at least 5 seconds faster on either end, on my machine). QOI and/or BZ2 textures are now decoded/decompressed on the fly, rather than during the (de)serialization process.

This also mostly replaces System.Drawing.Common calls with ones to ImageMagick instead. In UndertaleModLib, it's used only for PNG encoding/decoding, but I also rewrote a tiny bit of code on the UI side. This should mean the library code itself is cross-platform. Additionally, I performed some tests and found that exporting PNGs with the new UI code preserves colors with 0 alpha.

Caveats

This breaks pretty much every script that interacts with texture data, but that will be resolved in an upcoming PR.

There's also one further memory optimization that can be made with BZ2 + QOI textures, if we can decompress the first 8 bytes of the BZ2 data only. Essentially, it involves finding the size of the inner QOI data, which can be used to initialize the capacity of the buffer used to decompress the BZ2 data later (when called to do so, on the fly). The performance impact is probably not extreme, though - it would prevent a few reallocations at most. It's something maybe worth revisiting in the future.

Notes

Tested on a number of games, including ones with PNG textures, BZ2 + QOI textures, and pre/post GameMaker 2022.5. I haven't yet tested QOI-only games, but the code should theoretically work with them. Files have loaded/saved byte-for-byte, besides a bug in the FONT chunk that's fixed by the serialization cleanup PR (#1864).

I tested collision mask saving/loading, the room editor, the sprite editor, the embedded texture editor (saving/loading), and the texture page item editor (saving/loading).

On the UI front, instances of BitmapSource are cached for as long as the garbage collector doesn't get rid of them from memory, which can prevent unnecessary image decodes.

github-actions[bot] commented 3 months ago

Download the artifacts for this pull request here:

GUI:

CLI:

Miepee commented 3 months ago

CLI was able to dump all embedded textures, so i'll call this a success! Gonna be merging this now, fixing scripts is next on the table then :)