How to pixelate image according to mouseX

Hi everyone,

I'm trying to pixelate an image, so that when the mouseX moves from 0 towards right, the image gets more and more pixelated. I've tried to do this using the map() function and I don't understand what's wrong with my code. At the moment it only shows a grey window. Also, would it be possible to get the pixel effect on the whole sketch (with multiple videos, images etc.), not just one image? Here's my code, would be really grateful for your help!

// Image variable
PImage img;

void setup() {
  size(500, 500);
  // Load the file from the data folder
  img = loadImage("sunflower.jpg");
}

void draw() {


  // Call loadPixels before we deal with pixels
  loadPixels();  

 float a = map(mouseX,0,width,0,10);

  // Loop through all pixels, skip every 10 pixels along the y-axis
  for (int y = 0; y < img.height; y+=a) {
    // skip every 5 pixels along the x-axis
    for (int x = 0; x < img.width; x+=a) {
      // Calculate the 1D location from a 2D grid
      int loc = x + y*img.width;

      // Color according to the image
     noStroke();
      fill(img.pixels[loc]);
      rect(x,y, 10,10);

    }
  }

}
Tagged:

Answers

  • edited March 2017

    big error in line 14

    img. ....

  • Yes, you can get it for videos as well. In regards to your previous code, you need to call image(img,0,0); and since you are modifying your pixel array, you need to call img.updatePixels(); after you are done modifying your pixels.

    Lastly, line 26 in this case is preferred to be called in setup.

    Kf

  • (And noStroke() can be put in setup instead of inside the nested loop in draw)

  • Thank you for your help! I tried again with your suggestions, but I still get a grey image. The problem seems to be with the "a" variable as my original code does work when I replace the variable with an integer. However it does not work with line 16 (float a=...) and variable "a" embedded in code (lines 19 & 21). Any ideas on this?

  • edited March 2017

    Line 16 should be float a = map(mouseX,0,width,1,10); avoid having 0 as you can end up in infinite loops.

    Also line 28 should be rect(x,y,a,a); and to make things better in this case, call rectMode(CENTER) in your setup() function.

    Please also show your latest code reflecting the implemented suggested changes from previous posts.

    Kf

  • edited April 2017

    This sounds like it could be done in a shader.

    PShader pixelate;
    PImage img;
    void setup() {
      size(500, 500, P3D);
      img = loadImage("sunflower.jpg");
      pixelate = loadShader("pixelate.frag");
      pixelate.set("u_resolution", float(width), float(height));
      pixelate.set("u_tex", img);
    }
    
    void draw() {
      if (mouseX!=pmouseX) {
        update();
      }
    }
    void update() {
      pixelate.set("u_LEVEL", floor(map(mouseX, 0, width, 0, 128)));
      shader(pixelate);
      rect(0, 0, width, height);
    }
    

    pixelate.frag needs to be in data folder

    #ifdef GL_ES
    precision mediump float;
    #endif
    uniform vec2 u_resolution;
    uniform int u_LEVEL;
    uniform sampler2D u_tex;
    ivec2 pix;
    void main () {
    pix.xy = ivec2(gl_FragCoord.xy);
    pix.y=int(u_resolution.y)-pix.y;
    pix+=(u_LEVEL/2-(pix%u_LEVEL));
    gl_FragColor = texelFetch(u_tex,pix,0);
    }
    

    Also, would it be possible to get the pixel effect on the whole sketch (with multiple videos, images etc.)

    Possibly using filter() but I couldn't get it to work ,
    EDIT: got it working now

  • @prince_polka

    Really cool. BTW, you missed a final curly bracket in your frag code.

    Kf

  • edited April 2017

    [deleted] nothing important, see post below

  • @hello_processing

    I made an example with just an ellipse following the mouse and getting pixlier closer to the right edge of screen. Will probably work with images, text and video as well, haven't tested though.

    @cansik

    I'we just "figured out" how to use filter ;)

    It seems filter works opposite of shader() in three ways.

    It seems if you set() a Pimage as a sampler you shouldn't call it texture, should flip it upside down, and call shader() before you draw.

    And with filter() it's the opposite, you should call the sampler texture, shouldn't flip the screen, and call filter() after you'we drawn.

    This pixelate effect isn't super fancy but maybe something to consider adding to your PostFX library, if you're still working on it.

    **Sketch **

    PShader pixelate;
    
    void setup()
    {
      fullScreen(P2D);
      frameRate(60);
      pixelate = loadShader("pixelate.glsl");
      pixelate.set("u_resolution", width+0.,height+0.);
      fill(255);
    }
    
    void draw()
    {
      background(0);
      ellipse(mouseX,mouseY,300,300);
      pixelate.set("u_LEVEL", int(min(max(0,map(mouseX,0,width,0,64)),64)) ); 
      filter(pixelate);
    }
    

    pixelate.glsl

    #ifdef GL_ES
    precision mediump float;
    #endif
    uniform vec2 u_resolution;
    uniform int u_LEVEL;
    uniform sampler2D texture;
    ivec2 pix;
    
    
    // 4 sampe interpolation
    vec4 tl,tr,bl,br;
    int margin;
    ivec2 corner(int x,int y) {
    return  ivec2(min(max(ivec2(0,0),pix.xy+ivec2(margin*x,margin*y)),u_resolution.xy-1));
    }
    void main () {
    pix.xy = ivec2(gl_FragCoord.xy);
    pix+=(u_LEVEL/2-(pix%u_LEVEL));
    margin=u_LEVEL/4;
    
    tl = texelFetch(texture,corner(1,1),0);
    tr = texelFetch(texture,corner(3,1),0);
    bl = texelFetch(texture,corner(1,3),0);
    br = texelFetch(texture,corner(3,3),0);
    
    gl_FragColor = (tl+tr+bl+br)*0.25;
    }
    
  • edited April 2017

    with filter() it's the opposite, you should call the sampler texture, shouldn't flip the screen, and call filter() after you've drawn.

    Here is a concise explanation of this contrast:

    1. filter() is a post-processing method, like blend() -- it acts on Processing's built-in pixels[] array. Filter after data is added to the pixels array (e.g. after calling image). Everything uses the normal Processing coordinate system (0,0 in the upper left).

    2. shader() is a configuration method, like tint() -- it changes Processing's rendering pipeline. Shade before you draw, changing how subsequent drawing operations will affect the canvas. Shaders are written in OpenGL Shader Language (GLSL), which uses the OpenGL coordinate system (0,0 in the lower left) -- hence the need to vertically "flip" coordinates when interacting with GLSL.

  • @jeremydouglass That explains the performance increase when using filter(). However, to clarify, both methods (technically, only in P2D/P3D) make use of the GPU.

  • Thank you so much for your help everyone!

  • @prince_polka I tried to add your shader to my library, but I can not compile the shader. You are using glsl commands which are not support by MacOS at the moment (only GLSL 120 is supported I think).

    ERROR: 0:24: '%' does not operate on 'ivec2' and 'int' ERROR: 0:27: Invalid call of undeclared identifier 'texelFetch' ERROR: 0:28: Invalid call of undeclared identifier 'texelFetch' ERROR: 0:29: Invalid call of undeclared identifier 'texelFetch' ERROR: 0:30: Invalid call of undeclared identifier 'texelFetch'

    I'm going to try to rewrite the shader to work everywhere :)

  • Added a new imod function and implemented my own texelFetch method, but it is not working as expected. There is no pixelate effect on the image.

    ivec2 imod(ivec2 vec, int modulus)
    {
        return ivec2(mod(vec.x, modulus), mod(vec.y, modulus));
    }
    
    vec4 texelFetch(sampler2D tex, vec2 size, ivec2 coord)
    {
        return texture2D(tex, vec2(float(coord.x) / size.x,
                                   float(coord.y) / size.y));
    }
    

    Full code here: old shader/pixelateFrag.glsl

    So I've implemented it with a simpler version, but I don't know if it has the same result as your code. My code can be found here:

    new shader/pixelateFrag.glsl

  • edited May 2017

    @cansik
    I don't use mac and didn-t know you couldnt use % or texelFetch,
    With your code I get dots and line artifacts

Sign In or Register to comment.