feat: add little-endian pack functions to string.pack module#34
Merged
Tsukina-7mochi merged 1 commit intodevelopfrom Nov 14, 2025
Merged
Conversation
Add u32LE, i32LE, and u16LE functions for little-endian binary encoding. These functions complement the existing big-endian functions and are needed for bitmap file format support. - Add u32LE: 32-bit unsigned integer, little-endian - Add i32LE: 32-bit signed integer, little-endian - Add u16LE: 16-bit unsigned integer, little-endian - Add comprehensive tests for all three functions
Tsukina-7mochi
pushed a commit
that referenced
this pull request
Nov 14, 2025
Add a library to export Aseprite RGB images as 24-bit BMP files. This enables exporting images in the widely-supported bitmap format. Features: - Encodes Aseprite Image objects to BMP binary string - Supports 24-bit RGB color mode only - Proper BGR byte order conversion - Bottom-to-top row ordering per BMP specification - Automatic row padding to 4-byte boundaries - Standard BMP file and info headers (14 + 40 bytes) Implementation: - src/pkg/bitmap/init.lua: Main BMP encoder with create() API - src/pkg/bitmap/bitmap_test.lua: Comprehensive test suite - src/pkg/asepriteUtil/mock.lua: Reusable Aseprite API mocks for testing The bitmap encoder uses the little-endian pack functions added in PR #34 to generate proper BMP file structures.
Tsukina-7mochi
added a commit
that referenced
this pull request
Nov 14, 2025
* feat: add bitmap (BMP) encoder for 24-bit RGB images Add a library to export Aseprite RGB images as 24-bit BMP files. This enables exporting images in the widely-supported bitmap format. Features: - Encodes Aseprite Image objects to BMP binary string - Supports 24-bit RGB color mode only - Proper BGR byte order conversion - Bottom-to-top row ordering per BMP specification - Automatic row padding to 4-byte boundaries - Standard BMP file and info headers (14 + 40 bytes) Implementation: - src/pkg/bitmap/init.lua: Main BMP encoder with create() API - src/pkg/bitmap/bitmap_test.lua: Comprehensive test suite - src/pkg/asepriteUtil/mock.lua: Reusable Aseprite API mocks for testing The bitmap encoder uses the little-endian pack functions added in PR #34 to generate proper BMP file structures. * refactor: use metatable pattern for bitmap objects Change bitmap.create() to return a table with metatable instead of a plain string. This allows the bitmap object to be converted to a string via tostring() or the __tostring metamethod. Changes: - Replace create() function with bitmap class using metatable - Add tostring() method that generates BMP binary data - Set __tostring metamethod for implicit string conversion - Update all tests to use new API: bitmap(image) - Add test for both explicit and implicit tostring conversion Usage: ```lua local bitmap = require("pkg.bitmap").bitmap local bmp = bitmap(image) -- Explicit conversion local data = bmp:tostring() -- Implicit conversion local data = tostring(bmp) -- Or use in string concatenation local data = "" .. bmp ``` This pattern matches the RIFF chunk implementation and provides more flexibility for future extensions. * refactor: separate bitmap class into dedicated file Move bitmap class definition from init.lua to bitmap.lua for better code organization and separation of concerns. Changes: - Create src/pkg/bitmap/bitmap.lua with bitmap class and helper functions - Update init.lua to just require and export the bitmap class - No API changes - tests continue to work without modification This makes the codebase more modular and easier to maintain. * chore: remove unnecessary @module annotations * chore: remove @module annotation from mock.lua * refactor: use string.pack in mock pixelColor.rgba * chore: set pixels per meter to 0 in BMP header * refactor: restructure bitmap implementation Major refactoring of bitmap module for cleaner architecture: - mock.lua: Use bit operations instead of string.pack for rgba - bitmap.lua: Use table.concat instead of string concatenation - bitmap.lua: Rename class to BitmapFile and store components separately - fileHeader: BMP file header (14 bytes) - bitmapInfoHeader: Bitmap info header (40 bytes) - pixelData: Binary pixel data - bitmap.lua: Export create function instead of __call metamethod - init.lua: Simplify to directly return bitmap module - bitmap_test.lua: Use hard-coded binary string literals instead of helpers - bitmap_test.lua: Add test for BitmapFile structure API change: bitmap(image) -> bitmap.create(image) * refactor: remove empty init.lua * refactor: change expression --------- Co-authored-by: Claude <noreply@anthropic.com>
Tsukina-7mochi
added a commit
that referenced
this pull request
Feb 19, 2026
* chore: add style * style: apply stylua * chore: add lib to styluaignore * feat: update type definition * feat: add pre-init and post-run code to cleanup modules * chore: update api definition * chore: add claude configuration * feat: add little-endian pack functions to string.pack module Add u32LE, i32LE, and u16LE functions for little-endian binary encoding. These functions complement the existing big-endian functions and are needed for bitmap file format support. - Add u32LE: 32-bit unsigned integer, little-endian - Add i32LE: 32-bit signed integer, little-endian - Add u16LE: 16-bit unsigned integer, little-endian - Add comprehensive tests for all three functions * chore: update submomule origin to HTTP * feat: add bitmap (BMP) encoder for 24-bit RGB images (#35) * feat: add bitmap (BMP) encoder for 24-bit RGB images Add a library to export Aseprite RGB images as 24-bit BMP files. This enables exporting images in the widely-supported bitmap format. Features: - Encodes Aseprite Image objects to BMP binary string - Supports 24-bit RGB color mode only - Proper BGR byte order conversion - Bottom-to-top row ordering per BMP specification - Automatic row padding to 4-byte boundaries - Standard BMP file and info headers (14 + 40 bytes) Implementation: - src/pkg/bitmap/init.lua: Main BMP encoder with create() API - src/pkg/bitmap/bitmap_test.lua: Comprehensive test suite - src/pkg/asepriteUtil/mock.lua: Reusable Aseprite API mocks for testing The bitmap encoder uses the little-endian pack functions added in PR #34 to generate proper BMP file structures. * refactor: use metatable pattern for bitmap objects Change bitmap.create() to return a table with metatable instead of a plain string. This allows the bitmap object to be converted to a string via tostring() or the __tostring metamethod. Changes: - Replace create() function with bitmap class using metatable - Add tostring() method that generates BMP binary data - Set __tostring metamethod for implicit string conversion - Update all tests to use new API: bitmap(image) - Add test for both explicit and implicit tostring conversion Usage: ```lua local bitmap = require("pkg.bitmap").bitmap local bmp = bitmap(image) -- Explicit conversion local data = bmp:tostring() -- Implicit conversion local data = tostring(bmp) -- Or use in string concatenation local data = "" .. bmp ``` This pattern matches the RIFF chunk implementation and provides more flexibility for future extensions. * refactor: separate bitmap class into dedicated file Move bitmap class definition from init.lua to bitmap.lua for better code organization and separation of concerns. Changes: - Create src/pkg/bitmap/bitmap.lua with bitmap class and helper functions - Update init.lua to just require and export the bitmap class - No API changes - tests continue to work without modification This makes the codebase more modular and easier to maintain. * chore: remove unnecessary @module annotations * chore: remove @module annotation from mock.lua * refactor: use string.pack in mock pixelColor.rgba * chore: set pixels per meter to 0 in BMP header * refactor: restructure bitmap implementation Major refactoring of bitmap module for cleaner architecture: - mock.lua: Use bit operations instead of string.pack for rgba - bitmap.lua: Use table.concat instead of string concatenation - bitmap.lua: Rename class to BitmapFile and store components separately - fileHeader: BMP file header (14 bytes) - bitmapInfoHeader: Bitmap info header (40 bytes) - pixelData: Binary pixel data - bitmap.lua: Export create function instead of __call metamethod - init.lua: Simplify to directly return bitmap module - bitmap_test.lua: Use hard-coded binary string literals instead of helpers - bitmap_test.lua: Add test for BitmapFile structure API change: bitmap(image) -> bitmap.create(image) * refactor: remove empty init.lua * refactor: change expression --------- Co-authored-by: Claude <noreply@anthropic.com> * build: refactor bootstrap code * refactor: refactor bitmap pkg * feat(bitmap-pkg): add factory to create image with alpha mask * feat: add pre-init and post-run code to cleanup modules * feat(icon-and-cursor): add parameter definition * feat(icon-and-cursor): implement dialog * feat: implement layer&frame extraction * feat(icon-cursor): implement ico/cur export * feat: update RIFF library * feat: reimplement icon-cursor script * feat(icon-cursor): implement cli * feat(icon-cursor): persist dialog state and improve UX Refactor export dialog to save/restore user settings via sprite properties, allowing preferences to persist between exports. Replace hardcoded option strings with structured option tables using optionLabels/getOptionValue helpers. Wrap dialog in a validation loop so users can fix errors without re-entering all fields. * fix(icon-cursor): use descriptive labels for filetype dropdown options Replace abbreviation-style labels (ICO, CUR, ANI) with human-readable names (Icon, Cursor, Animated Cursor) in the export dialog filetype selector for better clarity. * fix(icon-cursor): refactor option lookup to return full entry and fix UI updates Replace getOptionValue with getOptionEntry to return the full option object instead of just the value string. Add isCursor and isAnimated flags to FILETYPE_OPTIONS to derive visibility state from data rather than hardcoded string comparisons. Fix filename update to properly modify the dialog widget via dialog:modify. Add default values for hotspot and framerate params. * fix(asepriteUtil): access frameNumber property from tag frame objects The tag.fromFrame and tag.toFrame properties return Frame objects, not numeric indices. Use .frameNumber to get the integer value needed for iteration and array indexing. * feat(icon-cursor): support single frame selection in export dialog Add ability to select individual frames (not just tags) for export. The tag parameter now accepts a frame number (integer) in addition to a tag name (string) or nil (all frames). Frame options are listed in the dialog alongside tag options. Also removes leftover debug print statements and replaces util.alert with error() for consistency. * fix(icon-cursor): zero out hotspot fields for ICO format ICO files should always have hotSpotX and hotSpotY set to zero, as hotspot coordinates are only meaningful for CUR (cursor) files. Previously, user-specified hotspot values were written regardless of file type. * fix(bitmap): fix bitmap info header image size calculation Replace manual row-size calculations with sizes derived from the actual encoded byte strings. Parameterize createInfoHeader to accept bitsPerPixel and imageSize, removing hardcoded values. This eliminates redundant size arithmetic and ensures headers always match the real payload, making the module easier to extend for other bit depths. * feat(icon-cursor): add CLI argument parsing with proper type coercion for non-UI mode Extract getParamsFromArgs to properly map CLI arguments (app.params) to internal parameter format, applying type coercion for numeric fields (hot-spot-x, hot-spot-y, framerate, tag) and initializing from sprite defaults before overriding with provided arguments. This replaces the previous approach of passing raw app.params directly, which skipped default initialization and lacked type safety. * feat(icon-cursor): bump version to v0.2.0 * chore: build * feat(icon-cursor): add configurable completion dialog with showCompleted parameter Add a "Show completion dialog" checkbox to the export dialog, allowing users to suppress the post-export confirmation. Include field documentation, default value, and validation for the new boolean parameter. * fix(icon-cursor): fix operator precedence in dialog default value fallbacks `tostring()` was being called before the `or` fallback, causing `or` to never trigger since `tostring()` always returns a non-nil string. Move the `or` inside `tostring()` so the fallback applies to the raw value before conversion. * chore: build * docs(icon-cursor): update readme Document new version highlights including dialog validator fix, reduced icon file size, and CLI support. Move license notice out of readme. --------- Co-authored-by: Claude <noreply@anthropic.com>
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
u32LE: 32-bit unsigned integer, little-endiani32LE: 32-bit signed integer, little-endianu16LE: 16-bit unsigned integer, little-endianPurpose
These functions complement the existing big-endian functions and are needed for bitmap file format support (BMP files use little-endian byte order).
Changes
src/pkg/string/pack.lua: Added three new little-endian pack functions with proper type annotationssrc/pkg/string/pack_test.lua: Added test cases for all three new functionsTest Plan
make testto verify all tests pass