image_pixels_plus 1.0.0
image_pixels_plus: ^1.0.0 copied to clipboard
Read the width/height and the color of any pixel of an image — raster or SVG. A modern, Flutter-web-compatible fork of image_pixels.
1.0.0 #
Initial release of the fork. image_pixels_plus keeps the original
image_pixels API and fixes/modernizes it:
API renamed to match the package #
ImagePixels→ImagePixelsPlusandImagePixelsSvg→ImagePixelsPlusSvg.ImgDetailsis now self-sufficient:pixelColorAt(x, y)andpixelColorAtAlignment(alignment)are real methods instead of nullable function-typed fields — drop the!from your builder code, e.g.img.pixelColorAt!(x, y)becomesimg.pixelColorAt(x, y).pixelColorAtAlignmentnow takes a non-nullableAlignment.ImagePixelsPlus.debugByteDataExtractoris now annotated@visibleForTesting, so the analyzer flags accidental production usage.
Resource-leak fixes #
- Fixed a native-memory leak where
ImageInfoobjects delivered by the image stream were never disposed. Flutter hands every listener an owned clone, so each delivery leaked aui.Imagehandle — per frame for animated GIF/WebP, and again on provider switches, stale deliveries and unmounting. Handles are now owned and disposed correctly in all those paths. (Regression tests prove the leak existed by counting open handles viaui.Image.debugGetOpenHandleStackTraces.) - Fixed a leaked
Pictureon every SVG rasterization (rasterizeSvg) and on the web fallback path ofextractRawRgbaBytes; both are now disposed even when rasterization fails.
Performance #
- New
lazyBytesflag on allImagePixelsPlusconstructors: skips the eager full-image byte extraction (width × height × 4bytes + GPU→CPU readback) until the first pixel read is actually performed. Ideal when you only need dimensions or read pixels rarely. - Redundant re-extraction is skipped when a stream re-delivers an identical
frame;
pixelColorAtAlignmentno longer allocates aSizeper call. - New optional
cacheKeyparameter onImagePixelsPlusSvg: gives customBytesLoaders (which may not implement value equality) a stable identity so ancestor rebuilds don't trigger full SVG parse + rasterization cycles. Built-in flutter_svg loaders already compare by value and need nothing.
API hardening #
rasterizeSvgnow validates its arguments at runtime (release mode too): exactly one source must be given and dimensions must be positive; violations throwArgumentErrorinstead of relying on asserts or crashing with a null-check error.
Flutter web fix #
- Fixed
Failed to encode the image into bytes: pixel extraction now handles web renderers that cannot read back the pixels of a decoded image by re-rasterizing it into a fresh engine-owned surface as a fallback. - Extraction failures degrade gracefully (pixel reads return the
defaultColor) instead of crashing with unhandled exceptions.
SVG support #
- New
ImagePixelsPlusSvgwidget (asset,string,bytesor any vector graphicsBytesLoader) that rasterizes an SVG and gives you the regular pixel-reading API, on all platforms including web. - New
rasterizeSvg()function to rasterize an SVG to aui.Imageyourself. - Rasterization starts in
didChangeDependencies()(notinitState()), since it needs inherited widgets like theme/localization through the context.
API additions #
ImagePixelsPlus.uiImage()constructor for already-decodedui.Images (caller keeps ownership).- Optional
errorBuilder, called when the image fails to load; previously errors were silently swallowed. ImgDetails.hasPixelDatato distinguish "image available" from "pixels readable".
Refactoring / fixes #
- Replaced usage of the protected
loadImage()method with the publicImageProvider.resolve()API. - Proper listener lifecycle: listeners are removed on dispose and on provider changes; a generation counter discards stale async results.
- Fixed a bug where stale pixel bytes could be indexed with new dimensions
while a new image was loading (possible
RangeError). Byte extraction is now atomic with dimension updates, plus defensive bounds checking.
Tooling #
- Full test suite (24 tests): unit tests for byte extraction and SVG rasterization; widget tests for all constructors, error handling, alignment switching, resource-leak regressions (open-handle counting), extraction counting, lazy-mode behavior, same-frame deduplication, argument validation and SVG source-stability scenarios.
- Modernized example app: single showcase file with Material 3 theming, container demo with live alignment picker, raster/SVG pixel pickers with clipboard support, and web platform support.
- Removed the Dart-2 lints
iterable_contains_unrelated_type/list_remove_unrelated_type, superseded bycollection_methods_unrelated_type. - Stopped tracking
pubspec.lock(packages don't commit lockfiles).