Image Skalieren

Status
Nicht offen für weitere Antworten.

MadHatter

Aktives Mitglied
Hi!
Ich arbeite gerade an ein kleines Grafikprogramm und bin schon gleich an ein großes Problem gestoßen.
Mir scheint so, als täte das skalierte zeichnen ziemlich viel Performance fressen.
Code:
                g.drawImage(timgDrawLayer, 0, 0, (int) (psp.getProjectWidth() * zoomFactor), (int) (psp
                        .getProjectHeight() * zoomFactor), null);
Was kann ich machen um das Problem zu lösen?
 

Illuvatar

Top Contributor
Ist es vielleicht möglich, das bild einmal zu skalieren (Image#getScaledInstance), in einer Variable zu speichern und dann das schon skalierte Bild zu zeichnen?
 

MadHatter

Aktives Mitglied
Also mir ist folgendes aufgefallen:
der Befehl
Code:
g.drawImage(timgDrawLayer, 0, 0, (int) (psp.getProjectWidth() * zoomFactor), (int) (psp
                        .getProjectHeight() * zoomFactor), null);
ist langsam, wenn Bildgröße im Bereich ca. 100x100 bis 200x200 ist, und zoomFactor um die 4 bis 5. Bei Bildern der Größe 400x400 4 Fach Gezoomed, oder erstelle ich gleich ein großes bild der größe z.B. 800x800, läuft es dann wieder schnell. Ohne das Programm zu schließen, erstelle ich dann ein Bild der "kritischen" Größe, also z.B. 100x100, und male darauf gezoomed, dann läuft es wieder schnell (also das skalierte zeichnen läuft dann wieder super schnell, sobald ich vorher ein großes Bild erstellt hab, z.b. 800x800 oder 400x400 gezoomed).
Woran liegt das? Wie kann ich machen, dass er direkt schnell zeichnet, ohne vorher ein riesen Bild zu erstellen? Bitte helft mir!! Bin verzweifelt :cry:. danke :)
 

Grizzly

Top Contributor
Du kannst ja ein BufferedImage in der skalierten Größe erstellen und Dir darauf das Graphics Objekt holen. Da kannst Du dann das Bild drauf skalieren. Soviel zumindest mal zum Zwischenspeichern in einer "Variable". :)
 

Grizzly

Top Contributor
MadHatter hat gesagt.:
Bringt aber anscheinend leider nix (macht es sogar langsamer, scheint so).
Hm, naja, das es langsam ist, liegt dann aber wohl eher am Skalieren.

Was willst Du überhaupt machen? Das man die Zeichenfläche zoomen und dann auch im gezoomten Bild zeichnen kann?
 

MadHatter

Aktives Mitglied
Grizzly hat gesagt.:
Hm, naja, das es langsam ist, liegt dann aber wohl eher am Skalieren.

Was willst Du überhaupt machen? Das man die Zeichenfläche zoomen und dann auch im gezoomten Bild zeichnen kann?
Genau das will ich.

Ich hab wir was zum "reproducen" des Problems gemacht: http://virtualuna.de/data_library/bug_reproducer.jar
Der Source-Code ist mit drin in der JAR-File (Main.java).
Probiert folgendes, zeichnet auf der Fläche schnell mit der Maus (so wie bei MSPaint) kreisförmige Linien, wie ihr seht, sind diese Eckig, weils langsam ist. Geht dann erst im Menü auf "CreateHugeImage"->"Create", er erstellt ein neues großes Bild (im Hintergrund öffnet sich ein neues Fenster, ihr könnt es danach schließen wenn ihr wollt), dann zeichnet noch mal auf das Haupt-Frame (wenn nicht mehr viel Platz ist, geht auf Image->Clear, er füllt es weiß) so wie vorhin schnelle kreisförmige Linien, und ihr seht, es ist viel schneller als vorher. Warum?
Wie kriegt man hin, dass es von Anfang an schnell ist?[schild=1 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]Hilfe bitte[/schild]
 

MPW

Top Contributor
MadHatter hat gesagt.:
Probiert folgendes, zeichnet auf der Fläche schnell mit der Maus (so wie bei MSPaint) kreisförmige Linien, wie ihr seht, sind diese Eckig, weils langsam ist.

Müll, die sind eckig, weil der "Stift" zu dick ist. Die Auflösung in der gezeichnet wird reicht nicht aus, um das fein zu machen. (Hab' mir den Code nicht angeguckt, kann natürlich auch an der zu geringen Pixelanzahl liegen, weiß nicht, wie du das implementiert hast.)


MadHatter hat gesagt.:
so wie vorhin schnelle kreisförmige Linien, und ihr seht, es ist viel schneller als vorher. Warum?
Der ist nicht schneller oder langsamer(zu mindest nicht bei meinem Rechner), der zeichnet nur mit einer höheren Auflösung.


Ich bin jetzt zu faul den Source durchzugucken, liegt das an einem zu dicken Stift, oder wird das nicht verändert und es liegt nur an der anderen Auflösung?

Falls 1: reduziere ihn.
Falls 2: Mach das Bild mit der geringeren Auflösung auch deutlich kleiner, also lass das mit dem Zoomen! Das macht Bilder immer unscharf, sonst müsstest du Algorithmen drauflegen, die das glätten und das ist sicher nicht einfach.
 

MadHatter

Aktives Mitglied
Der Stift ist nicht zu Dick, sondern es wird gezoomt!!!! Es geht doch darum, das es im gezoomten Modus langsamer ist, dass es beim "stretchen" des Bildes die Anzahl Punkte die er sammelt weniger ist. Das liegt daran, dass es fürs Zeichnen im "gezoomten" Modus langsamer ist. Es ist auch langsamer. Ich hab die Zeit über System.nanoTime() gemessen. Das lustige ist ja, es wird schnell, sobald man ein großes Bild im Hintergrund erstellt...
Naja, ich hoff mal es gibt andere die das Problem verstehen können.
 

MPW

Top Contributor
Ah, jetzt hab' ich den Effekt auch gesehen;-)
War mir nicht aufgefallen, da ich wohl gleich zu Anfang ein neues BigImageFrame gemacht hab.

Also das verstehe ich jetzt echt nicht, muss an falsch deklarierten Variabeln oder so liegen..
 

MadHatter

Aktives Mitglied
Also das verstehe ich jetzt echt nicht, muss an falsch deklarierten Variabeln oder so liegen..
Ich verstehe es auch garnicht. Bin total verzweifelt deshalb. Ne, die Variablen sind glaub ich nicht falsch deklariert. Der Sourcecode ist eigentlich leicht zu verstehen und keine 100 Zeilen lang (das meißte sind leere Zeilen) - kannst es dir ja selber anschauen. Das ist bis jetzt das mysteriöseste "Progger-Problem" dass ich je hatte.
 

MPW

Top Contributor
Also, warum dieser Effekt auftritt ist mir jetzt klar: Die Systemauslastung liegt bei 100%, es gibt nicht genug Ressourcen um alles zu verarbeiten.

Aber warum ist es einmal bei 100% und einmal nur bei 98%? Wodurch wird der Unterschied bezwckt, obwohl die JVM noch eine Fensterinstanz mehr zu verwalten hat. Ich bin nicht so ein Spezialist für die Spitzfindigkeiten der JVMs, vllt. müsste da mal jemannd anders helfen.

Aber ich weiß noch was: Das ganze ist nicht so das wahre, Paint hat eine relaxte Auslastung von 30%, du musst das mit diesem draw Image in den griff kriegen, ich würde das in einen lowprioritäten Thread auslagern, der einfach so alle 1/10 s repaintet und nicht generell.
 

MadHatter

Aktives Mitglied
MPW hat gesagt.:
Aber ich weiß noch was: Das ganze ist nicht so das wahre, Paint hat eine relaxte Auslastung von 30%, du musst das mit diesem draw Image in den griff kriegen, ich würde das in einen lowprioritäten Thread auslagern, der einfach so alle 1/10 s repaintet und nicht generell.
Ja gut, aber dann wird es nicht immer direkt aufm Bildschirm angezeigt, oder?
 

MPW

Top Contributor
Also,
ich hab' das gerade mal mit einem Thread ausprobiert, der immer 1s (!) wartet, und da sind die Linien wunderschön, allerdings hängt es natürlich gewaltig.

Dann hab' ich so auf 100 ms gestellt, das merkt man auch noch, aber mehr ist halt nicht drin.

Man könnte den Thread auch auf recht niedrige Priorität setzen, dann würde es bei langsamen Zeichnen sofort erscheinen und wenn's ein bisschen länger dauert halt erst ein bisschen später.
Zusätlich muss man noch implementieren, dass er nur bei gedrückter Taste überhaupt aktiv wird, hab' ich jetzt alles noch nicht gemacht.

Und was man dann immer noch optimieren könnte ist die Verarbeitung im EventListener, vielleicht bringt es etwas jedes mal einen neuen Thread aufzumachen, dem man die neuen Koordinaten übergibt, es holt sich dann von seinem vorgänger die alten und zeichnet dann, das würde auch so einiges sparen....
Oder man speichert alle X-Werte in einem Stapel und lässt sie von einem Thread abarbeiten, das ist vllt. noch besser, da das speichern an sich, kaum Rechenzeit braucht.
 

MadHatter

Aktives Mitglied
Danke für deine Mühe! Ja genau das ist ja das Problem, es würde hängen...
Aber bisher bin ich für die Variante mit dem erstellen eines großen Bildes vor dem Zeichnen... es hängt dannach nicht und die linien sind weich *g*
 

Lim_Dul

Top Contributor
Mach mal
buff = new BufferedImage(w,h, BufferedImage.TYPE_INT_RGB);
anstelle von

buff = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);

Dann geht es definitiv besser.
 

MadHatter

Aktives Mitglied
Und was macht man, wenn das Bild durchsichtig ist(sein soll)?
Aber sonst ist es eine gute "Lösung", danke!
 

Lim_Dul

Top Contributor
Dumm aus der Wäsche gucken und sun treten ;)

Ernsthaft: Wo genau das Problem liegt, kann ich auch nicht finden. Es scheint aber irgendwo in den Tiefen der Image API zu schlummern. Zumindest deuten die "Problemlösungen" darauf hin. Wenn ich mal Zeit finde, experementiere ich auch mal was weiter.
 

MPW

Top Contributor
Ja, aber das ist ja keine Alternative, oder?

edit: grr.. da war schon wieder einer schneller.

Also irgendwas hab' ich mit dem Stack falsch gemacht, es hat "lustige" Nebeneffekte, außerdem muss man das zeichnen noch in einen anderen Thread packen, hab's nur gerade nicht geschissen gekriegt.
Wie kann man denn aus einer inneren Klasse, wenn man z.B. einen zweiten Thread haben will, in der dazugehörigen public Klasse Methoden aufrufen ohne in das non-static - static Delemma zu kommen?

Code:
class ImageComponent extends JComponent implements MouseListener, MouseMotionListener, Runnable
{
    private static final long serialVersionUID = 1L;

    public BufferedImage buff;
    private int zoom;
    private int x0=0,y0=0;
	JComponent k = this;

    Stack<Point> s = new Stack<Point>();


	public ImageComponent(int w, int h, int z)
    {
        Dimension imgdim = new Dimension(w*z,h*z);
        zoom = z;

        buff = new BufferedImage(w,h, BufferedImage.TYPE_INT_ARGB);
        Graphics g = buff.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0,0, w,h);

        this.setMinimumSize(imgdim);
        this.setMaximumSize(imgdim);

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
        new Thread(this).start();
    }
    public void paintComponent(Graphics g)
    {
        g.drawImage(buff, 0,0, buff.getWidth()*zoom, buff.getHeight()*zoom, null);
    }

    public void mouseDragged(MouseEvent e)
    {
		s.push(new Point(e.getX(), e.getY()));
   }

    public void mouseMoved(MouseEvent e)
    {}

    public void mouseClicked(MouseEvent e)
    {}

    public void mousePressed(MouseEvent e)
    {
        x0 = e.getX()/zoom;
        y0 = e.getY()/zoom;
    }

    public void mouseReleased(MouseEvent e)
    {}

    public void mouseEntered(MouseEvent e)
    {}

    public void mouseExited(MouseEvent e)
    {}
    public void run() {
		while (true) {
			if (! s.empty()) {
				Point p = s.pop();
				int x = (int)p.getX()/zoom;
				int y = (int)p.getY()/zoom;
				Graphics g = buff.getGraphics();
		        g.setColor(Color.BLACK);
		        g.drawLine(x0,y0, x,y);
		        x0=x;
		        y0=y;
		        repaint();
			} else {
				try {
					Thread.sleep(200);
				} catch (InterruptedException e) {
				}
				System.out.println("empty");
			}
		}

	}
}
[/code]
 

MadHatter

Aktives Mitglied
Naja, also mit Threads kenn ich mich nicht aus, und scheint auch nicht zur Lösung zu führen. Tatsächlich ist das skalieren von Bildern, ohne Alphakanal (BufferedImage.TYPE_INT_RGB) viel viel schneller als das skalieren von Bildern mit (BufferedImage.TYPE_INT_ARGB). Die Lösung die mir jetzt half, war, dass ich jetzt alles auf ein BufferedImage.TYPE_INT_RGB zeichne, und am Ende dann dieses skaliere. Das "stottern" ist dadurch weg, und ein großes Bild vorher zu erstellen ist dann auch nicht mehr notwendig.
 

MPW

Top Contributor
Ach so, und meine Variante hat dir nicht gefallen, obwohl die auch so schoen war....***buhuh*** naja, schoen das es jetzt klappt.
 

MPW

Top Contributor
Joa, ich hatte verdammt genaue Pixel, allerdings nicht die Threadvariante, sondern habe in dem MouseListener die Koordinaten nur in ein Hash gespeichert, und dann mit einem Thread gezeichnet, langsam ging das direkt, bei schnellen Bewegungen war ein kleines bisschen Verzoegerung drin, aber die Qualitaet war spitze.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
H Skalieren von Image -> java.lang.OutOfMemoryError - WARUM Allgemeine Java-Themen 18
D Image bewegt sich nicht nach Klicken auf Button Allgemeine Java-Themen 15
Mozart53 JLabel nur meinen Text verschieben ohne Image Allgemeine Java-Themen 3
Y Wie bekomme ich durch getImage an das Image heran? Allgemeine Java-Themen 1
J jsch direktes streamen in ein image Allgemeine Java-Themen 11
A 2D-Grafik Einfachster Ansatz, um sich wiederholende Figur in einem 2D-Image zu erkennen Allgemeine Java-Themen 1
T 2D-Grafik Chart als Image erstellen Allgemeine Java-Themen 3
G Image in Shape wandeln Allgemeine Java-Themen 1
T Swing Image rotieren Allgemeine Java-Themen 1
I nach Image Load in ListView, kann Ordner nicht mehr gelöscht werden Allgemeine Java-Themen 1
C pfad vom Image ausgeben lassen Allgemeine Java-Themen 5
Bananabert Swing jtree : image als user object Allgemeine Java-Themen 2
M Image auslesen Allgemeine Java-Themen 2
G Pixelanzahl aus Raw Image Datei Allgemeine Java-Themen 1
H OCR und Image Processing Allgemeine Java-Themen 4
M Image für PDF nicht verfügbar - Runnable .jar Allgemeine Java-Themen 3
S BLOB Image in JSP anzeigen Allgemeine Java-Themen 5
BRoll Image RGB Werte auslesen und vergleichen Allgemeine Java-Themen 8
K Image zu BufferedImage konvertieren Allgemeine Java-Themen 9
K Image beim catchen ist immer null Allgemeine Java-Themen 9
X Image Processing libary für JavaSE und Android Allgemeine Java-Themen 2
Crashbreaker RCP-View Image öffnen und darstellen Allgemeine Java-Themen 7
S IMAGE ARRAY laden Allgemeine Java-Themen 6
B Image oder GridControl? Allgemeine Java-Themen 8
B Image Thinning Allgemeine Java-Themen 3
A Input/Output Buffered Image zu Byte Array und zurück konvertieren Allgemeine Java-Themen 4
F Datentypen Floppy-Image-Dateisystem Allgemeine Java-Themen 5
F Image - Ausschnitt bekommen Allgemeine Java-Themen 3
J Teil eines Image/ImageIcon zeichnen Allgemeine Java-Themen 2
N Unable to convolve src image Allgemeine Java-Themen 7
H image in jtextarea/JLabel einbinden... Allgemeine Java-Themen 4
Aigu Bilderkennung / Image Analysis Allgemeine Java-Themen 2
M Nochmal I-Frame zu Image Allgemeine Java-Themen 4
M JPEG Image komprimieren Allgemeine Java-Themen 2
M Probleme mit Image Extraction aus PDF Allgemeine Java-Themen 2
V Image laden - URL über ClassLoader ermitteln Allgemeine Java-Themen 2
G sun.awt.image.OffScreenImage Serializable machen Allgemeine Java-Themen 5
T Image in gif umwandeln Allgemeine Java-Themen 14
G itext größe von image Allgemeine Java-Themen 2
T JPanel to Image? Allgemeine Java-Themen 6
K Image Resizer Allgemeine Java-Themen 4
D Image runterscalieren, aber schlechte Quali? Allgemeine Java-Themen 3
L Buffered Image teilweise zeichnen Allgemeine Java-Themen 6
P Image erzeugen Allgemeine Java-Themen 7
B Image libraries Allgemeine Java-Themen 3
MQue Image über Komponente Allgemeine Java-Themen 3
P Image auf JPanel auf JFrame Allgemeine Java-Themen 3
P Image auf einem Panel mit null-Layout Allgemeine Java-Themen 8
E Image unterscheiden Allgemeine Java-Themen 16
E Image auf einem JLabel darstellen Allgemeine Java-Themen 3
F BufferedImage -> Image Allgemeine Java-Themen 4
E Wie bekomme ich mein Image in das Fenster Allgemeine Java-Themen 2
T Muster/Zeichen/Texterkennung auf einem Image Allgemeine Java-Themen 9
L Linien, Recktecke und Elipsen zeichnen ohne Image Allgemeine Java-Themen 2
T Disk Image Library (iso,mdf,nrg,bin) Allgemeine Java-Themen 6
S KeyListener! Image Problem! Allgemeine Java-Themen 2
S Image als Background Allgemeine Java-Themen 5
B Image(png) versenden Allgemeine Java-Themen 3
N Image -> cropImage Allgemeine Java-Themen 3
T Image mithilfe von DirectColorModel und Pixel erstellen Allgemeine Java-Themen 3
G Image in der Größe ändern Allgemeine Java-Themen 2
C probleme mit image Allgemeine Java-Themen 4
C Pixelfarbe aus einem image auslesen Allgemeine Java-Themen 6
D ByteArray für Image-Icon laden. Allgemeine Java-Themen 4
T iso datei (Image) mit Java einlesen und Inhalt entpacken Allgemeine Java-Themen 3
O Image mit transparenten farben wie bei *.GIF ? Allgemeine Java-Themen 3
B Image#getScaledInstance & Graphics2D#drawImage ClassCast Allgemeine Java-Themen 3
H Speicher freigeben klappt nicht bei Image Objekten, warum? Allgemeine Java-Themen 8
T Auf ein Image geklickt Allgemeine Java-Themen 13
J ISO image erzeugen Allgemeine Java-Themen 3
J Wie mache ich den Hintergrund einer Image durchsichtig? Allgemeine Java-Themen 7
G Aus JPanel Image Hohlen Allgemeine Java-Themen 3
D BufferedReader in image umwandeln Allgemeine Java-Themen 3
S Image Datei serializieren Allgemeine Java-Themen 3
G JFrame nimmt mein Image nicht Allgemeine Java-Themen 2
F Image als GIF oder JPEG abspeichern Allgemeine Java-Themen 2
A GUI skalieren Allgemeine Java-Themen 3
RalleYTN 2D-Grafik Bild mit bilinearer Interpolation skalieren Allgemeine Java-Themen 31
D Tool zum skalieren von bildern Allgemeine Java-Themen 4
S Sinnvolles skalieren von Werte-Set? Allgemeine Java-Themen 2
S Linie skalieren Allgemeine Java-Themen 13
F 2D-Grafik Qualitätsverlust beim Skalieren Allgemeine Java-Themen 4
F Bild aus externer Quelle laden und Skalieren? Allgemeine Java-Themen 11
G AffineTransform Skalieren? Allgemeine Java-Themen 2
P Wieso skalieren diese beiden Threads unterschiedlich gut? Allgemeine Java-Themen 16
G Bilder skalieren Allgemeine Java-Themen 2

Ähnliche Java Themen

Neue Themen


Oben