From 551c0bd0c3acd161f6d25154ff49762fd92f412f Mon Sep 17 00:00:00 2001 From: Jakub Brzegowski Date: Mon, 23 Mar 2020 14:22:20 +0100 Subject: [PATCH] Add solution to scalashop --- .../scala/scalashop/HorizontalBoxBlur.scala | 14 +++++++---- .../scala/scalashop/VerticalBoxBlur.scala | 15 ++++++++---- .../src/main/scala/scalashop/package.scala | 23 +++++++++++++++++-- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/scalashop/src/main/scala/scalashop/HorizontalBoxBlur.scala b/scalashop/src/main/scala/scalashop/HorizontalBoxBlur.scala index f86b45c..4d733ff 100644 --- a/scalashop/src/main/scala/scalashop/HorizontalBoxBlur.scala +++ b/scalashop/src/main/scala/scalashop/HorizontalBoxBlur.scala @@ -40,8 +40,11 @@ object HorizontalBoxBlur extends HorizontalBoxBlurInterface { * Within each row, `blur` traverses the pixels by going from left to right. */ def blur(src: Img, dst: Img, from: Int, end: Int, radius: Int): Unit = { - // TODO implement this method using the `boxBlurKernel` method - ??? + for (y <- from until end) { + for (x <- 0 until src.width) { + dst.update(x, y, boxBlurKernel(src, x, y, radius)) + } + } } /** Blurs the rows of the source image in parallel using `numTasks` tasks. @@ -51,9 +54,12 @@ object HorizontalBoxBlur extends HorizontalBoxBlurInterface { * rows. */ def parBlur(src: Img, dst: Img, numTasks: Int, radius: Int): Unit = { - // TODO implement using the `task` construct and the `blur` method + val perTask: Int = Math.max(1, src.height / numTasks) + val froms = (0 until src.height by perTask).toList + val blurRanges = froms.zip(froms.tail :+ src.height) + val tasks = blurRanges.map({ case (from, end) => task { blur(src, dst, from, end, radius) }}) - ??? + tasks.foreach(task => task.join()) } } diff --git a/scalashop/src/main/scala/scalashop/VerticalBoxBlur.scala b/scalashop/src/main/scala/scalashop/VerticalBoxBlur.scala index f406e40..213aeeb 100644 --- a/scalashop/src/main/scala/scalashop/VerticalBoxBlur.scala +++ b/scalashop/src/main/scala/scalashop/VerticalBoxBlur.scala @@ -42,8 +42,11 @@ object VerticalBoxBlur extends VerticalBoxBlurInterface { * bottom. */ def blur(src: Img, dst: Img, from: Int, end: Int, radius: Int): Unit = { - // TODO implement this method using the `boxBlurKernel` method - ??? + for (x <- from until end) { + for (y <- 0 until src.height) { + dst.update(x, y, boxBlurKernel(src, x, y, radius)) + } + } } /** Blurs the columns of the source image in parallel using `numTasks` tasks. @@ -53,8 +56,12 @@ object VerticalBoxBlur extends VerticalBoxBlurInterface { * columns. */ def parBlur(src: Img, dst: Img, numTasks: Int, radius: Int): Unit = { - // TODO implement using the `task` construct and the `blur` method - ??? + val perTask: Int = Math.max(1, src.width / numTasks) + val froms = (0 until src.width by perTask).toList + val blurRanges = froms.zip(froms.tail :+ src.width) + val tasks = blurRanges.map({ case (from, end) => task { blur(src, dst, from, end, radius) }}) + + tasks.foreach(task => task.join()) } } diff --git a/scalashop/src/main/scala/scalashop/package.scala b/scalashop/src/main/scala/scalashop/package.scala index ae29e42..f56a115 100644 --- a/scalashop/src/main/scala/scalashop/package.scala +++ b/scalashop/src/main/scala/scalashop/package.scala @@ -41,9 +41,28 @@ package object scalashop extends BoxBlurKernelInterface { /** Computes the blurred RGBA value of a single pixel of the input image. */ def boxBlurKernel(src: Img, x: Int, y: Int, radius: Int): RGBA = { + val (x1, x2) = (clamp(x - radius, 0, src.width - 1), clamp(x + radius, 0, src.width - 1)) + val (y1, y2) = (clamp(y - radius, 0, src.height - 1), clamp(y + radius, 0, src.height - 1)) + val pixelsCount = (x2 - x1 + 1) * (y2 - y1 + 1) + var i = x1 + var j = 0 + var r, g, b, a = 0 + + while (i <= x2) { + j = y1 + while (j <= y2) { + val pixel = src(i, j) + r += red(pixel) + g += green(pixel) + b += blue(pixel) + a += alpha(pixel) + + j += 1 + } + i += 1 + } - // TODO implement using while loops - ??? + rgba(r / pixelsCount, g / pixelsCount, b / pixelsCount, a / pixelsCount) } val forkJoinPool = new ForkJoinPool