Conversation
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.
Adds
img-tools, a build-time tool that compresses an app'sbmpimage literals into one packed buffer with a keyed lookup, and the device runtime that decodes them (img.ts).This PR introduces
//% packable, a new comment attribute forbmpimage literals. It is not a pxt attribute: pxt parses it like any attribute it doesn't recognize and ignores it. It is read by ui-core's newimg-genbuild tool, which compresses every marked image into one packed buffer that the app looks up by key at runtime.//% packablemakes the image eligible for packing. The image is identified by its const name.//% packable="name"sets that name explicitly, so a library can rename the const without breaking the apps that reference it.//% whenUsed. That is what lets the compiler drop the original literal once it is packed; without it, the generator refuses to pack the image, since the pixels would ship twice.On MicroCode's 115 images, pixel data goes from 18,328 B to 9,922 B, and each image's const initializer overhead disappears with it.
Using it
The app maps its lookup keys to images in
img.keys.json, runsimg-gento generateimg.g.ts, and retrieves images by key:Setup, configuration and every diagnostic are documented in
img-tools/README.md.How it works
paddingfield, which pxt writes as 0 and never reads, carries the method:0x0000is uncompressed,0xC0nnis compressed methodnn. Method 1, nibble RLE, is the only one defined. Because uncompressed is0x0000, any ordinarybmpliteral is already a valid record.hexbuffer with a u16 offset table. Identical images share a record.bitmaps.ofCompressed(buf, offset)decodes one record, returningnullif it can't read it.ui.ImagePackdecodes on first access and caches for the lifetime of the program, with no eviction, falling back toui.MISSINGfor an unknown key or unreadable record.Generator behavior
//% packableimages across the app and its pxt dependencies, excludingtestFiles. A dependency's image is packed only if the app's key table names it. If no key table exists, one is scaffolded containing all packed image keys. A note to review it manually is written to the console output.//% whenUsed, or the const is still referenced directly. The reference scan is namespace-aware and ignores comments and string data."ui.thermometer") when two packages declare the same one; a bare name resolves to the app's own image.img.keys.jsonif none exists, listing each packable app image under its own name, and asks for a review.img-gen --checkscans the built output for packed images that also ship as separate buffers. It reports, and never fails.ui-core's own icons
23 of the 24 icons in
icons.tsare now//% packable, so apps can absorb them into their own pack. This has no effect on apps that don't run the generator.MISSINGis deliberately left unmarked, since it is the pack's fallback.Other changes
package.json: adds the./imgexport, theimg-genbin and atest:imgscript.package-lock.jsonpicks up the package's scoped name and bins.Testing
npm run test:img: 76node:testtests with no dependencies, covering the codec, scanner, key table, packer, emitter, dependency discovery, pin check, generator, bin and post-build check. One test checks that the records embedded intest.tsare still what the encoder produces, so the device tests can't drift from the tooling.runImgTestandrunImagePackTestpass on a micro:bit V2. They cover both methods, a record at a nonzero offset, rejection of unknown methods, cache identity, shared records and fallbacks.Release
The standard dependency chain bump is required: