# Skaliertes Image pixelweise bearbeiten



## Atze (26. Mrz 2011)

hat schon jemand mal was paint-artiges in java geschrieben? stehe momentan vor dem problem, dass ich ein kleines image (64x32 px) mit einer grafischen oberfläche bearbeiten muss. pixelweise bearbeiten ist ja nicht das problem. allerdings ist 64x32 sehr winzig, daher sollte es gezoomt werden. wenn ich es skaliere (bspw x10) sieht mans besser, aber aus einem pixel werden logischerweise 10. später im ergebnis möchte ich aber nur das originale, einzelne pixel haben.

also bleibt wohl nur für die oberfläche in 10-facher größe anzeigen, bearbeiten und beim speichern wieder runterrechnen. soweit klar, aber wie zeige ich das an, bzw komme mit der oberfläche am einfachsten an einzelne pixel. wenn man sich bilder mit photoshop zoomed, wird aus dem  1px großen stift ein retangle, welches die "echten" pixel in einer art raster abläuft. muss ich mir das selbst bauen? oder gibts da irgendwas fertiges? wenn selber bauen, dann wie am besten? einzelne panels mit listenern (64x32 stück)? oder nen transparenten layer mit nem raster drüber und über die koordinaten gehen?
ich hoffe ihr könnt das problem nachvollziehen!?  ist schwer in worte zu fassen, daher auch schwer was im netz zu finden.


----------



## Atze (27. Mrz 2011)

was los? keiner ne meinung? zu trivial? oder hat das noch niemand gemacht? :/

*edit:*

da noch niemand was dazu sagen konnte, hier nochmal ein screenshot um das problem irgendwie deutlicher zu machen. vielleicht hab ich's einfach zu umständlich erklärt, kann mir irgendwie nicht vorstellen, dass noch niemand sowas gebraucht haben soll. ich möchte ein bild einfach zoomen und die pixel über ein raster ansprechen (siehe screenshot aus gimp), so wie es jedes gängige grafikprogramm beim heranzoomen auch tut. gibt es bereits was fertiges? nen jcolorchooser gibts ja auch, ist ja thematisch nicht weit auseinander, oder?  falls ich mir das selber bauen muss - also bei nem beispiel-zoomfaktor 10 statt eines einzelnen pixel malen, ein rechteck von 10 x 10 pixeln zu zeichnen wäre ja nicht das problem. aber dies sollte eben rasterweise geschehen. wie würdet ihr das umsetzen?


----------



## Atze (4. Apr 2011)

habs jetzt ein paar tage liegen lassen und hab mir nun folgendes überlegt:
- das vergrößerte originalbild (640x320) in die anzahl an ursprünglichen pixeln teilen (64x32)
- die einzelnen images auf panels zeichnen und diese "bildfelder" (10x10) auf clicks reagieren lassen, dabei für die oberfläche färben und den farbwert merken
- zuletzt einfach die farbwerte der einzelnen panels (in originalgröße, also 64x32 - für jedes panel einen pixel) zeichnen und speichern

jemand einwände? verbesserungsvorschläge? alternative ansätze?


----------



## Marco13 (4. Apr 2011)

Hatte den Thread gar nicht gesehen. 

Wenn man das Bild vergrößert zeichnet (also mit graphics2d.scale(10,10) ) dann könnte das dem gewünschten Aussehen schon recht nahe kommen. Evtl. muss man sowas wie Filtering (LINEAR, BILINEAR etc) explizit AUSschalten, damit er nicht versucht, die riesen-Pixel weichzumatschen. 

Dann sollte man in einfachsten Fall die Koordinaten aller MouseEvents durch 10 teilen können, um an der richtigen Stelle zu landen. Zwei mögliche Probleme kommen mir in den Sinn: Man muss eine Verschiebung reinrechnen, wenn man nur einen bestimmten Bildausschnitt sehen will. Diese Verschiebung in die Mauskoordinaten mit reinzurechnen könnte ein bißchen fummelig werden, aber sollte machbar sein. 
Dabei könnte es bei hohen Skalierungen Probleme mit der Genauigkeit geben, aber 10x10 sollte noch ohne größere Fehler gehen. Ansonsten ... wenn das nicht funzt, müßte man im schlimmsten Fall eine Art "Pixel-Editor" erstellen, das könnte dann aufwändiger werden.


----------



## Atze (5. Apr 2011)

versteh ich dich falsch oder reden wir aneinander vorbei? 

sollte recht simpel werden, um die richtige skalierung (so wie ich deine antwort verstanden habe) mach ich mir keine sorgen. es soll nicht dynamisch mehrere wählbare skalierungen geben, und der user soll das auch nicht manuell durchführen. beim laden soll das original (64x32) auf 640x320 "gezoomt" werden, hab jetzt einfach mal den faktor 10 gewählt weils dann gut sichtbar ist und sich einfach rechnen lässt. hätte auch x12 oder x15 sein können, aber wird dann auch zu groß.

jedenfalls wird das sofort einmalig vergrößert, um das bearbeiten der pixel zu erleichtern. 64x32 ist einfach zu klein dafür. auf der 640x320 großen oberfläche will ich dann aber die pixel mit einem raster so handlen, als ob es die ursprünglichen 64x32 pixel wären, also nur 64x32 felder. (so wie photoshop halt jedes bild zoomt und der gewählte pinsel dann auch entsprechend dicker wird, also mehr pixel gleichzeitig färbt)

jetzt ist nur die frage, wie bekomm ich da am einfachsten ne "durchsichtige" matrix drüber? ich dachte halt einfach an ein 64x32 mosaik aus jeweils 10x10 großen panels mit dem jeweiligen vervielfachten pixel. jedes panel sollte dann halt mit nem mouseover nen schraffierten rahmen haben und sich beim klick mit der gewählten farbe aus dem colorchooser füllen. die farbe merk ich mir und bei speicher bekommt halt nur das ensprechende kleine pixel aus dem 64x32 die farbe. das bild wird halt wieder aus den farben der panels zusammengesetzt

so, viel erklärt für wenig content, aber hoffe ist verständlicher


----------



## Marco13 (5. Apr 2011)

Vielleicht fehlt mir das Einfühlungsvermögen in die intention des Aufgabenstellers...

Aber lass' das mit den Panels mal. Klingt murksig.


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

class IconPaintPanel extends JPanel implements MouseListener, MouseMotionListener
{
    private BufferedImage image;
    private int scaling = 10;
    private int currentX = 0;
    private int currentY = 0;

    public IconPaintPanel(BufferedImage image)
    {
        this.image = image;
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        AffineTransform oldAT = g.getTransform();
        g.scale(scaling, scaling);

        g.drawImage(image,0,0,this);

        g.setTransform(oldAT);

        g.setColor(Color.RED);

        int snapX = ((int)(currentX/scaling))*scaling;
        int snapY = ((int)(currentY/scaling))*scaling;

        g.drawRect(snapX, snapY, scaling, scaling);

    }

    @Override
    public void mouseMoved(MouseEvent e)
    {
        currentX = e.getX();
        currentY = e.getY();
        repaint();
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        currentX = e.getX();
        currentY = e.getY();
        repaint();
    }

    @Override
    public void mouseClicked(MouseEvent e)
    {
        int imageX = (int)(currentX/scaling);
        int imageY = (int)(currentY/scaling);
        image.setRGB(imageX, imageY, Color.RED.getRGB());
        repaint();
    }

    @Override
    public void mouseEntered(MouseEvent e){}
    @Override
    public void mouseExited(MouseEvent e){}
    @Override
    public void mousePressed(MouseEvent e){}
    @Override
    public void mouseReleased(MouseEvent e){}

}






class IconPaint
{
    public static void main(String args[]) throws Exception
    {
        final BufferedImage image = ImageIO.read(new File("bildB.jpg_tn.jpg"));


        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                JFrame f = new JFrame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                IconPaintPanel p = new IconPaintPanel(image);
                f.getContentPane().add(p);
                f.setSize(400,400);
                f.setVisible(true);
            }
        });
    }

}
```


----------



## Atze (5. Apr 2011)

hervorragend @ marco!!!! danke! u made my day!!


----------

