Changelog of @hackage/gb-sprite 0.5.0.0

Changelog

0.5.0.0

Breaking Changes

  • BMP.hs and PNG.hs are now pure. writeBmp and writePng have moved to GBSprite.Export. Import from GBSprite.Export instead of GBSprite.BMP or GBSprite.PNG for file I/O. The pure encoders encodeBmp and encodePng remain in their original modules.
  • Eliminated unsafePerformIO from Import.hs. PNG decompression now uses the zlib streaming API (Codec.Compression.Zlib.Internal) for fully pure, exception-free error handling.

New Modules

  • GBSprite.Adjust — Canvas-wide color adjustments: grayscale, invert, tint, brightness, contrast, saturation, hue shift, color remapping, posterize, threshold, sepia.
  • GBSprite.Filter — Convolution filters: box blur, Gaussian blur (3-pass approximation), sharpen (unsharp mask), Sobel edge detection, bloom (bright extract + blur + additive blend).
  • GBSprite.Import — Native BMP and PNG decoding. Read 24/32-bit BMP and 8-bit RGB/RGBA PNG files back into Canvas. Supports all 5 PNG filter types (None, Sub, Up, Average, Paeth). Pure decoders (decodeBmp, decodePng) and IO wrappers (readBmp, readPng).
  • GBSprite.Isometric — Isometric projection for 2:1 diamond tiles. World/screen coordinate conversion, point-in-diamond hit testing, depth sorting, diamond drawing/filling, and isometric tilemap rendering.

New Features

  • HSL/HSV color space (Color): toHSL, fromHSL, toHSV, fromHSV, and derived transforms (tintColor, invertColor, grayscaleColor, brightenColor, contrastColor, saturateColor, shiftHueColor).
  • Arbitrary rotation (Transform): rotateArbitrary with bilinear interpolation for any angle in degrees.
  • Bilinear scaling (Transform): scaleBilinear for smooth up/down scaling; scaleTo for exact target dimensions.
  • Shear transforms (Transform): shearH and shearV.
  • Anti-aliased lines (Draw): drawAALine using Wu's algorithm.
  • Cubic Bezier curves (Draw): drawCubicBezier.
  • Catmull-Rom splines (Draw): drawCatmullRom — smooth curves through control points.
  • Pattern fill (Draw): patternFill — fill a rectangular area with a repeating tile.
  • Blend modes (Compose): BlendMultiply, BlendScreen, BlendOverlay, BlendAdditive, BlendSoftLight, BlendDifference via blendCompose.
  • Alpha masking (Compose): maskCanvas — clip rendering to a mask's alpha channel.
  • Perlin noise (Noise): perlinNoise — gradient noise with dot-product interpolation.
  • Worley noise (Noise): worleyNoise — cellular/Voronoi patterns.
  • Turbulence (Noise): turbulence — absolute-value FBM for fire/cloud/water textures.
  • Palette lerp (Palette): paletteLerp — interpolate between two palettes for day/night transitions.
  • Palette extraction (Palette): extractPalette — derive a palette from a canvas using median cut.
  • Color quantization (Palette): quantizeColor — map a color to the nearest palette entry.
  • Sprite mirroring (Sprite): mirrorSprite — horizontal flip of all frames.
  • Sprite trimming (Sprite): trimSprite — crop transparent borders from all frames.
  • Animation blending (Animation): blendFrames — cross-fade between two canvases.
  • Canvas crop/trim (Canvas): crop, trimTransparent, canvasOpacity.
  • Canvas dimension clamping: newCanvas and fromPixels now clamp dimensions to minimum 1.
  • Empty string guard: renderText returns a valid 1-pixel-wide canvas for empty input.

Bug Fixes

  • Fix Porter-Duff alpha blend (Color): alphaBlend now correctly weights the destination channel by dstA when compositing semi-transparent colors. Previously, the destination RGB contribution was over-weighted when dstA < 255.
  • Fix isometric diamond off-by-one (Isometric): drawDiamond and fillDiamond now draw within the tw x th bounding box (previously drew (tw+1) x (th+1) pixels).
  • Fix shear direction (Transform): shearH and shearV now shift in the documented direction (positive values shift bottom rows right / right columns down).
  • Fix PNG decompression exception (Import): decodePng uses the zlib streaming API for pure error handling — no unsafePerformIO, no caught exceptions.
  • Fix bloom luminance (Filter): Bloom threshold now uses BT.709 perceptual weights instead of simple RGB average.
  • Fix sprite sheet vertical padding (Sheet): Shelf packing now applies padding between shelves vertically, not just horizontally.
  • Fix Perlin gradient vectors (Noise): Diagonal gradients now use exact 1/sqrt(2) instead of truncated 0.707.
  • Fix dither performance (Dither): Bayer matrices backed by ByteString for O(1) lookup (was O(n) list traversal per pixel). findClosest now carries best distance in accumulator (halves comparisons).
  • Fix wrapHue performance (Color): O(1) modular arithmetic replaces recursive subtract/add loop.
  • Fix maskCanvas docstring (Compose): Corrected to say "alpha channel" (was incorrectly "luminance").

Tests

  • 591 tests (up from 366). Full coverage of all new modules and bug fixes.

0.4.0.0

Breaking Changes

  • Drop vector dependency. Canvas pixel storage changed from Data.Vector.Storable.Vector Word8 to strict ByteString. Users pattern-matching on cPixels will need to update. All public API functions are unchanged.

New

  • Native PNG export (GBSprite.PNG): hand-rolled 32-bit RGBA PNG encoder using zlib for DEFLATE compression and a pure CRC32 implementation. PNG export is now always available — no flags, no JuicyPixels.
  • GBSprite.Export now re-exports both exportBmp and exportPng.
  • 10 new PNG tests (366 total, up from 356).

Removed

  • juicy-pixels flag and GBSprite.Export.PNG — replaced by native GBSprite.PNG.
  • vector dependency — pixel data backed by strict ByteString instead of Vector.Storable. Same performance characteristics, fewer dependencies.

Dependencies

  • base, bytestring, zlib — that's it. Down from base, bytestring, vector, optional JuicyPixels.

0.3.0.1

Fixes

  • Fix BMP roundtrip test leaking temp files — tests now clean up after themselves.
  • Replace partial !! with safe indexing in BMP test.
  • Fix CI: run haddock before build to avoid stale .hi files causing 0% doc coverage.
  • Fix README: correct encodeBmp return type, add missing API sections (Palette, Sprite, Tilemap), add missing exported functions.

0.3.0.0

Bug Fixes

  • Fix drawEllipse midpoint algorithm: region 2 now continues from where region 1 ended instead of restarting at (rx, 0). Ellipses now correctly plot all four cardinal edge pixels.
  • Fix safeSetPixel in VFX.hs: use setPixel directly instead of fillCircle with radius 0.
  • Replace partial minimum/maximum with safe folds in fillPolygon (Draw.hs) and computeMaxWidth (Sheet.hs).
  • Fix grayscale4 palette: was a duplicate of gameboy (green-tinted). Now uses evenly-spaced true grayscale (0, 85, 170, 255).

Performance

  • Replace 16 lazy foldl with strict foldl' across Draw.hs, VFX.hs, Sheet.hs, Tilemap.hs, and Text.hs.

Internal

  • 356 tests (up from 105): comprehensive coverage of all modules.
  • CI and cabal: tested-with upgraded from GHC 9.6 to GHC 9.8.
  • Publish workflow: replace sed version-patching with tag/cabal version verification.

0.2.1.2

  • Change license from MIT to BSD-3-Clause.

Bug Fixes

  • Fix maximum crash on empty list in packSheet (Sheet.hs).
  • Replace partial !! with safe indexing in Bayer dithering (Dither.hs).
  • Fix -Wname-shadowing warning in test suite.

Documentation

  • Fix README Animation API section (wrong type name and signatures).
  • Add gb-vector as ecosystem companion in README.

Internal

  • CI: cross-platform build matrix (Linux, macOS, Windows).

0.2.1.1

  • Remove unused containers dependency.

0.2.1.0

Performance

Library-wide elimination of O(n²) per-pixel setPixel/VS.// mutation. All pixel-producing functions now use single-pass VS.generate for O(n) performance.

  • NineSlice: renderNineSlice — rewritten for large target sizes that previously stalled.
  • Transform: flipH, flipV, rotate90, rotate180, rotate270, scaleNearest, outline, dropShadow — all rewritten with direct index computation.
  • Compose: stamp, stampAlpha — single-pass with inline source/destination byte reads.
  • Gradient: linearGradient, radialGradient, diagonalGradient — generate directly from coordinate math.
  • Noise: valueNoiseColor, fbm — generate noise samples directly into output vector.
  • Dither: orderedDither — single-pass palette reduction.

0.2.0.0

New Modules

  • GBSprite.Noise: Procedural noise generation — valueNoise, valueNoiseColor, fbm (fractal Brownian motion). Deterministic LCG with bilinear interpolation and smoothstep.
  • GBSprite.Gradient: Gradient generation — linearGradient (horizontal/vertical), radialGradient, diagonalGradient.
  • GBSprite.NineSlice: UI panel scaling — NineSlice type with configurable border regions, renderNineSlice preserves corners and edges at any target size.
  • GBSprite.Dither: Ordered dithering — orderedDither with Bayer2, Bayer4, Bayer8 matrices for palette reduction. Classic retro cross-hatch patterns.
  • GBSprite.Export.PNG: Separated from Export.hs, eliminating CPP. Only built when juicy-pixels flag is enabled.

Bug Fixes

  • Eliminate CPP from Export.hs — split into GBSprite.Export (BMP, always available) and GBSprite.Export.PNG (optional).

Internal

  • 105 pure tests (up from 62)
  • 12 new Draw function tests (drawThickLine, drawPolygon, fillPolygon, drawEllipse, fillEllipse, drawBezier, drawRoundRect, fillRoundRect)
  • CI: ormolu glob src/**/*.hs replaces hardcoded file list
  • CI: jobs chained so lint/format gate build (saves Actions minutes on failure)
  • Metadata: cabal-version 3.0, stability experimental, CHANGELOG.md

0.1.0.0

Initial release.

Canvas & Color

  • Canvas type: width, height, RGBA pixel vector
  • Color type with lerp, multiply, alphaBlend, withAlpha, scaleAlpha
  • Bounds-checked getPixel / setPixel (out-of-bounds returns transparent)

Drawing Primitives

  • Lines: drawLine, drawThickLine
  • Rectangles: drawRect, fillRect, drawRoundRect, fillRoundRect
  • Circles: drawCircle, fillCircle
  • Ellipses: drawEllipse, fillEllipse
  • Polygons: drawPolygon, fillPolygon
  • Curves: drawBezier, drawArc

Transforms

  • flipH, flipV, rotate90, rotate180, rotate270
  • scaleNearest: nearest-neighbour scaling

Composition

  • stamp: blit with transparency
  • overlay: layer multiple canvases

Animation

  • Animation type with Loop, Once, PingPong modes
  • Frame indexing with animationDone predicate

Sprites & Sheets

  • Sprite type: multi-frame sprite container
  • packSheet: bin-packing sprite sheet atlas

Text

  • renderText: bitmap font text rendering
  • textWidth: measure text width in pixels

VFX

  • explosion: animated explosion effect
  • ring: expanding ring effect
  • flash: screen flash frames

Palettes

  • Palette type with indexed color lookup
  • paletteSwap: remap colors
  • Built-in: gameboy (4-color Game Boy palette)

Export

  • exportBmp: native BMP file export (always available)
  • exportPng: PNG export via JuicyPixels (optional juicy-pixels flag)