# OPENRNDR & Processing - Slitscanning

**URL:** https://openrndr.discourse.group/t/openrndr-processing-slitscanning/76
**Category:** Tutorials
**Created:** [April 3, 2020, 2:43pm UTC](https://openrndr.discourse.group/t/openrndr-processing-slitscanning/76 "2020-04-03T14:43:13Z")
**Posts on this page:** 1
**Page:** 1

<div class="post-metadata">

### Author: ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)
#### Post date: [April 3, 2020, 2:43pm UTC](https://openrndr.discourse.group/t/openrndr-processing-slitscanning/76/1 "2020-04-03T14:43:13Z")

</div>

# Slitscanning

A program that loads an image and draws a horizontal line of pixels from that image stretched vertically to cover the whole window. The vertical position of the line of pixels - where are we looking at in the source photo - changes over time, slowly going from top to bottom in a loop producing an interesting animated effect.

 ![thumb](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/f3674a5c5a506ada5c3d925630ff43577030b3c4.jpeg)

### Processing / Java

```auto
PImage img;
void setup() {
  size(1280, 640, P2D);
  img = loadImage("/path/to/your/photo.jpg");
  img.loadPixels();
}
void draw() {
  int yy = frameCount % img.height;
  for(int x=0; x<width; x++) {
    int xx = (int)map(x, 0, width, 0, img.width);
    stroke(img.pixels[xx + yy * img.width]);
    line(x, 0, x, height);
  }
}
void keyPressed() {
  if(key == 's') {
    save("thumb.jpg");
  }
}

```

### OPENRNDR / Kotlin (version 1)

```auto
fun main() = application {
    configure {
        width = 1280
        height = 640
    }
    program {
        val img = loadImage("/path/to/your/photo.jpg")
        val shadow = img.shadow
        shadow.download()
        extend(Screenshots())
        extend {
            val yy = frameCount % img.height
            for (x in 0 until width) {
                val xx = map(0.0, width.toDouble(), 0.0, img.width.toDouble(), x.toDouble()).toInt()
                drawer.stroke = shadow[xx, yy]
                drawer.lineSegment(x.toDouble(), 0.0, x.toDouble(), height.toDouble())
            }
        }
    }
}

```

### OPENRNDR / Kotlin (version 2)

```auto
fun main() = application {
    configure {
        width = 1280
        height = 640
    }
    program {
        val img = loadImage("/path/to/your/photo.jpg")
        extend(Screenshots())
        extend {
            drawer.shadeStyle = shadeStyle {
                fragmentTransform = "x_fill = texture(p_img, vec2(c_boundsPosition.x, fract(p_time)));"
                parameter("img", img)
                parameter("time", seconds * 0.05)
            }
            drawer.rectangle(drawer.bounds)
        }
    }
}

```

Differences to note:

| Topic | Processing | OPENRNDR |
| --- | --- | --- |
| accessing pixels on an image | The pixels are part of the image so you first `img.loadPixels()` and then access `img.pixels` | The pixels are downloaded from the `shadow` of the image, then you access them via that `shadow` object |
| iteration | `for(int x=0; x<width; x++)` | `for (x in 0 until width)` |
| mapping | `map(val, min0, max0, min1, max1)` | `map(min0, max0, min1, max1, val)` |
| set line color | `stroke(color)` | `drawer.stroke = color` |
| drawing lines | `line(x0, y0, x1, y1)` | `drawer.lineSegment(x0, y0, x1, y1)` |
| upgrading integers to float or double | automatic. you can use integers where floats are expected | manual, use `myInt.toDouble()` or combine them with a double, for example `myInt * 0.5` |
| saving a screenshot | call `save()` inside `void keyPressed() {}` | `extend(Screenshots())` and press the [space] key in your program |
| draw a rectangle covering the screen | `rect(0, 0, width, height)` | `drawer.rectangle(drawer.bounds)` |

The version 2 above shows that you can [easily inline shaders](https://guide.openrndr.org/advancedDrawing/shadeStyles.html) in the program so you avoid drawing many lines in a for loop. This more advanced option is great for those experienced in GLSL shaders.

Two parameters are passed to the shader: the image and the current time scaled down to slow down the effect. The shader then copies to every pixel on the screen the color of a pixel somewhere above or below, the exact source location defined by the value of `p_time`.

👇 Share your questions and comments below | 🔎 [Find other OPENRNDR & Processing posts](https://openrndr.discourse.group/search?q=Processing%20%23openrndr%3Atutorials)
