-2

我一直想知道如何在 Java 或 Processing 中有效地实现以下图像缩放过程。向外扩展时,图像的边界环绕屏幕边缘。我想在运行时将其应用于处理中的 Pixels() 数组。(为了保持这个处理不可知 - Pixels() 只不过是一种在数组中返回我当前屏幕上的所有像素的方法)。

(请注意,此示例是在 MaxMsp/Jitter 中使用 jit.rota 模块制作的,它似乎使用了非常有效的实现)。

未缩放

缩小

任何人都可以帮助我了解如何开始吗?我认为它必须是缩小图像和创建它的相邻副本的组合 - 但这对我来说听起来不是很有效。上面的示例在具有最极端设置的视频上也能完美运行。

4

2 回答 2

1

我认为会很快的一种选择是使用基本的片段着色器。

幸运的是,你有一个非常接近你需要的例子,通过File > Examples > Topics > Shaders > Infinite Tiles处理

我将无法有效地提供一个体面的从头到尾的指南,但如果您从头开始,Processing 网站上有一个详尽的 PShader 教程。

您需要的一个非常粗略的要点:

  • 着色器是在 GPU 上运行得非常快且并行化的程序,分为两个:顶点着色器(主要处理 3d 几何图形)、片段着色器(主要处理“片段”(即将成为屏幕上的像素))。你会想玩一个片段着色器
  • 该语言称为 GLSL,有点不同(类型更少,更严格,语法更简单),但并非完全陌生(类似 C 类型的声明变量、函数、条件、循环等)
  • 如果您想在处理中使 GLSL 程序中的变量可访问,请在其前面加上关键字uniform
  • 使用textureWrap(REPEAT)包裹边缘
  • 要缩放图像并包装它,您需要缩放纹理采样坐标:

InfiniteTiles 滚动着色器如下所示:

//---------------------------------------------------------
// Display endless moving background using a tile texture.
// Contributed by martiSteiger
//---------------------------------------------------------

uniform float time;
uniform vec2 resolution;
uniform sampler2D tileImage;

#define TILES_COUNT_X 4.0

void main() {
  vec2 pos = gl_FragCoord.xy - vec2(4.0 * time);
  vec2 p = (resolution - TILES_COUNT_X * pos) / resolution.x;
  vec3 col = texture2D (tileImage, p).xyz;
  gl_FragColor = vec4 (col, 1.0);
}

您可以稍微简化一下,因为您不需要滚动。此外,您可以简单地相乘,而不是减法和乘法(- TILES_COUNT_X * pos):

//---------------------------------------------------------
// Display endless moving background using a tile texture.
// Contributed by martiSteiger
//---------------------------------------------------------

uniform float scale;
uniform vec2 resolution;
uniform sampler2D tileImage;

void main() {
  vec2 pos = gl_FragCoord.xy * vec2(scale);
  vec2 p = (resolution - pos) / resolution.x;
  vec3 col = texture2D (tileImage, p).xyz;
  gl_FragColor = vec4 (col, 1.0);
}

请注意,我已将time变量重新用于成为scale,因此访问此统一变量的处理代码也必须更改:

//-------------------------------------------------------------
// Display endless moving background using a tile texture.
// Contributed by martiSteiger
//-------------------------------------------------------------

PImage tileTexture;
PShader tileShader;

void setup() {
  size(640, 480, P2D);
  textureWrap(REPEAT);
  tileTexture = loadImage("penrose.jpg");
  loadTileShader();
}

void loadTileShader() {  
  tileShader = loadShader("scroller.glsl");
  tileShader.set("resolution", float(width), float(height));  
  tileShader.set("tileImage", tileTexture);
}

void draw() {
  tileShader.set("scale", map(mouseX,0,width,-3.0,3.0));
  shader(tileShader);
  rect(0, 0, width, height);
}

移动鼠标改变比例: 片段着色器缩放正常缩放

片段着色器缩放小比例

更新您可以在这里使用非常相似的着色器:

于 2016-11-21T10:40:06.760 回答
0

我确实想出了一个解决方案——但接下来将实施 George 的方法,因为使用着色器的速度差异似乎是值得的!

public void scalePixels(double wRatio,double hRatio, PGraphics viewPort) {
    viewPort.loadPixels();
    int[] PixelsArrayNew = viewPort.pixels.clone();
    double x_ratio = wRatio ;
    double y_ratio = hRatio ;
    double px, py ;
    for (int i=0;i<viewPort.height;i++) {
        for (int j=0;j<viewPort.width;j++) {
            px = Math.floor(j%(wRatio*viewPort.width)/x_ratio) ;
            py = Math.floor(i%(hRatio*viewPort.height)/y_ratio) ;
            viewPort.pixels[(int)(i*viewPort.width)+j] = PixelsArrayNew[(int)((py*viewPort.width)+px)] ;
        }
    }
    viewPort.updatePixels();    
}
于 2016-11-26T14:41:25.190 回答