diff --git a/pubspec.yaml b/pubspec.yaml index a9538c98..20003ba8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://github.com/brendan-duncan/image documentation: https://github.com/brendan-duncan/image/blob/main/doc/README.md environment: - sdk: '>=2.15.0 <4.0.0' + sdk: '>=3.2.0 <4.0.0' dependencies: archive: ^4.0.1 @@ -20,3 +20,4 @@ dev_dependencies: http: ^1.1.0 lints: ^2.0.1 test: ^1.16.0 + web: ^1.1.0 diff --git a/web/filter_lab.dart b/web/filter_lab.dart index 4d38fb40..ded877d3 100644 --- a/web/filter_lab.dart +++ b/web/filter_lab.dart @@ -1,38 +1,47 @@ -import 'dart:html'; +import 'dart:js_interop'; +import 'dart:typed_data'; import 'package:image/image.dart' as img; +import 'package:web/web.dart'; -late ImageData filterImageData; -late CanvasElement canvas; -late DivElement logDiv; +late HTMLCanvasElement canvas; +late HTMLDivElement logDiv; late img.Image origImage; -void _addControl(String label, String value, DivElement parent, +void _addControl(String label, String value, HTMLDivElement parent, void Function(double) callback) { - final amountLabel = LabelElement()..text = '$label:'; - final amountEdit = InputElement() + final amountLabel = HTMLLabelElement()..text = '$label:'; + final amountEdit = HTMLInputElement() ..value = value ..id = '${label}_edit'; amountEdit.onChange.listen((e) { try { - final d = double.parse(amountEdit.value!); + final d = double.parse(amountEdit.value); callback(d); } catch (e) { //print(e); } }); amountLabel.htmlFor = '${label}_edit'; - parent.append(amountLabel) + parent + ..append(amountLabel) ..append(amountEdit) - ..append(ParagraphElement()); + ..append(HTMLParagraphElement()); +} + +HTMLDivElement _getSidebar() { + final sidebar = document.querySelector('#sidebar') as HTMLDivElement; + while (sidebar.children.length > 0) { + sidebar.removeChild(sidebar.lastChild!); + } + return sidebar; } void testSepia() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); + final sidebar = _getSidebar(); - final label = Element.tag('h1')..text = 'Sepia'; - sidebar.children.add(label); + final label = HTMLHeadingElement.h1()..text = 'Sepia'; + sidebar.appendChild(label); num amount = 1.0; @@ -40,16 +49,13 @@ void testSepia() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); image = img.sepia(image, amount: amount); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('Amount', amount.toString(), sidebar, (num v) { @@ -61,11 +67,10 @@ void testSepia() { } void testSobel() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); + final sidebar = _getSidebar(); - final label = Element.tag('h1')..text = 'Sepia'; - sidebar.children.add(label); + final label = HTMLHeadingElement.h1()..text = 'Sobel'; + sidebar.appendChild(label); num amount = 1.0; @@ -73,15 +78,13 @@ void testSobel() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); image = img.sobel(image, amount: amount); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('Amount', amount.toString(), sidebar, (num v) { @@ -93,11 +96,9 @@ void testSobel() { } void testGaussian() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); - - final label = Element.tag('h1')..text = 'Gaussian Blur'; - sidebar.children.add(label); + final sidebar = _getSidebar(); + final label = HTMLHeadingElement.h1()..text = 'Gaussian Blur'; + sidebar.appendChild(label); var radius = 5; @@ -105,15 +106,13 @@ void testGaussian() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); image = img.gaussianBlur(image, radius: radius); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('Radius', radius.toString(), sidebar, (num v) { @@ -125,11 +124,9 @@ void testGaussian() { } void testVignette() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); - - final label = Element.tag('h1')..text = 'Vignette'; - sidebar.children.add(label); + final sidebar = _getSidebar(); + final label = HTMLHeadingElement.h1()..text = 'Vignette'; + sidebar.appendChild(label); num start = 0.3; num end = 0.75; @@ -139,15 +136,13 @@ void testVignette() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); image = img.vignette(image, start: start, end: end, amount: amount); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('Start', start.toString(), sidebar, (num v) { @@ -169,11 +164,9 @@ void testVignette() { } void testPixelate() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); - - final label = Element.tag('h1')..text = 'Pixelate'; - sidebar.children.add(label); + final sidebar = _getSidebar(); + final label = HTMLHeadingElement.h1()..text = 'Pixelate'; + sidebar.appendChild(label); var blockSize = 5; @@ -181,15 +174,13 @@ void testPixelate() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); image = img.pixelate(image, size: blockSize); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('blockSize', blockSize.toString(), sidebar, (num v) { @@ -201,11 +192,9 @@ void testPixelate() { } void testColorOffset() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); - - final label = Element.tag('h1')..text = 'Pixelate'; - sidebar.children.add(label); + final sidebar = _getSidebar(); + final label = HTMLHeadingElement.h1()..text = 'Color Offset'; + sidebar.appendChild(label); var red = 0; var green = 0; @@ -217,15 +206,13 @@ void testColorOffset() { var image = img.Image.from(origImage); image = img.colorOffset(image, red: red, green: green, blue: blue, alpha: alpha); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('red', red.toString(), sidebar, (num v) { @@ -252,11 +239,9 @@ void testColorOffset() { } void testAdjustColor() { - final sidebar = document.querySelector('#sidebar') as DivElement; - sidebar.children.clear(); - - final label = Element.tag('h1')..text = 'Adjust Color'; - sidebar.children.add(label); + final sidebar = _getSidebar(); + final label = HTMLHeadingElement.h1()..text = 'Adjust Color'; + sidebar.appendChild(label); num contrast = 1.0; num saturation = 1.0; @@ -269,7 +254,6 @@ void testAdjustColor() { void apply() { final t = Stopwatch()..start(); var image = img.Image.from(origImage); - image = img.adjustColor(image, contrast: contrast, saturation: saturation, @@ -278,16 +262,13 @@ void testAdjustColor() { exposure: exposure, hue: hue, amount: amount); - - // Fill the buffer with our image data. - filterImageData.data - .setRange(0, filterImageData.data.length, image.toUint8List()); - // Draw the buffer onto the canvas. - canvas.context2D.clearRect(0, 0, canvas.width!, canvas.height!); - canvas.context2D.putImageData(filterImageData, 0, 0); - logDiv.text = 'TIME: ${t.elapsedMilliseconds / 1000.0}'; - //print(t.elapsedMilliseconds / 1000.0); + final imageBytes = Uint8ClampedList.view(image.toUint8List().buffer); + final imageData = + ImageData(imageBytes.toJS, image.width, image.height.toJS); + // Draw the buffer onto the canvas. + canvas.context2D.clearRect(0, 0, canvas.width, canvas.height); + canvas.context2D.putImageData(imageData, 0, 0); } _addControl('Contrast', contrast.toString(), sidebar, (num v) { @@ -329,10 +310,10 @@ void testAdjustColor() { } void main() { - canvas = document.querySelector('#filter_canvas') as CanvasElement; - logDiv = document.querySelector('#log') as DivElement; + canvas = document.querySelector('#filter_canvas') as HTMLCanvasElement; + logDiv = document.querySelector('#log') as HTMLDivElement; - final menu = document.querySelector('#FilterType') as SelectElement; + final menu = document.querySelector('#FilterType') as HTMLSelectElement; menu.onChange.listen((e) { if (menu.value == 'Pixelate') { testPixelate(); @@ -351,26 +332,23 @@ void main() { } }); - final image = ImageElement(src: 'res/big_buck_bunny.jpg'); + final image = HTMLImageElement()..src = 'res/big_buck_bunny.jpg'; image.onLoad.listen((e) { - final c = CanvasElement() + final c = HTMLCanvasElement() ..width = image.width ..height = image.height ..context2D.drawImage(image, 0, 0); - final imageData = - c.context2D.getImageData(0, 0, image.width!, image.height!); + final imageData = c.context2D.getImageData(0, 0, image.width, image.height); origImage = img.Image.fromBytes( - width: image.width!, - height: image.height!, - bytes: imageData.data.buffer, + width: image.width, + height: image.height, + bytes: imageData.data.toDart.buffer, numChannels: 4); canvas.width = image.width; canvas.height = image.height; - filterImageData = - canvas.context2D.createImageData(image.width, image.height); testSepia(); }); diff --git a/web/filter_lab.html b/web/filter_lab.html index 725ff920..cfc64828 100644 --- a/web/filter_lab.html +++ b/web/filter_lab.html @@ -1,34 +1,56 @@ - - - - - - - filter_lab - - - - -
-

Dart Image: Filter Lab

-
- -
-
- - -
-
-
- - - - + + + + + + + filter_lab + + + + +
+

Dart Image: Filter Lab

+
+ +
+
+ + +
+
+
+ + + +