47 lines
1.3 KiB
Dart
47 lines
1.3 KiB
Dart
|
import 'dart:math' as math;
|
||
|
import 'dart:typed_data';
|
||
|
import 'dart:ui' as ui;
|
||
|
|
||
|
import 'package:flutter/services.dart';
|
||
|
|
||
|
class Bitmap<T> {
|
||
|
// This idiosyncratic usage of "bitmap" comes from some other technology.
|
||
|
// What I'm saying is "don't blame me"
|
||
|
final math.Rectangle<int> rect;
|
||
|
final List<T> data;
|
||
|
|
||
|
Bitmap(this.rect, this.data) {
|
||
|
assert(this.data.length == this.rect.width * this.rect.height);
|
||
|
}
|
||
|
|
||
|
static Future<Bitmap<T>> load<T>(String name, T Function(int) cb) async {
|
||
|
final assetImageByteData = await rootBundle.load(name);
|
||
|
final codec =
|
||
|
await ui.instantiateImageCodec(assetImageByteData.buffer.asUint8List());
|
||
|
final image = (await codec.getNextFrame()).image;
|
||
|
|
||
|
final bytedata =
|
||
|
(await image.toByteData(format: ui.ImageByteFormat.rawStraightRgba))!;
|
||
|
|
||
|
final sx = image.width;
|
||
|
final sy = image.height;
|
||
|
|
||
|
final List<T> data = [];
|
||
|
for (var i = 0; i < sx * sy; i++) {
|
||
|
var pixel = bytedata.getUint32(i * 4, Endian.big);
|
||
|
data.add(cb(pixel));
|
||
|
}
|
||
|
|
||
|
return Bitmap(math.Rectangle(0, 0, sx, sy), data);
|
||
|
}
|
||
|
|
||
|
T? get(int x, int y) {
|
||
|
var realX = x - rect.top;
|
||
|
var realY = y - rect.left;
|
||
|
if (realX < 0 || realY < 0 || realX > rect.width || realY > rect.height) {
|
||
|
return null;
|
||
|
}
|
||
|
return data[realY * rect.width + realX];
|
||
|
}
|
||
|
}
|