# Glüh effekt um Image



## Titanpharao (19. Mai 2010)

Hallo liebe Community,

habe auch mal wieder eine Frage. Kennt jemand eine möglichkeit ein "glow" effekt um ein Bild zu zeichnen? Aber nicht um ein "eckiges" bild, sondern um eine sprite. Möchte meinen NPC's einen effekt geben, bei einer bestimmten sache. Oder einen einfachen Kontur effekt. Suche schon, vielleicht hat auch jemand sowas schon gemacht.
Vielen danke für ideen.

p.s.: Will halt zeigen ob der NPC ein Quest für dich hat, ohne das dumm "!" wie mans aus den meisten Spielen kennt.


----------



## Quaxli (19. Mai 2010)

Ein passendes, transparentes Bild, ist vermutlich nicht das, was Du willst?


----------



## Marco13 (19. Mai 2010)

Wenn das zur Laufzeit aus einem Bild erstellt werden soll, das um den Sprite herum transparent ist, könnte man das Bild mit einem Gaußfilter weichzeichnen und heller machen, und über das Ergebnisbild dann nochmal das Originalbild drüberpinseln...

```
import javax.swing.*;
import javax.imageio.*;
import java.awt.image.*;
import java.awt.*;
import java.io.*;

class ImageGlow
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    new ImageGlow();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }


    public ImageGlow() throws Exception
    {
        JFrame f = new JFrame();


        f.getContentPane().setLayout(new GridLayout(1,2));

        BufferedImage input = ImageIO.read(new File("bild1.png"));
        f.getContentPane().add(new JLabel(new ImageIcon(input)));

        BufferedImage output = crateGlow(input);
        f.getContentPane().add(new JLabel(new ImageIcon(output)));


        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);

    }

    private static BufferedImage crateGlow(BufferedImage in)
    {
        int glowSize = 30;

        int iw = in.getWidth();
        int ih = in.getHeight();
        BufferedImage input = new BufferedImage(iw+glowSize*2, ih+glowSize*2, BufferedImage.TYPE_INT_ARGB);
        Graphics g = input.createGraphics();
        g.setColor(new Color(0,0,0,0));
        g.fillRect(0,0,input.getWidth(), input.getHeight());
        g.drawImage(in, glowSize, glowSize, null);
        g.dispose();

        BufferedImage output = new BufferedImage(iw+glowSize*2, ih+glowSize*2, BufferedImage.TYPE_INT_ARGB);
        Kernel kernel = createKernel(glowSize);

        BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null );
        output = op.filter(input, output);

        RescaleOp rescale = new RescaleOp(10, 0, null);
        output = rescale.filter(output, output);

        g = output.createGraphics();
        g.drawImage(input, 0, 0, null);
        g.dispose();
        return output;
    }

    private static float[] to1D(float a[][])
    {
        float result[] = new float[a.length*a[0].length];
        int index = 0;
        for (int i=0; i<a.length; i++)
        {
            for (int j=0; j<a[i].length; j++)
            {
                result[index] = a[i][j];
                index++;
            }
        }
        return result;
    }

    private static Kernel createKernel(int radius)
    {
        float g[][] = createGaussianKernel(radius, 3.0f, 1.0f);
        float h[] = to1D(g);
        return new Kernel(radius*2+1, radius*2+1, h);
    }

    private static float[][] createGaussianKernel(int arrayRadius, float kernelRadius, float sigma)
    {
        int size = arrayRadius*2+1;
        float sum = 0;
        float result[][] = new float[size][size];
        for (int x=-arrayRadius; x<=arrayRadius; x++)
        {
            for (int y=-arrayRadius; y<=arrayRadius; y++)
            {
                float fx = kernelRadius * (float)x/arrayRadius;
                float fy = kernelRadius * (float)y/arrayRadius;
                int ix = x+arrayRadius;
                int iy = y+arrayRadius;
                float value = gaussian(fx, fy, sigma);
                result[ix][iy] = value;
                sum += value;
            }
        }
        float invSum = 1.0f / sum;
        for (int x=0; x<size; x++)
        {
            for (int y=0; y<size; y++)
            {
                result[x][y] *= invSum;
            }
        }
        return result;
    }


    private static float gaussian(float x, float y, float sigma)
    {
        float nominator = x*x + y*y;
        float sigmaSquared = sigma * sigma;
        float denominator = 2 * sigmaSquared;
        float exponent = -nominator / denominator;
        float power = (float)Math.exp(exponent);
        float factor = 1.0f / (2 * (float)Math.PI * sigmaSquared);
        float result = factor * power;
        return result;
    }
}
```


----------



## Titanpharao (19. Mai 2010)

Hey danke sieht echt cool aus, nur wieso wird jetzt das transparent in dem neuen Bild so "vergraut"? :/ Brauche nur den Gelben schimmer. Achso und wieso ist das so "gelb"? geht nicht auch blau ?


----------



## Empire Phoenix (19. Mai 2010)

2 mal deinen sprite rendern, einmal 2-10 pixel größer mit nur farbe bis transparent am rand, darauf dann den sprite normal


----------



## Marco13 (19. Mai 2010)

Das gepostete war nur ein Test-Hack (um selbst zu sehen, ob das funktioniert und wie es aussieht  ). Da gibt's natürlich etliche Parameter und Stellschrauben und Verbesserungsmöglichkeiten... Das "vergrauen" kommt wohl durch die Transparenz, das müßte man wohl auch irgendwie rausfiltern können (genaugenommen war das "skalieren" nur, um das ausgrauen nicht so stark erscheinen zu lassen). Die Farbe des Glows sollte von der (Rand-) Farbe des Sprites abhängen. Alles andere ... müßte man per Hand noch tunen...


----------



## Titanpharao (19. Mai 2010)

Also die Farbe ist immer Gelb, egal welches Bild ich benutze. Puh ... sieht auch stark unterschiedlich aus von Bild zu Bild. Fummel mal bissel an dem Code rum, sieht aber recht kompliziert aus


----------



## Marco13 (19. Mai 2010)

Ohja, das gelb kommt daher, dass das mit dem rescale etwas... grell war... Hier nochmal, etwas vereinfacht und kommentiert.

Das Erstellen des Kernels braucht man eigentlich nicht nachzuvollziehen. Aber ich glaube, um "bessere" Glow-Effekte hinzukriegen, müßte man evtl. die einzelnen Bänder (also speziell den Alpha-Kanal getrennt) betrachten, das könnte dann etwas aufwändiger werden. Dann wäre es vermutlich DOCH einfacher, das ganze als Bild mit PaintShop zu malen 


```
import javax.swing.*;
import javax.imageio.*;
import java.awt.image.*;
import java.awt.*;
import java.io.*;
import java.util.*;

class ImageGlow
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    new ImageGlow();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }


    public ImageGlow() throws Exception
    {
        JFrame f = new JFrame();


        f.getContentPane().setLayout(new GridLayout(1,0));

        BufferedImage input = ImageIO.read(new File("image03.png"));
        JLabel label = new JLabel(new ImageIcon(input));
        label.setBackground(Color.WHITE);
        label.setOpaque(true);
        f.getContentPane().add(label);

        BufferedImage output = crateGlow(input);

        label = new JLabel(new ImageIcon(output));
        label.setBackground(Color.WHITE);
        label.setOpaque(true);
        f.getContentPane().add(label);

        label = new JLabel(new ImageIcon(output));
        label.setBackground(Color.GRAY);
        label.setOpaque(true);
        f.getContentPane().add(label);

        label = new JLabel(new ImageIcon(output));
        label.setBackground(Color.BLACK);
        label.setOpaque(true);
        f.getContentPane().add(label);


        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.pack();
        f.setVisible(true);

    }

    private static BufferedImage crateGlow(BufferedImage in)
    {
        int glowSize = 30;

        // Eingabebild in die Mitte von einem ARGB-Bild malen, das
        // einen Rand für das Glühen hat
        int iw = in.getWidth();
        int ih = in.getHeight();
        int ow = iw+glowSize*2;
        int oh = iw+glowSize*2;
        BufferedImage input = new BufferedImage(ow, oh, BufferedImage.TYPE_INT_ARGB);
        Graphics g = input.createGraphics();
        g.setColor(new Color(0,0,0,0));
        g.fillRect(0,0,input.getWidth(), input.getHeight());
        g.drawImage(in, glowSize, glowSize, null);
        g.dispose();

        // Kernel erstellen, der das bild weichzeichnet
        int gg = glowSize * glowSize;
        float matrix[] = new float[gg];
        Arrays.fill(matrix, 1.0f/gg);
        //Kernel kernel = new Kernel(glowSize, glowSize, matrix);
        Kernel kernel = createKernel(glowSize); //new Kernel(glowSize, glowSize, matrix);
        BufferedImageOp op = new ConvolveOp(kernel, ConvolveOp.EDGE_ZERO_FILL, null );

        // Weichzeichnen
        BufferedImage output = new BufferedImage(ow, oh, BufferedImage.TYPE_INT_ARGB);
        output = op.filter(input, output);

        // Das Glühen heller machen
        RescaleOp rescale = new RescaleOp(
            new float[]{2.0f,2.0f,2.0f,2.0f},
            new float[]{0,0,0,0}, null);
        output = rescale.filter(output, output);

        // Originalbild drübermalen
        g = output.createGraphics();
        g.drawImage(input, 0, 0, null);
        g.dispose();
        return output;
    }


    private static Kernel createKernel(int arrayRadius)
    {
        float kernelRadius = 3;
        float sigma = 1;
        int size = arrayRadius*2+1;
        float sum = 0;
        float result[] = new float[size*size];
        for (int x=-arrayRadius; x<=arrayRadius; x++)
        {
            for (int y=-arrayRadius; y<=arrayRadius; y++)
            {
                float fx = kernelRadius * (float)x/arrayRadius;
                float fy = kernelRadius * (float)y/arrayRadius;
                int ix = x+arrayRadius;
                int iy = y+arrayRadius;
                float value = gaussian(fx, fy, sigma);
                result[ix+iy*size] = value;
                sum += value;
            }
        }
        float invSum = 1.0f / sum;
        for (int x=0; x<size*size; x++)
        {
            result[x] *= invSum;
        }
        return new Kernel(size, size, result);
    }


    private static float gaussian(float x, float y, float sigma)
    {
        float nominator = x*x + y*y;
        float sigmaSquared = sigma * sigma;
        float denominator = 2 * sigmaSquared;
        float exponent = -nominator / denominator;
        float power = (float)Math.exp(exponent);
        float factor = 1.0f / (2 * (float)Math.PI * sigmaSquared);
        float result = factor * power;
        return result;
    }

}
```


----------



## Titanpharao (19. Mai 2010)

So, wenn man mit JAVA nicht mehr weiter weis, bedient man sich halt anderen Mitteln. Habs jetzt über ein Photoshop Skript gemacht. Also wenn ich mal etwas ändern will, dauert es genauso lange wie im Quellcode . 
Wenigstens etwas programmiert bei der Sache 

Trotzdem vielen Dank für deine mühe und diese wirren JAVA Klassen.


----------



## Marco13 (19. Mai 2010)

Naja. Alles, was man mit Photoshop machen kann, kann man auch mit Java machen.

Dieses Programm generiert urheberrechtlich geschützte Bilder, Bilder mit strafrechtlich relevantem Inhalt, Bilder auf denen zu sehen ist, wie das Wetter in 14 Jahren sein wird, ein Bild von einer Katze die einen Cheezburger ißt, und auch Bilder von deinen Sprites mit dem perfektesten Glüh-Effekt, den du dir vorstellen kannst. Einfach die auskommentierte Zeile einkommentieren und starten, dann werden alle diese Bilder auf die Festplatte geschrieben. Das könnte eine Weile dauern, aber... das ist es ja wohl wert 


```
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

class ImageMaker
{
    public static void main(String args[])
    {
        BufferedImage image =
            new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        while (nextImage(image, 0));
    }

    private static boolean nextImage(BufferedImage image, int i)
    {
        int x = i % image.getWidth();
        int y = i / image.getWidth();
        if (i>=image.getWidth()*image.getHeight())
        {
            return false;
        }
        int rgb = image.getRGB(x,y);
        if (rgb < Integer.MAX_VALUE)
        {
            rgb++;
            image.setRGB(x, y, rgb);
            //store(image);
            return true;
        }
        rgb = -Integer.MAX_VALUE;
        image.setRGB(x, y, rgb);
        return nextImage(image, i+1);
    }

    private static long counter = 0;
    private static void store(BufferedImage image)
    {
        String name = "image"+System.nanoTime()+"-"+counter+".png";
        counter++;
        try
        {
            ImageIO.write(image, "png", new File(name));
        }
        catch (Exception e)
        {
        }
    }
}
```


----------

