Description
Use case
Currently in flutter there is not a convenient way to create an Image
of a given width and height, and then set individual pixels on said Image
before displaying it.
Consider the following example program:
import 'dart:async';
import 'dart:math';
import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart' hide Image;
void main() async {
final Completer<Image> completer = Completer<Image>();
const int w = 640;
const int h = 640;
final Int32List img = Int32List(w * h);
final Random random = Random();
double x = 0;
double y = 0;
for (int i = 0; i < 200000; i++) {
double tmpx, tmpy;
final double r = random.nextDouble();
if (r <= 0.01) {
tmpx = 0;
tmpy = 0.16 * y;
} else if (r <= 0.08) {
tmpx = 0.2 * x - 0.26 * y;
tmpy = 0.23 * x + 0.22 * y + 1.6;
} else if (r <= 0.15) {
tmpx = -0.15 * x + 0.28 * y;
tmpy = 0.26 * x + 0.24 * y + 0.44;
} else {
tmpx = 0.85 * x + 0.04 * y;
tmpy = -0.04 * x + 0.85 * y + 1.6;
}
x = tmpx;
y = tmpy;
final int col = (w / 2 + x * w / 11).round();
final int row = (h - y * h / 11).round();
img[row * w + col] = Colors.green.value;
}
decodeImageFromPixels(
img.buffer.asUint8List(),
w,
h,
PixelFormat.bgra8888,
completer.complete,
);
runApp(RawImage(image: await completer.future));
}
As far as I know, this is the only available api for this in flutter today. It is a bit awkward because you have to use a 1 dimensional array (Int32List
), when conceptually an Image
is a 2 dimensional array. You want to be able to easily set the value of a pixel at a given x
and y
coordinate. Also decodeImageFromPixels
feels a bit awkward as well, having to use a Completer
to retrieve the Image
.
You can compare this program to the same program written in many other languages and frameworks: https://rosettacode.org/wiki/Barnsley_fern. In many other languages there is a an api for this along the lines of image = Image(width, height)
and image.setPixel(x, y, color)
, for example the BufferedImage
in the Java example.
There aren't any existing packages on pub.dev for this (as far as I can tell), It would be possible to write a package to help with this, but it seems like something that should be in the framework itself.
Proposal
If there was a class for this, lets say we call it ImageBuffer
, it's usage might look like the following:
import 'dart:math';
import 'dart:ui';
import 'package:flutter/material.dart';
void main() async {
final ImageBuffer img = ImageBuffer(640, 640);
final Random random = Random();
double x = 0;
double y = 0;
for (int i = 0; i < 200000; i++) {
double tmpx, tmpy;
final double r = random.nextDouble();
if (r <= 0.01) {
tmpx = 0;
tmpy = 0.16 * y;
} else if (r <= 0.08) {
tmpx = 0.2 * x - 0.26 * y;
tmpy = 0.23 * x + 0.22 * y + 1.6;
} else if (r <= 0.15) {
tmpx = -0.15 * x + 0.28 * y;
tmpy = 0.26 * x + 0.24 * y + 0.44;
} else {
tmpx = 0.85 * x + 0.04 * y;
tmpy = -0.04 * x + 0.85 * y + 1.6;
}
x = tmpx;
y = tmpy;
img.setPixel(
(img.width / 2 + x * img.width / 11).round(), // x position
(img.height - y * img.height / 11).round(), // y position
Colors.green.value, // color value
);
}
runApp(RawImage(image: await img.decode()));
}