floyd-steinberg-dithering/lib/Dither.dart

176 lines
4.4 KiB
Dart
Raw Permalink Normal View History

2018-02-12 14:55:45 +00:00
import 'dart:html';
2018-02-14 14:19:21 +00:00
import 'dart:typed_data';
2018-02-12 14:55:45 +00:00
2018-02-14 14:56:55 +00:00
class Pixed {
static PixelArray greyscale(PixelArray image) {
PixelArray pxArr = new PixelArray.fromPixelArray(image);
for (var y = 0; y < pxArr.getHeight(); y++) {
for (var x = 0; x < pxArr.getWidth(); x++) {
var px = pxArr.getPixel(x, y);
int average = ((px.r+px.g+px.b) / 3).round();
px.r = average;
px.g = average;
px.b = average;
}
}
2018-02-14 15:45:43 +00:00
return pxArr;
}
2018-02-14 14:56:55 +00:00
2018-02-14 15:45:43 +00:00
static PixelArray quantize(PixelArray image, [int steps=1]) {
PixelArray pxArr = new PixelArray.fromPixelArray(image);
for (var y = 0; y < pxArr.getHeight(); y++) {
for (var x = 0; x < pxArr.getWidth(); x++) {
var px = pxArr.getPixel(x, y);
px.r = (steps * px.r / 255).round() * (255 ~/ steps);
px.g = (steps * px.g / 255).round() * (255 ~/ steps);
px.b = (steps * px.b / 255).round() * (255 ~/ steps);
}
}
return pxArr;
}
static PixelArray calcQuantizeError(PixelArray original, PixelArray quantized) {
PixelArray pxArr = new PixelArray.fromPixelArray(original);
for (var y = 0; y < pxArr.getHeight(); y++) {
for (var x = 0; x < pxArr.getWidth(); x++) {
Pixel px = pxArr.getPixel(x, y);
Pixel quant = quantized.getPixel(x, y);
px.r = px.r - quant.r;
px.g = px.g - quant.g;
px.b = px.b - quant.b;
}
}
2018-02-14 14:56:55 +00:00
return pxArr;
}
}
2018-02-14 14:19:21 +00:00
class Pixel {
int x;
int y;
int r;
int g;
int b;
int a;
2018-02-12 14:55:45 +00:00
2018-02-14 14:19:21 +00:00
Pixel(this.x, this.y, this.r, this.g, this.b, this.a);
int getBytePos(int imageWidth) {
return (x+y*imageWidth)*4;
}
void setRGB(int r, int g, int b) {
this.r = r;
this.g = g;
this.b = b;
}
@override
String toString() {
return 'Pixel at $x, $y: {r: $r, g: $g, b: $b, a: $a}';
}
2018-02-12 14:55:45 +00:00
2018-02-14 14:19:21 +00:00
}
class PixelArray {
2018-02-14 15:44:56 +00:00
//TODO Implement iterable
2018-02-14 14:19:21 +00:00
List<List<Pixel>> pixels;
PixelArray(int width, int height) {
2018-02-14 15:44:56 +00:00
pixels = new List(height);
for (int y = 0; y < height; y++) {
pixels[y] = new List(width);
for (int x = 0; x < height; x++) {
pixels[y][x] = new Pixel(x, y, 0, 0, 0, 0);
}
}
}
2018-02-14 14:19:21 +00:00
PixelArray.fromByteArray(Uint8ClampedList array, int imageWidth) {
pixels = new List(array.length~/imageWidth~/4);
int y = 0;
int x = 0;
pixels[y] = new List(imageWidth);
print(pixels[0].length.toString() + ","+ pixels.length.toString());
for (var pos = 0; pos < array.length; pos = pos + 4) {
if (x >= imageWidth) {
x = 0;
y++;
pixels[y] = new List(imageWidth);
2018-02-12 14:55:45 +00:00
}
2018-02-14 14:19:21 +00:00
pixels[y][x] = new Pixel(x, y, array[pos], array[pos+1], array[pos+2], array[pos+3]);
x++;
2018-02-12 14:55:45 +00:00
}
2018-02-14 14:19:21 +00:00
}
2018-02-14 14:27:33 +00:00
PixelArray.fromImageData(ImageData imagedata, int imageWidth): this.fromByteArray(imagedata.data, imageWidth);
PixelArray.fromPixelArray(PixelArray pixelArray) {
pixels = new List<List<Pixel>>.from(pixelArray.pixels);
}
2018-02-14 14:19:21 +00:00
Uint8ClampedList toByteArray() {
//TODO: look for longest array, or each line separately. Only gets width from line 1 currently.
Uint8ClampedList result = new Uint8ClampedList(getHeight()*getWidth()*4);
int x = 0;
int y = 0;
for (var i = 0; i < result.length; i = i + 4) {
if (x >= getWidth()) {
y++;
x = 0;
}
result[i] = pixels[y][x].r;
result[i+1] = pixels[y][x].g;
result[i+2] = pixels[y][x].b;
result[i+3] = pixels[y][x].a;
2018-02-12 14:55:45 +00:00
2018-02-14 14:19:21 +00:00
x++;
}
return result;
2018-02-12 14:55:45 +00:00
}
ImageData toImageData() {
return new ImageData(this.toByteArray(), this.getWidth(), this.getHeight());
}
2018-02-14 14:19:21 +00:00
Pixel getPixel(int x, int y) {
return pixels[y][x];
}
void setPixel(Pixel pixel, [int x, int y]) {
2018-02-14 15:44:56 +00:00
if (x != null && y != null && getHeight() < y && getWidth() < x) {
2018-02-14 14:19:21 +00:00
pixel.x = x;
pixel.y = y;
pixels[y][x] = pixel;
return;
2018-02-14 15:44:56 +00:00
} else if (getHeight() <= pixel.y || getWidth() <= pixel.x) {
2018-02-14 14:19:21 +00:00
return;
} else {
pixels[pixel.y][pixel.x] = pixel;
return;
}
}
int getWidth() {
2018-02-14 15:44:56 +00:00
//TODO find longest/shortest width not at 0 (support for non square img)
2018-02-14 14:19:21 +00:00
return pixels[0].length;
}
int getHeight() {
return pixels.length;
}
2018-02-14 15:44:56 +00:00
PixelArray clone() {
PixelArray pxArr = new PixelArray(getWidth(), getHeight());
for (var y = 0; y < getHeight(); y++) {
for (var x = 0; x < getWidth(); x++) {
Pixel px = getPixel(x, y);
Pixel newPix = new Pixel(x, y, px.r, px.g, px.b, px.a);
pxArr.setPixel( newPix, x, y );
}
}
return pxArr;
}
2018-02-14 14:19:21 +00:00
}