-2

Ich habe mich gefragt, wie man die folgende Bildskalierung in Java oder Processing effizient implementiert. Beim Skalieren werden die Grenzen des Bilds um die Bildschirmränder gelegt. Ich möchte dies zur Laufzeit in meinem Pixel() -Array in Processing anwenden. (um diese Verarbeitung agnostisch zu halten - Pixel() ist nichts anderes als eine Methode, die alle Pixel auf meinem aktuellen Bildschirm in einem Array zurückgibt).Java/Processing - Bildmatrix mit Umrandungen skalieren

(Beachten Sie, dass dieses Beispiel in MaxMsp/Jitter mit dem Modul jit.rota erstellt wurde, das eine sehr effiziente Implementierung zu verwenden scheint).

unscaled

zoomed out

Kann mir jemand helfen, wie, um loszulegen? Ich gehe davon aus, dass es eine Kombination aus Herunterskalieren des Bildes und Erstellen von Zusatzkopien sein muss - aber das klingt für mich nicht sehr effizient. Das obige Beispiel funktioniert perfekt bei Videos mit den extremsten Einstellungen.

+0

haben Sie alles versucht ?? und vergiss das sehr efficient das ist nicht deine Fabrik – gpasch

Antwort

1

Eine Option, die ich für schnell halten kann, ist ein einfacher Fragment-Shader.

Zum Glück haben Sie ein Beispiel ziemlich nahe kommen, was Sie brauchen, dass Schiffe mit Verarbeitung über Datei> Beispiele> Themen> Shaders> Infinite Fliesen

ich nicht in der Lage sein, effizient einen guten Start zu schaffen, zu beenden, aber gibt es eine erschöpfende PShader tutorial on the Processing website, wenn Sie das von Grund auf neu beginnen.

Ein wirklich grober Kern von dem, was Sie brauchen:

  • Shadern Programme, die wirklich schnell laufen und auf dem GPU parallelisiert, aufgeteilt in zwei: Vertex-Shader (Deal mit 3D-Geometrie in erster Linie), Fragment-Shader (Deal mit "Fragmenten" (was wird auf dem Bildschirm Pixel werden) hauptsächlich). Sie werden mit einem Fragment Shader spielen wollen
  • Die Sprache heißt GLSL und ist ein bisschen anders (weniger Typen, strengere, einfachere Syntax), aber nicht völlig fremd (ähnlich C-Typ deklarieren Variablen, Funktionen, Bedingungen, Schleifen usw.)
  • , wenn Sie eine Variable von einem GLSL Programm zugänglich in Verarbeitung machen wollen, dass es mit dem Schlüsselwort uniform
  • Verwendung Präfix textureWrap(REPEAT) Kanten einzuwickeln
  • das Bild zu skalieren und wickeln Sie brauchen um die Koordinaten der Texturabtastung zu skalieren:

Hier ist, was die InfiniteTiles scroller Shader wie folgt aussieht:

//--------------------------------------------------------- 
// 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); 
} 

Sie diese ein wenig vereinfachen können, wie Sie zu Scrollen nicht brauchen.Zusätzlich statt Subtrahieren und Multiplizieren (- TILES_COUNT_X * pos), können Sie einfach mehrfach:

//--------------------------------------------------------- 
// 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); 
} 

Hinweis ich die time Variable umgewidmet habe scale werden, damit die Verarbeitung Code dieses einheitliche Variable zugreift, muss auch ändern:

//------------------------------------------------------------- 
// 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); 
} 

Bewegen Sie die Maus Skala zu ändern: fragment shader scaling normal scale

fragment shader scaling small scale

aktualisieren Sie mit einem sehr ähnlichen Shader spielen können here:

0

ich effektiv mit einer Lösung gekommen - aber wird George Methode als nächstes als die Geschwindigkeitsdifferenz implementieren Shadern mit scheint es wert zu sein!

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();  
} 
Verwandte Themen