From f0ddadd74fb341752d7a963c90e5db1a91ebe4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Costa?= Date: Sun, 5 Jan 2025 10:52:07 +0000 Subject: [PATCH] Add tabulate to backend surfaces --- .../backend/ImageDataOpaqueSurface.scala | 22 ++++++++++++++++ .../minart/backend/ImageDataSurface.scala | 22 ++++++++++++++++ .../minart/backend/BufferedImageSurface.scala | 26 +++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataOpaqueSurface.scala b/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataOpaqueSurface.scala index 5adfe013..5050813b 100644 --- a/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataOpaqueSurface.scala +++ b/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataOpaqueSurface.scala @@ -80,6 +80,28 @@ final class ImageDataOpaqueSurface(val data: ImageData) extends MutableSurface { object ImageDataOpaqueSurface { + /** Produces an opaque ImageData backed surface containing values of a given function + * over ranges of integer values starting from 0. + * + * @param width the surface width + * @param height the surface height + * @param f the function computing the element values + */ + def tabulate(width: Int, height: Int)(f: (Int, Int) => Color): ImageDataOpaqueSurface = { + val surface = + ImageDataOpaqueSurface.fromImage(new Image(width, height)) + var y = 0 + while (y < height) { + var x = 0 + while (x < width) { + surface.unsafePutPixel(x, y, f(x, y)) + x += 1 + } + y += 1 + } + surface + } + /** Loads an ImageDataOpaqueSurface from an offscreen canvas * * @param canvas offscreen canvas diff --git a/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataSurface.scala b/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataSurface.scala index 1a252090..566acf4a 100644 --- a/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataSurface.scala +++ b/backend/js/src/main/scala/eu/joaocosta/minart/backend/ImageDataSurface.scala @@ -78,6 +78,28 @@ final class ImageDataSurface(val data: ImageData) extends MutableSurface { object ImageDataSurface { + /** Produces an ImageData backed surface containing values of a given function + * over ranges of integer values starting from 0. + * + * @param width the surface width + * @param height the surface height + * @param f the function computing the element values + */ + def tabulate(width: Int, height: Int)(f: (Int, Int) => Color): ImageDataSurface = { + val surface = + ImageDataSurface.fromImage(new Image(width, height)) + var y = 0 + while (y < height) { + var x = 0 + while (x < width) { + surface.unsafePutPixel(x, y, f(x, y)) + x += 1 + } + y += 1 + } + surface + } + /** Loads an ImageDataOpaqueSurface from an offscreen canvas * * @param canvas offscreen canvas diff --git a/backend/jvm/src/main/scala/eu/joaocosta/minart/backend/BufferedImageSurface.scala b/backend/jvm/src/main/scala/eu/joaocosta/minart/backend/BufferedImageSurface.scala index 47dd93fc..2d47a972 100644 --- a/backend/jvm/src/main/scala/eu/joaocosta/minart/backend/BufferedImageSurface.scala +++ b/backend/jvm/src/main/scala/eu/joaocosta/minart/backend/BufferedImageSurface.scala @@ -67,3 +67,29 @@ final class BufferedImageSurface(val bufferedImage: BufferedImage) extends Mutab super.blit(that, blendMode)(x, y, cx, cy, cw, ch) } } + +object BufferedImageSurface { + + /** Produces a BufferedImage backed surface containing values of a given function + * over ranges of integer values starting from 0. + * + * @param width the surface width + * @param height the surface height + * @param f the function computing the element values + */ + def tabulate(width: Int, height: Int)(f: (Int, Int) => Color): BufferedImageSurface = { + val surface = + new BufferedImageSurface(new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)) + var y = 0 + while (y < height) { + var x = 0 + while (x < width) { + surface.unsafePutPixel(x, y, f(x, y)) + x += 1 + } + y += 1 + } + surface + } + +}