From 60f5ce3cc1c64cb8673ba444c653b34598606b58 Mon Sep 17 00:00:00 2001 From: Unknown Date: Mon, 12 Feb 2018 15:55:45 +0100 Subject: [PATCH 1/7] Remove Pointers to Image Lib --- lib/Dither.dart | 18 ++++++++++++++++++ lib/dither.dart | 3 +++ pubspec.yaml | 1 - web/main.dart | 40 ++++++---------------------------------- 4 files changed, 27 insertions(+), 35 deletions(-) create mode 100644 lib/Dither.dart create mode 100644 lib/dither.dart diff --git a/lib/Dither.dart b/lib/Dither.dart new file mode 100644 index 0000000..6cc123f --- /dev/null +++ b/lib/Dither.dart @@ -0,0 +1,18 @@ +import 'dart:html'; + +class Dither { + static ImageData editImage(ImageData image) { + + +// image = contrast( image, 200); + + for (var y = 0; y < image.height; y++) { + for (var x = 0; x < image.width; x++) { +// print(image.getPixel(x, y)); + } + } + + return image; + } + +} diff --git a/lib/dither.dart b/lib/dither.dart new file mode 100644 index 0000000..7c5d5e3 --- /dev/null +++ b/lib/dither.dart @@ -0,0 +1,3 @@ +library dither; + +export 'Dither.dart'; \ No newline at end of file diff --git a/pubspec.yaml b/pubspec.yaml index 522ef38..02840b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,7 +8,6 @@ environment: sdk: '>=1.20.1 <2.0.0' dependencies: - image: "^1.1.29" # path: ^1.4.1 dev_dependencies: diff --git a/web/main.dart b/web/main.dart index 23f277c..b9f9f47 100644 --- a/web/main.dart +++ b/web/main.dart @@ -1,56 +1,28 @@ import 'dart:html'; -import 'package:image/image.dart'; +import 'package:dart_floyd_steinberg_dithering/Dither.dart'; CanvasElement input; CanvasElement output; ImageElement inputImg; +ImageElement outputImg; void main() { inputImg = new ImageElement(src: 'kitten.jpg', width: 712, height: 470); input = document.querySelector('#input'); - print(input); - inputImg.onLoad.listen(imgLoaded); - output = document.querySelector('#output'); - output.context2D.fillRect(0, 0, output.width, output.height); + inputImg.onLoad.listen(imgLoaded); } void imgLoaded(Event e) { print("image loaded"); input.context2D.drawImage(inputImg, 0, 0); - Image outputImg = editImage( getImageFromCanvas(input) ); - - drawImageToCanvas(output, outputImg ) ; + output.context2D.putImageData( Dither.editImage( getImageData(input)), 0, 0); } -Image getImageFromCanvas(CanvasElement input) { - ImageData data = input.context2D.getImageData(0, 0, input.width, input.height); - return new Image.fromBytes(input.width, input.height, data.data); -} - -void drawImageToCanvas(CanvasElement canvas, Image image) { - var imageData = canvas.context2D.createImageData(image.width, image.height); - imageData.data.setRange(0, imageData.data.length, image.getBytes()); - - canvas.context2D.putImageData(imageData, 0, 0); -} - -Image editImage(Image image) { - - - image = contrast( image, 200); - - for (var y = 0; y < image.height; y++) { - for (var x = 0; x < image.width; x++) { -// print(image.getPixel(x, y)); - } - } - - - - return image; +ImageData getImageData(CanvasElement canvas) { + return canvas.context2D.getImageData(0, 0, canvas.width, canvas.height); } \ No newline at end of file From d6503bb613c408e7892897fd231ea3b3888942ce Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 15:19:21 +0100 Subject: [PATCH 2/7] Add Basic Data Structures --- lib/Dither.dart | 102 ++++++++++++++++++++++++++++++++++++++++++------ web/main.dart | 1 - 2 files changed, 91 insertions(+), 12 deletions(-) diff --git a/lib/Dither.dart b/lib/Dither.dart index 6cc123f..7cc3f6c 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -1,18 +1,98 @@ import 'dart:html'; +import 'dart:typed_data'; -class Dither { - static ImageData editImage(ImageData image) { +class Pixel { + int x; + int y; + int r; + int g; + int b; + int a; + Pixel(this.x, this.y, this.r, this.g, this.b, this.a); -// image = contrast( image, 200); - - for (var y = 0; y < image.height; y++) { - for (var x = 0; x < image.width; x++) { -// print(image.getPixel(x, y)); - } - } - - return image; + 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}'; + } + + } + +class PixelArray { + List> pixels; + + 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); + } + pixels[y][x] = new Pixel(x, y, array[pos], array[pos+1], array[pos+2], array[pos+3]); + x++; + } + } + + 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; + + x++; + } + + return result; + } + + Pixel getPixel(int x, int y) { + return pixels[y][x]; + } + + void setPixel(Pixel pixel, [int x, int y]) { + if (x != null && y != null && pixels[y] != null && pixels[y].length >= x) { + pixel.x = x; + pixel.y = y; + pixels[y][x] = pixel; + return; + } else if (pixels.length < pixel.y || pixels[y].length < pixel.x) { + return; + } else { + pixels[pixel.y][pixel.x] = pixel; + return; + } + } + + int getWidth() { + return pixels[0].length; + } + + int getHeight() { + return pixels.length; + } +} \ No newline at end of file diff --git a/web/main.dart b/web/main.dart index b9f9f47..7e712d9 100644 --- a/web/main.dart +++ b/web/main.dart @@ -20,7 +20,6 @@ void imgLoaded(Event e) { print("image loaded"); input.context2D.drawImage(inputImg, 0, 0); - output.context2D.putImageData( Dither.editImage( getImageData(input)), 0, 0); } ImageData getImageData(CanvasElement canvas) { From fb7776feac38b7e04640bac1113968e0de22d035 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 15:27:33 +0100 Subject: [PATCH 3/7] PixelArray from ImageData constructor --- lib/Dither.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Dither.dart b/lib/Dither.dart index 7cc3f6c..839fe79 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -49,6 +49,8 @@ class PixelArray { } } + PixelArray.fromImageData(ImageData imagedata, int imageWidth): this.fromByteArray(imagedata.data, imageWidth); + 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); From 881da038251566b2dbbedcc19c18e3dc6a2ce2ab Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 15:54:28 +0100 Subject: [PATCH 4/7] Add Helper Functions create PixelArray from another PixelArray create empty PixelArray convert PixelArray to ImageData --- lib/Dither.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/lib/Dither.dart b/lib/Dither.dart index 839fe79..ce0032c 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -32,6 +32,10 @@ class Pixel { class PixelArray { List> pixels; + PixelArray(int width, int height) { + pixels = new List.filled(height, new List(width)); + } + PixelArray.fromByteArray(Uint8ClampedList array, int imageWidth) { pixels = new List(array.length~/imageWidth~/4); int y = 0; @@ -51,6 +55,10 @@ class PixelArray { PixelArray.fromImageData(ImageData imagedata, int imageWidth): this.fromByteArray(imagedata.data, imageWidth); + PixelArray.fromPixelArray(PixelArray pixelArray) { + pixels = new List>.from(pixelArray.pixels); + } + 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); @@ -72,6 +80,10 @@ class PixelArray { return result; } + ImageData toImageData() { + return new ImageData(this.toByteArray(), this.getWidth(), this.getHeight()); + } + Pixel getPixel(int x, int y) { return pixels[y][x]; } From 33e07962bd18ba31fcc0cc2ddc46f92ffe868e40 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 15:56:55 +0100 Subject: [PATCH 5/7] Add Greyscale Function --- lib/Dither.dart | 18 ++++++++++++++++++ web/main.dart | 4 ++++ web/styles.css | 4 ++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/Dither.dart b/lib/Dither.dart index ce0032c..940c068 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -1,6 +1,24 @@ import 'dart:html'; import 'dart:typed_data'; +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; + } + } + + return pxArr; + } +} + class Pixel { int x; int y; diff --git a/web/main.dart b/web/main.dart index 7e712d9..ef830c7 100644 --- a/web/main.dart +++ b/web/main.dart @@ -20,6 +20,10 @@ void imgLoaded(Event e) { print("image loaded"); input.context2D.drawImage(inputImg, 0, 0); + PixelArray px = new PixelArray.fromImageData(getImageData(input), 712); + px = Pixed.greyscale(px); + + output.context2D.putImageData(px.toImageData(), 0, 0); } ImageData getImageData(CanvasElement canvas) { diff --git a/web/styles.css b/web/styles.css index 6a88d3b..b8742bc 100644 --- a/web/styles.css +++ b/web/styles.css @@ -6,11 +6,11 @@ html, body { margin: 0; padding: 0; font-family: 'Roboto', sans-serif; - background: gainsboro; + background: black; } canvas { - padding: 00px; + padding: 0px; text-align: center; } From 2f0de10848e8498a11a3abfc8a7728a12b12e8a4 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 16:44:56 +0100 Subject: [PATCH 6/7] Add PixelArray clone function --- lib/Dither.dart | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/Dither.dart b/lib/Dither.dart index 940c068..8579376 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -48,10 +48,17 @@ class Pixel { } class PixelArray { + //TODO Implement iterable List> pixels; PixelArray(int width, int height) { - pixels = new List.filled(height, new List(width)); + 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); + } + } } PixelArray.fromByteArray(Uint8ClampedList array, int imageWidth) { @@ -107,12 +114,12 @@ class PixelArray { } void setPixel(Pixel pixel, [int x, int y]) { - if (x != null && y != null && pixels[y] != null && pixels[y].length >= x) { + if (x != null && y != null && getHeight() < y && getWidth() < x) { pixel.x = x; pixel.y = y; pixels[y][x] = pixel; return; - } else if (pixels.length < pixel.y || pixels[y].length < pixel.x) { + } else if (getHeight() <= pixel.y || getWidth() <= pixel.x) { return; } else { pixels[pixel.y][pixel.x] = pixel; @@ -121,10 +128,23 @@ class PixelArray { } int getWidth() { + //TODO find longest/shortest width not at 0 (support for non square img) return pixels[0].length; } int getHeight() { return pixels.length; } + + 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; + } } \ No newline at end of file From 4a341451ba9f1a9db517fa5a39b3285b09aa5034 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 14 Feb 2018 16:45:43 +0100 Subject: [PATCH 7/7] Add quantize Function --- lib/Dither.dart | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/lib/Dither.dart b/lib/Dither.dart index 8579376..7f1cdb9 100644 --- a/lib/Dither.dart +++ b/lib/Dither.dart @@ -14,7 +14,33 @@ class Pixed { px.b = average; } } + return pxArr; + } + 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; + } + } return pxArr; } }