image

    Pure MoonBit image codecs and icon container encoders.

    image
    png
    icon
    ico
    icns
    Download zip
    Version
    0.1.2
    License
    Apache-2.0
    Last updated
    11 hours ago
    Downloads
    332

    Dependencies

    #image

    Nanaloveyuki/image is Orbit's lightweight pure MoonBit image companion. It decodes PNG into RGBA8, resizes in premultiplied-alpha space, deterministically encodes PNG, and assembles ICO and ICNS containers. All APIs accept and return Bytes; the library has no filesystem or CLI surface and links no native image library. New capabilities are added only for a concrete Orbit requirement.

    #Install

    After the package is published to MoonCake, add it to a MoonBit module:

    moon add Nanaloveyuki/image

    Import the root package from the consuming package's moon.pkg:

    import { "Nanaloveyuki/image", }

    #Decode and Encode PNG

    decode_png verifies every PNG chunk CRC and the zlib checksum before returning an Image. It applies limits before allocation and streams decompression into a bounded output buffer.

    fn normalize_icon(source : Bytes) -> Bytes raise @image.ImageError {
    let image = @image.decode_png(source)
    let square = @image.square_image(image)
    let resized = @image.resize_lanczos3(square, 256, 256)
    @image.encode_png(resized, compression_level=6)
    }

    The decoder accepts non-interlaced 8-bit grayscale, palette, RGB, grayscale-alpha, and RGBA PNGs. Unsupported PNG layouts return ImageError; they are never partially decoded. Use default_decode_limits() as the baseline or pass a narrower DecodeLimits value to decode_png.

    encode_png emits exactly IHDR, IDAT, and IEND, so output is stable for a fixed library version, source image, and compression level.

    #Generate Icons

    Icon encoders require a square source image by default. This makes source image requirements explicit; square_image(image, policy=CenterCrop) is available when the caller deliberately wants center cropping.

    fn icon_artifacts(source : Bytes) -> (Bytes, Bytes, Array[@image.PngVariant]) raise @image.ImageError {
    let image = @image.square_image(@image.decode_png(source))
    let pngs = @image.encode_png_sizes(image, [16, 32, 64, 128, 256])
    let ico = @image.encode_ico(image)
    let icns = @image.encode_icns(image)
    (ico, icns, pngs)
    }

    encode_ico defaults to 16/24/32/48/64/128/256 PNG entries. encode_icns defaults to 16 through 1024 and emits the matching Retina ICNS PNG chunk types. Writing returned bytes to project-specific paths is the caller's responsibility.

    #SVG Wrapper

    png_data_uri_svg(png, width, height) wraps an existing PNG as a base64 data URI inside SVG. It does not vectorize pixels and is not used by the icon encoders.

    #Development

    See docs/development.md for local validation, API-change requirements, and contribution review rules.

    ImageError

    pub suberror ImageError {
    ImageError(ImageErrorKind, String)
    }

    DecodeLimits

    pub(all) struct DecodeLimits {
    max_input_bytes : Int
    max_dimension : Int
    max_pixels : Int
    }

    Limits applied before allocating decoded image buffers.

    Image

    pub(all) struct Image {
    width : Int
    height : Int
    pixels : Bytes
    } derive(Eq)

    RGBA8 image data in row-major order.

    Image::equal

    fn Image::equal(Image, Image) -> Bool

    Image::is_square

    fn Image::is_square(self : Image) -> Bool

    Image::new

    fn Image::new(width : Int, height : Int, pixels : Bytes) -> Image raise ImageError

    Construct a checked RGBA8 image.

    Image::not_equal

    fn Image::not_equal(x : Image, y : Image) -> Bool

    ImageErrorKind

    pub(all) enum ImageErrorKind {
    InvalidInput
    ResourceLimit
    UnsupportedFormat
    InvalidDimensions
    NotSquare
    } derive(Eq,
    Debug
    )

    ImageErrorKind::equal

    ImageErrorKind::not_equal

    fn ImageErrorKind::not_equal(x : ImageErrorKind, y : ImageErrorKind) -> Bool

    PngVariant

    pub(all) struct PngVariant {
    size : Int
    png : Bytes
    }

    SquarePolicy

    pub(all) enum SquarePolicy {
    Strict
    CenterCrop
    } derive(Eq,
    Debug
    )

    SquarePolicy::equal

    SquarePolicy::not_equal

    fn SquarePolicy::not_equal(x : SquarePolicy, y : SquarePolicy) -> Bool

    decode_png

    fn decode_png(input : Bytes, limits? : DecodeLimits) -> Image raise ImageError

    Decode a non-interlaced, 8-bit PNG into RGBA8. Every chunk checksum and the zlib Adler-32 checksum are verified before returning pixels.

    default_decode_limits

    fn default_decode_limits() -> DecodeLimits

    Default limits: 64 MiB compressed input, 16,384 pixels per edge, 64 MiB RGBA.

    default_icns_sizes

    fn default_icns_sizes() -> Array[Int]

    default_ico_sizes

    fn default_ico_sizes() -> Array[Int]

    encode_icns

    fn encode_icns(image : Image, sizes? : Array[Int], compression_level? : Int) -> Bytes raise ImageError

    Encode a deterministic ICNS containing PNG chunks for standard macOS icon sizes and their Retina chunk counterparts.

    encode_ico

    fn encode_ico(image : Image, sizes? : Array[Int], compression_level? : Int) -> Bytes raise ImageError

    Encode an ICO whose directory entries point to PNG payloads.

    encode_png

    fn encode_png(image : Image, compression_level? : Int) -> Bytes raise ImageError

    Encode image pixels as a deterministic RGBA PNG with no metadata chunks.

    encode_png_sizes

    fn encode_png_sizes(image : Image, sizes : Array[Int], compression_level? : Int) -> Array[PngVariant] raise ImageError

    Encode caller-selected square PNG icon sizes in the requested order.

    png_data_uri_svg

    fn png_data_uri_svg(png : Bytes, width : Int, height : Int) -> String raise ImageError

    Wrap a PNG byte sequence in a portable data-URI SVG image element.

    resize_lanczos3

    fn resize_lanczos3(image : Image, width : Int, height : Int) -> Image raise ImageError

    Resize RGBA8 pixels with a Lanczos3 reconstruction filter in premultiplied alpha space. Premultiplication prevents transparent colors from producing dark fringes after resampling.

    square_image

    fn square_image(image : Image, policy? : SquarePolicy) -> Image raise ImageError

    Return a square source image. Strict rejects a non-square input; the opt-in crop policy retains the centered square region.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io