diff --git a/Lab11.iml b/Lab11.iml
index 4de040d..c703763 100644
--- a/Lab11.iml
+++ b/Lab11.iml
@@ -8,5 +8,8 @@
+
+
+
\ No newline at end of file
diff --git a/libs/bridj-0.7.0.jar b/libs/bridj-0.7.0.jar
new file mode 100644
index 0000000..dd285c7
Binary files /dev/null and b/libs/bridj-0.7.0.jar differ
diff --git a/libs/slf4j-api-1.7.2.jar b/libs/slf4j-api-1.7.2.jar
new file mode 100644
index 0000000..1a88708
Binary files /dev/null and b/libs/slf4j-api-1.7.2.jar differ
diff --git a/libs/webcam-capture-0.3.12.jar b/libs/webcam-capture-0.3.12.jar
new file mode 100644
index 0000000..4442b2e
Binary files /dev/null and b/libs/webcam-capture-0.3.12.jar differ
diff --git a/res/Dead_tree.png b/res/Dead_tree.png
new file mode 100644
index 0000000..08bf780
Binary files /dev/null and b/res/Dead_tree.png differ
diff --git a/res/collins_eileen.png b/res/collins_eileen.png
new file mode 100644
index 0000000..e8be92a
Binary files /dev/null and b/res/collins_eileen.png differ
diff --git a/res/grace_hopper.jpg b/res/grace_hopper.jpg
new file mode 100644
index 0000000..478720d
Binary files /dev/null and b/res/grace_hopper.jpg differ
diff --git a/res/imageProcessing.jpg b/res/imageProcessing.jpg
new file mode 100644
index 0000000..92ae49b
Binary files /dev/null and b/res/imageProcessing.jpg differ
diff --git a/res/imageProcessing_empty.jpg b/res/imageProcessing_empty.jpg
new file mode 100644
index 0000000..c415c7e
Binary files /dev/null and b/res/imageProcessing_empty.jpg differ
diff --git a/res/mask.png b/res/mask.png
new file mode 100644
index 0000000..b557939
Binary files /dev/null and b/res/mask.png differ
diff --git a/res/mask640x480.png b/res/mask640x480.png
new file mode 100644
index 0000000..ebe9452
Binary files /dev/null and b/res/mask640x480.png differ
diff --git a/res/moire1.png b/res/moire1.png
new file mode 100644
index 0000000..fa73e3d
Binary files /dev/null and b/res/moire1.png differ
diff --git a/res/moire2.jpg b/res/moire2.jpg
new file mode 100644
index 0000000..b0d296a
Binary files /dev/null and b/res/moire2.jpg differ
diff --git a/res/rice.jpg b/res/rice.jpg
new file mode 100644
index 0000000..c778fe1
Binary files /dev/null and b/res/rice.jpg differ
diff --git a/src/imagefilters/ImageFilters.scala b/src/imagefilters/ImageFilters.scala
new file mode 100644
index 0000000..a412260
--- /dev/null
+++ b/src/imagefilters/ImageFilters.scala
@@ -0,0 +1,13 @@
+package imagefilters
+
+/**
+ * This class implements the various image filters
+ */
+object ImageFilters {
+
+ def duplicate(a: Array[Array[Int]]): Array[Array[Int]] = {
+
+ /* TODO: Write your code hereunder */
+ return Array.empty
+ }
+}
diff --git a/src/imagefilters/ImageProcessingApp.scala b/src/imagefilters/ImageProcessingApp.scala
new file mode 100644
index 0000000..3fcbaa0
--- /dev/null
+++ b/src/imagefilters/ImageProcessingApp.scala
@@ -0,0 +1,14 @@
+package imagefilters
+
+import isc.graphics.ImageGraphics
+
+object ImageProcessingApp extends App {
+
+ val imageFile = "./res/collins_eileen.png"
+ val org = new ImageGraphics(imageFile, "Original", -500, -250)
+ val dest = new ImageGraphics(imageFile, "Duplicate", 0, -250)
+
+ // Simple copy and display
+ val newPixels = ImageFilters.duplicate(org.getPixelsBW())
+ dest.setPixelsBW(newPixels)
+}
diff --git a/src/isc/graphics/ImageGraphics.scala b/src/isc/graphics/ImageGraphics.scala
new file mode 100644
index 0000000..9d98552
--- /dev/null
+++ b/src/isc/graphics/ImageGraphics.scala
@@ -0,0 +1,241 @@
+package isc.graphics
+
+import java.awt._
+import java.awt.image.BufferedImage
+import java.io.{File, FileInputStream}
+import javax.imageio.ImageIO
+import javax.swing.{JFrame, JPanel}
+
+/**
+ * [ImageGraphics] helpers functions in companion object.
+ */
+object ImageGraphics {
+ /**
+ * Converts a color array to a black-or-white array
+ *
+ * @param c The color array
+ * @return The array converted to BW
+ */
+ def convertToGray(c: Array[Array[Color]]): Array[Array[Color]] = {
+ val w = c.length
+ val h = c(0).length
+ val values = Array.ofDim[Color](w, h)
+
+ // FIXME this is slow
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ val col = c(i)(j)
+ val intColor = (0.3 * col.getRed + 0.59 * col.getGreen + 0.11 * col.getBlue).toInt
+ values(i)(j) = new Color(intColor, intColor, intColor)
+ }
+ }
+ values
+ }
+
+ def convertToGrayInt(c: Array[Array[Color]]): Array[Array[Int]] = {
+ val w = c.length
+ val h = c(0).length
+ val values = Array.ofDim[Int](w, h)
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ val col = c(i)(j)
+ val intColor = (0.3 * col.getRed + 0.59 * col.getGreen + 0.11 * col.getBlue).toInt
+ values(i)(j) = intColor
+ }
+ }
+ values
+ }
+
+ def main(args: Array[String]): Unit = {
+ val imageUsed = "res/grace_hopper.jpg"
+ val org = new ImageGraphics(imageUsed, "Original", 0, 0)
+ }
+}
+
+/**
+ * This class was made to deal with images as multidimensional arrays.
+ * Mainly used in the ImageProcessing
lab. It expects the images to reside in the src
directory
+ *
+ * @author Pierre-André Mudry
+ * @version 1.0
+ * @constructor
+ *
+ * @param filePath the path of the file, relative to the project. For instance, "./res/grace_hopper.jpg"
+ * @param windowTitle the title
+ * @param xPositionOffset the x offset
+ * @param yPositionOffset the y offet
+ */
+class ImageGraphics(val filePath: String, val windowTitle: String,
+ val xPositionOffset: Int, val yPositionOffset: Int) extends JFrame {
+
+ private var imgBuffer: BufferedImage = null
+ private var w = 0
+ private var h = 0
+
+ class ImgPanel extends JPanel {
+ override def paint(g: Graphics): Unit = {
+ super.paint(g)
+ g.drawImage(imgBuffer, 0, 0, null)
+ g.dispose()
+ }
+ }
+
+ val imgPanel = new ImgPanel()
+
+ try { // Fill the frame content with the image
+ try {
+ imgBuffer = ImageIO.read(new FileInputStream(new File(filePath)))
+ w = imgBuffer.getWidth
+ h = imgBuffer.getHeight
+ } catch {
+ case e: Exception =>
+ println("Could not load directly, using classpath.")
+ }
+
+ // If the first technique failed, try using resource instead
+ if (imgBuffer == null) {
+ try {
+ imgBuffer = ImageIO.read(classOf[ImageGraphics].getResource(filePath))
+ w = imgBuffer.getWidth
+ h = imgBuffer.getHeight
+ } catch {
+ case e: Exception =>
+ System.err.println("Could not find image " + filePath + ", exiting !")
+ e.printStackTrace()
+ System.exit(-1)
+ }
+ }
+
+ this.setResizable(false)
+ this.setTitle(windowTitle)
+ this.setLayout(new BorderLayout())
+ this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
+
+ imgPanel.setPreferredSize(new Dimension(imgBuffer.getWidth, imgBuffer.getHeight))
+ this.add(imgPanel, BorderLayout.CENTER)
+ this.pack()
+
+ // Get the size of the screen
+ val dim = Toolkit.getDefaultToolkit.getScreenSize
+
+ // Determine the new location of the window
+ val lw = this.getSize.width
+ val lh = this.getSize.height
+ val x = (dim.width - lw) / 2 + xPositionOffset
+ val y = (dim.height - lh) / 2 + yPositionOffset
+
+ // Move the window
+ this.setLocation(x, y)
+ this.setVisible(true)
+ } catch {
+ case e: Exception =>
+ e.printStackTrace()
+ }
+
+ /**
+ * Sets a grayscale pixel, does not sets values for invalid pixels
+ * outside the screen. Does not repaint the screen either because it
+ * is slow.
+ *
+ * @param x
+ * @param y
+ * @param intensity
+ */
+ def setPixelBW(x: Int, y: Int, intensity: Int): Unit = {
+ if (!((x < 0) || (y < 0) || (x >= w) || (y >= h)))
+ imgBuffer.setRGB(x, y, intensity << 16 | intensity << 8 | intensity)
+ }
+
+ /**
+ * Sets an array of grayscale pixels (from 0 to 255) and displays them
+ *
+ * @param pixels
+ */
+ def setPixelsBW(pixels: Array[Array[Int]]): Unit = {
+ try {
+ if (pixels(0).length != h || pixels.length != w) throw new Exception("Invalid size of the pixel array !")
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ val c = pixels(i)(j) << 16 | pixels(i)(j) << 8 | pixels(i)(j)
+ imgBuffer.setRGB(i, j, c)
+ }
+ }
+ this.repaint()
+ } catch {
+ case e: Exception =>
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * Sets an array of pixels of Color and displays them
+ *
+ * @param pixels
+ */
+ def setPixelsColor(pixels: Array[Array[Color]]): Unit = {
+ try {
+ if (pixels(0).length != h || pixels.length != w) throw new Exception("Invalid size of the pixel array !")
+
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ imgBuffer.setRGB(i, j, pixels(i)(j).getRGB)
+ }
+ }
+ this.repaint()
+ } catch {
+ case e: Exception =>
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * Gets a single pixel from the background image and returns its
+ * grayscale value
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return the pixel
+ */
+ def getPixelBW(x: Int, y: Int): Int =
+ if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) {
+ 0
+ }
+ else {
+ // Inside the image. Make the gray conversion and return the value
+ val c = new Color(imgBuffer.getRGB(x, y))
+ (0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
+ }
+
+ /**
+ * Gets the array of the pixels (which have been converted to grayscale
+ * if required)
+ *
+ * @return The arrays of gray pixels
+ */
+ def getPixelsBW(): Array[Array[Int]] = {
+ val values = Array.ofDim[Int](w, h)
+
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ val c = new Color(imgBuffer.getRGB(i, j))
+ values(i)(j) = (0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
+ }
+ }
+ values
+ }
+
+ /**
+ * Gets the array of the pixels as Colors (see #Color)
+ *
+ * @return The arrays of pixels
+ */
+ def getPixelsColor(): Array[Array[Color]] = {
+ val values = Array.ofDim[Color](w, h)
+ for (i <- 0 until w) {
+ for (j <- 0 until h) {
+ values(i)(j) = new Color(imgBuffer.getRGB(i, j))
+ }
+ }
+ values
+ }
+}
diff --git a/src/livefilter/LiveFilter.scala b/src/livefilter/LiveFilter.scala
new file mode 100644
index 0000000..d1ba393
--- /dev/null
+++ b/src/livefilter/LiveFilter.scala
@@ -0,0 +1,95 @@
+package livefilter
+
+import com.github.sarxos.webcam.WebcamPanel.DrawMode
+import com.github.sarxos.webcam.{Webcam, WebcamImageTransformer, WebcamPanel, WebcamResolution}
+
+import java.awt.image.BufferedImage
+import java.awt.{Color, Dimension}
+import java.io.{File, FileInputStream}
+import javax.imageio.ImageIO
+import javax.swing.JFrame
+
+object LiveFilter {
+ def main(args: Array[String]): Unit = {
+ new LiveFilter()
+ }
+}
+
+/**
+ * A live filter class using VGA resolution
+ */
+class LiveFilter extends WebcamImageTransformer {
+ val size: Dimension = WebcamResolution.VGA.getSize
+
+ val MASK: String = "./res/mask640x480.png"
+ val videoMask: Array[Array[Int]] = toBW(ImageIO.read(new FileInputStream(new File(MASK))))
+
+ // Gets default webcam and sets image transformer to this (transformer will modify
+ // image after it's been received from webcam, in this case it will rotate it)
+ val webcam: Webcam = Webcam.getDefault
+
+ //val webcam: Webcam = Webcam.getWebcamByName("/dev/video2")
+
+ webcam.setViewSize(size)
+ println(size)
+ webcam.setImageTransformer(this)
+ webcam.open
+
+ // Create a window
+ val window = new JFrame("Test filter")
+
+ // Creates a panel to put the webcam image in it
+ val panel = new WebcamPanel(webcam)
+ panel.setFPSDisplayed(true)
+ panel.setDrawMode(DrawMode.FIT)
+
+ // Add panel to window
+ window.add(panel)
+ window.pack()
+ window.setVisible(true)
+
+ window.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE)
+
+ def toBW(img: BufferedImage): Array[Array[Int]] = {
+ val o = Array.ofDim[Int](img.getWidth(), img.getHeight())
+ for (x <- o.indices) {
+ for (y <- o(0).indices) {
+ val c = new Color(img.getRGB(x, y))
+ o(x)(y) = (0.3 * c.getRed + 0.59 * c.getGreen + 0.11 * c.getBlue).toInt
+ }
+ }
+ o
+ }
+
+ def toArray(image: BufferedImage): Array[Array[Color]] = {
+ val out = Array.ofDim[Color](image.getWidth, image.getHeight)
+
+ for (x <- out.indices; y <- out(0).indices) {
+ out(x)(y) = new Color(image.getRGB(x, y))
+ }
+
+ out
+ }
+
+ private def updateImage(in: Array[Array[Color]], out: BufferedImage): Unit = {
+ for (x <- in.indices; y <- in(0).indices) {
+ out.setRGB(x, y, in(x)(y).getRGB)
+ }
+ }
+
+ /**
+ * Applies the various filters to the buffer
+ *
+ * @param image The input image
+ * @return The filtered image
+ */
+ override def transform(image: BufferedImage): BufferedImage = {
+ val img: Array[Array[Color]] = toArray(image)
+
+ // TODO Complete here by changing the assignment with your filters
+ val filtered: Array[Array[Color]] = img
+
+ updateImage(filtered, image)
+ return image
+ }
+}
\ No newline at end of file