Interpolation mode for image resizing

Hello, I am trying to recreate the translucent, blurred menus on MacOS. To optimize the blur, I resize the image to be blurred, blur it, and scale it up again after the blur. The problem is, that the downsizing of the image seems to be using neighbour interpolation, which results in a visible flickering of the blur when things move. I need something like bilinear interpolation.

Here you can see, that the angled edges are not anti-aliased: Screen Shot 2018-03-10 at 15.24.41

Is there a way to change the interpolation of the image resizing, or just some other way to get around it?

Answers

  • @BjarkePedersen --

    Not about interpolation, but you might be interested in this previous conversation:

  • edited March 2018 Answer ✓

    Thanks for the answer! I fixed the problem!

    I tried playing with the different glsl blur shaders, but concluded that it's not possible to only apply the shader to a single PImage. So I ditched the shaders.

    I fixed the image resizing interpolation though. The problem was that I was resizing images by displaying them inside a PGraphic at the low resolution. Example:

    pg.beginDraw();
    pg.image(img,0,0 low_width, low_height);
    pg.endDraw();
    

    What I needed to do was simply use the resize() function, which yielded nicely interpolated downscaling. Example:

    img.resize(low_width, low_height)

    Here you can see the result:

    Screen Shot 2018-03-11 at 12.44.41

    And here's the final blurred result: Screen Shot 2018-03-11 at 12.56.12

    Code for anyone interested:

    int scale = 5;  // Downsize factor for faster blurring (Higher = faster, lower quality)
    int blurSize = 25;  // Blur size
    int style = 1; // UI style. 1 = frosted glass  2 = macOS window 
    int w, h;
    
    PImage img;
    PGraphics pg, fullRes;
    
    void setup() {
      size(800, 800, P2D);
      pixelDensity(displayDensity());
      noFill();
      stroke(230);
    
      scale *= displayDensity();
      blurSize *= displayDensity();
      blurSize /= scale;
      w = width / scale;
      h = height / scale;
    
      pg = createGraphics(width, height);
    }
    
    float i = 0;
    
    void drawMain() {
      pg.beginDraw();
      pg.background(25);
    
      pg.noStroke();
      pg.fill(255, 100, 100);
      pg.rotate(sin(i/20)/10);
      pg.rect(100, 200, 300, 70, 25, 25, 25, 25);
      pg.rotate(-sin(i/20)/10);
    
      pg.fill(100, 200, 0);
      pg.ellipse(250, 600, 120, 200);
    
      pg.fill(255);
      pg.ellipse(600, 200, 600, 600);
    
      pg.rect(600, 200, 600, 600);
    
      pg.fill(0, 100, 255);
      pg.ellipse(sin(i/20)*20 + 600, 200, 200, 100);
    
      pg.endDraw();
    }
    
    void blurRegion(int x, int y, int wi, int hi) {
      int s = displayDensity(); 
      PImage blurImg = pg.get(x * s, y * s, wi * s, hi * s);
      PGraphics blurGraphics = createGraphics(wi / scale, hi / scale);
      wi /= scale;
      hi /= scale;
      // Downsize and blur the region
      blurImg.resize(wi, hi);
      blurImg.filter(BLUR, blurSize);
    
      // Color correct the blurred region
      for (int i=0; i<blurImg.pixels.length; i++) {
        color col = blurImg.pixels[i];
        if (style == 1) col = lerpColor(col, color(230, 230, 230), 0.3);
        if (style == 2) col = lerpColor(col, color(240, 240, 240), 0.8);
        blurImg.pixels[i] = col;
      }
      blurImg.updatePixels();
    
      wi *= scale;
      hi *= scale;
      image(blurImg, x, y, wi, hi);
    }
    
    void draw() {
      i++;
      drawMain();
      image(pg, 0, 0);
    
      blurRegion(mouseX, mouseY, 400, 200);
      rect(mouseX, mouseY, 400, 200);
    
      println(frameRate);
    }
    
  • Thxs for sharing.

    Kf

Sign In or Register to comment.