Repository navigation
Keep animated PNGs out of the iOS asset catalog - #59331
Closed
janicduplessis wants to merge 3 commits into
Closed
janicduplessis wants to merge 3 commits into
janicduplessis wants to merge 3 commits into
Conversation
actool compiles an animated PNG into a single still frame, so the CLI now copies any png asset with an acTL chunk as a loose file instead of adding it to RNAssets.xcassets. The runtime falls through to the loose-file lookup on a catalog miss and only reports an error when that fails too.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
With
RCTUseAssetCatalogon (#30129), every png/jpg/jpeg packager asset goes intoRNAssets.xcassets, andactoolkeeps only the first frame of an animated PNG. Arequire()d APNG renders as a still once the key is on, and the animated file is gone from the app, so a library that could animate it (expo-image, FastImage) has nothing to load.Bundler:
isCatalogAssetnow reports a png asset animated when any of its scales has anacTLchunk before the firstIDAT, and the asset is copied loose the way gif and webp already are. All scales go loose together, since the runtime resolves by scale-stripped name and an asset has to be entirely in the catalog or entirely out.Runtime:
RCTImageFromLocalAssetURLnow falls through to the loose-file lookup on a catalog miss, and logs the "not found in the asset catalog" error only if that fails too. A missingRNAssets.bundlecounts as a miss as well, sinceasset_catalog_compiledoes not create the bundle when no imageset is left (an app whose only png assets are animated); its error moves to the same spot. This reverses the no-fallback rule from #30129 (comment), but only on the miss branch:RCTAssetCatalogNameForURLstill returns a name for any.pngunderassets/, so without this the bundler change would turn the still frame into a blank image plus an error. A hit is still a single lookup.UIImagedoes not animate APNGs, so React Native's own<Image>still shows the first frame, as it did before the catalog existed. The change is for the file to ship intact. One consequence for expo/expo#50723: its catalog helper gates onRCTAssetCatalogNameForURLand callsRCTImageFromLocalAssetURL, so it now gets a stillUIImagefor an APNG through the fallback instead of nil.Changelog:
[IOS] [FIXED] - Keep animated PNGs out of the iOS asset catalog, where actool would flatten them to one frame
Test Plan:
RNTester has the key on and gets a 4-frame APNG as a new "Animated PNG" example next to the Animated GIF one. Release build (
xcodebuild -scheme RNTester -configuration Release, iOS 27.0 simulator):RNTester.app/assets/js/assets/animated.pngand the gif are the only loose images, every other png and jpg is inRNAssets.bundle/Assets.car(53 renditions, none namedanimated). Openingrntester://example/ImageExample/animated-pngrenders the first frame, andlog streamfor the process shows noRCTLogError, so the catalog miss fell through to the loose file.The flattening itself, for the record: compiling that APNG into a one-imageset catalog with
xcrun actoolyields a single still rendition inAssets.car(assetutil --info), while ImageIO reads 4 frames from the loose file.Unit tests cover the detector (acTL before IDAT, acTL after a 70 KB chunk, still PNG, non-PNG bytes, truncated file, missing file) and
isCatalogAsset(still png, APNG, only the @2x animated, jpg/gif never read):