Image filter gets stronger every loop - p5.js

I have made my own image filters sepia and blur. When the mouse is clicked on the original (left) image, it is meant to create a radial blur effect on the processed (right) image. However, after testing it I have found that it only works if I have my mouse over the picture as it’s loading. Then, if I click my mouse, the original picture is processed and it looks like the filter gets stronger on the already processed image to the right like it gets another filter applied on top. This continues the more I click. Would anyone have an idea of what I’ve done wrong? I’m not sure where the issue with my code is.

var imgIn;

function preload() {
    imgIn = loadImage("https://media.makeameme.org/created/doesnt-know-why-gxsyb3.jpg");
}
function setup() {
    createCanvas((imgIn.width * 2), imgIn.height);
}
function draw() {
    background(125);
    image(imgIn, 0, 0);
    image(earlyBirdFilter(imgIn), imgIn.width, 0);
    noLoop();
}
function mousePressed(){
  loop();
}
function earlyBirdFilter(img){
  var resultImg = createImage(img.width, img.height);

  resultImg = sepiaFilter(img);
  resultImg = darkCorners(resultImg);
  resultImg = radialBlurFilter(resultImg);
  resultImg = borderFilter(resultImg)

  resultImg.updatePixels();
  return resultImg;
}

function sepiaFilter(input){
  input.loadPixels();

  for (var x = 0 ; x < input.width; x++){
    for (var y = 0 ; y <input.height; y++){
      var index = (y*input.width + x) * 4;

      var oldRed = input.pixels[index+0];
      var oldGreen = input.pixels[index+1];
      var oldBlue = input.pixels[index+2];

      var newRed = (oldRed * .393) + (oldGreen *.769) + (oldBlue * .189)
      var newGreen = (oldRed * .349) + (oldGreen *.686) + (oldBlue * .168)
      var newBlue = (oldRed * .272) + (oldGreen *.534) + (oldBlue * .131)

      input.pixels[index +0] = newRed;
      input.pixels[index +1] = newGreen;
      input.pixels[index +2] = newBlue;
      input.pixels[index +3] = 255;
      
    }
  }
  input.updatePixels();
  return input;
  
}
function radialBlurFilter(input){
  var matrixSize = matrix.length;

  input.loadPixels();

for (var x = 0; x < input.width; x++) {
  for (var y = 0; y < input.height; y++) {

      var index = (x + y * input.width) * 4;
      var c = convolution(x, y, matrix, matrixSize, input);
      var d = dist(mouseX, mouseY, x, y);
      var m = map(d, 100, 300, 0, 1);
      var dynBlur = constrain(m ,0, 1);
      var r = input.pixels[index+0];
      var g = input.pixels[index+1];
      var b = input.pixels[index+2];

      input.pixels[index + 0] = c[0]*dynBlur + r*(1-dynBlur);
      input.pixels[index + 1] = c[1]*dynBlur + g*(1-dynBlur);
      input.pixels[index + 2] = c[2]*dynBlur + b*(1-dynBlur);
      input.pixels[index + 3] = 255;
  }
}
  input.updatePixels();
  return input;
}

I guess you should make a clone of the original image before processing it:

function draw() {
  const imgClone = imgIn.get();

  background(125);
  image(imgClone, 0, 0);
  image(earlyBirdFilter(imgClone), imgClone.width, 0);
}
3 Likes

I’m a little concerned about that many p5.Image cloning at each draw() iteration at 60 FPS. :fearful:

Each time we use createImage(), loadImage() or clone it via its method get(), we also create a heavy <canvas> element:

We could instead have 2 p5.Image variables for the original & its clone, and then just transfer the original’s pixels[] to the clone’s pixels[] by calling method set():

function transferImage(src, tgt) {
  tgt.pixels.set(src.pixels);
  tgt.updatePixels();
  return tgt;
}

This way we avoid creating p5.Image/<canvas> unneeded objects all the time. :bulb:

// https://Discourse.Processing.org/t/
// image-filter-gets-stronger-every-loop-p5-js/35641/4

// (2022-Mar-10)

'use strict';

const
  HTTP = 'https://',
  SITE = 'media.MakeAMeme.org/',
  FOLDER = 'created/',
  FILE = 'doesnt-know-why-gxsyb3',
  EXT = '.jpg',
  FILENAME = HTTP + SITE + FOLDER + FILE + EXT;

var imgIn, imgClone;

function preload() {
  imgIn = loadImage(FILENAME, img => {
    imgClone = img.get();
    img.loadPixels();
    imgClone.loadPixels();
  });
}

function setup() {
  createCanvas(imgIn.width << 1, imgIn.height).mousePressed(redraw);
  noLoop();
}

function draw() {
  background(125);
  image(transferImage(imgIn, imgClone), 0, 0);
  image(earlyBirdFilter(imgClone), imgIn.width, 0);
}

function transferImage(src, tgt) {
  tgt.pixels.set(src.pixels);
  tgt.updatePixels();
  return tgt;
}

function earlyBirdFilter(img) {
  borderFilter(radialBlurFilter(darkCorners(sepiaFilter(img)))).updatePixels();
  return img;
}

function sepiaFilter(img) {
  // blah, blah, blah...
  return img;
}

function darkCorners(img) {
  // blah, blah, blah...
  return img;
}

function radialBlurFilter(img) {
  // blah, blah, blah...
  return img;
}

function borderFilter(img) {
  // blah, blah, blah...
  return img;
}