Ich habe in meinem letzten Projekt, bei dem eine Welle/Welligkeit über ein Bild erzeugt wurde, eine Wand getroffen. Ich habe eine gemacht, die mit Grundfarben auf einem Gitter funktioniert, das perfekt funktioniert; Verdammt, ich fügte den Farben je nach Höhe der Welle sogar Schatten hinzu.Wellenerzeugung mit dem "Hugo Elias" Algorithmus bitte! Java
Mein Hauptziel war jedoch, diesen Effekt über ein Bild wie Sie here sehen. Ich folgte einem Algorithmus, den die Leute die Hugo-Elias-Methode nennen (obwohl IDK, wenn er wirklich mit dem Design kam). Sein Tutorial finden Sie here!
Als ich diesem Tutorial folgte, fand ich seinen Pseudocode herausfordernd zu folgen. Ich meine, das Konzept macht größtenteils Sinn, bis ich den Höhenkartenabschnitt über einem Bild getroffen habe. Das Problem, dass die x- und y-Offsets eine ArrayIndexOutOfBoundsException auslösen, liegt daran, dass er den Offset zu dem entsprechenden x oder y addiert. Wenn die Welle zu groß ist (d. H. In meinem Fall 512), wird ein Fehler ausgegeben; Wenn es jedoch zu klein ist, können Sie es nicht sehen.
Irgendwelche Ideen oder Korrekturen zu meiner versuchten Implementierung seines Algorithmus würden meinen Tag machen. Vielen Dank!
So kann ich nicht wirklich eine compile-fähige Version machen, die klein ist und das Problem zeigt, aber ich werde die drei Methoden geben, die ich im Algorithmus verwende. Beachten Sie auch, dass buffer1 und buffer2 die Höhenkarten für die Welle (current und previous) sind und imgArray eine gepufferteImage ist, die durch eine int [img.getWidth() * img.getHeight()] voller ARGB-Werte dargestellt wird.
hier Anyways Sie gehen:
public class WaveRippleAlgorithmOnImage extends JPanel implements Runnable, MouseListener, MouseMotionListener
{
private int[] buffer1;
private int[] buffer2;
private int[] imgArray;
private int[] movedImgArray;
private static double dampening = 0.96;
private BufferedImage img;
public WaveRippleAlgorithmOnImage(BufferedImage img)
{
this.img = img;
imgArray = new int[img.getHeight()*img.getWidth()];
movedImgArray = new int[img.getHeight()*img.getWidth()];
imgArray = img.getRGB(0, 0,
img.getWidth(), img.getHeight(),
null, 0, img.getWidth());
//OLD CODE
/*for(int y = 0; y < img.getHeight(); y++)
{
for(int x = 0; x < img.getWidth(); x++)
{
imgArray[y][x] = temp[0 + (y-0)*img.getWidth() + (x-0)];
}
}*/
buffer1 = new int[img.getHeight()*img.getWidth()];
buffer2 = new int[img.getHeight()*img.getWidth()];
buffer1[buffer1.length/2] = (img.getWidth() <= img.getHeight() ? img.getWidth()/3 : img.getHeight()/3);
//buffer1[25][25] = 10;
back = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_ARGB);
this.addMouseListener(this);
this.addMouseMotionListener(this);
}
//<editor-fold defaultstate="collapsed" desc="Used Methods">
@Override
public void run()
{
while(true)
{
this.update();
this.repaint();
this.swap();
}
}
//Called from Thread to update movedImgArray prior to being drawn.
private void update()
{
//This is my attempt of trying to convert his code to java.
for (int i=img.getWidth(); i < imgArray.length - 1; i++)
{
if(i % img.getWidth() == 0 || i >= imgArray.length - img.getWidth())
continue;
buffer2[i] = (
((buffer1[i-1]+
buffer1[i+1]+
buffer1[i-img.getWidth()]+
buffer1[i+img.getWidth()]) >> 1)) - buffer2[i];
buffer2[i] -= (buffer2[i] >> 5);
}
//Still my version of his code, because of the int[] instead of int[][].
for (int y = 1; y < img.getHeight() - 2; y++)
{
for(int x = 1; x < img.getWidth() - 2; x++)
{
int xOffset = buffer1[((y)*img.getWidth()) + (x-1)] - buffer1[((y)*img.getWidth()) + (x+1)];
int yOffset = buffer1[((y-1)*img.getWidth()) + (x)] - buffer1[((y+1)*img.getWidth()) + (x)];
int shading = xOffset;
//Here is where the error occurs (after a click or wave started), because yOffset becomes -512; which in turn gets
//multiplied by y... Not good... -_-
movedImgArray[(y*img.getWidth()) + x] = imgArray[((y+yOffset)*img.getWidth()) + (x+xOffset)] + shading;
}
}
//This is my OLD code that kidna worked...
//I threw in here to show you how I was doing it before I switched to images.
/*
for(int y = 1; y < img.getHeight() - 1; y++)
{
for(int x = 1; x < img.getWidth() - 1; x++)
{
//buffer2[y][x] = ((buffer1[y][x-1] +
//buffer1[y][x+1] +
//buffer1[y+1][x] +
//buffer1[y-1][x])/4) - buffer2[y][x];
buffer2[y][x] = ((buffer1[y][x-1] +
buffer1[y][x+1] +
buffer1[y+1][x] +
buffer1[y-1][x] +
buffer1[y + 1][x-1] +
buffer1[y + 1][x+1] +
buffer1[y - 1][x - 1] +
buffer1[y - 1][x + 1])/4) - buffer2[y][x];
buffer2[y][x] = (int)(buffer2[y][x] * dampening);
}
}*/
}
//Swaps buffers
private void swap()
{
int[] temp;
temp = buffer2;
buffer2 = buffer1;
buffer1 = temp;
}
//This creates a wave upon clicking. It also is where that 512 is coming from.
//512 was about right in my OLD code shown above, but helps to cause the Exeception now.
@Override
public void mouseClicked(MouseEvent e)
{
if(e.getX() > 0 && e.getY() > 0 && e.getX() < img.getWidth() && e.getY() < img.getHeight())
buffer2[((e.getY())*img.getWidth()) + (e.getX())] = 512;
}
private BufferedImage back;
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
back.setRGB(0, 0, img.getWidth(), img.getHeight(), movedImgArray, 0, img.getWidth());
g.drawImage(back, 0, 0, null);
}
}
Also irgendwelche Vorschläge oder Ideen wäre sehr dankbar. Danke noch einmal!
P.S. Hier sind zwei Bilder vom alten Code, der funktioniert.
Möchten Sie Ihren Code eingrenzen und Fragen stellen? –
Wie ich schon sagte, ich habe wirklich versucht, es so weit wie möglich einzugrenzen, um die SSCCE-Richtlinie zu erfüllen, aber ich möchte wirklich nur besser verstehen, wie man den Bildteil seines Algorithmus implementiert. Ich platzierte nur die Methoden, die ich für wichtig hielt, um es zu reparieren. ^ _^ –
+1 Leider ist dieser ausgezeichnete Artikel nicht mehr verfügbar, ich wünschte, ich hätte ihn offline gespeichert, aber ich tat es nicht. Durch diesen Algorithmus habe ich meinen eigenen naiven Blur-Algorithmus realisiert und implementiert (dachte schneller als Gauß) und dann die "trennbare 3-Pass-Box-Unschärfe" entdeckt - einen viel schneller als Gaußschen Ansatz. – Nolo