JPG,PNG,GIF(Beweglich/Unbeweglich) Skalieren und drechen

Alles rund um die Programmierung mit Qt
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

JPG,PNG,GIF(Beweglich/Unbeweglich) Skalieren und drechen

Beitrag von Experimentierer »

Hallo Leute,

Ich suche eine Möglichkeit um alle gängigen Bilder auf einer Oberfläche mit mehreren Funktionen unterzubringen. Unter anderem muss es möglich sein alle Bilder zu Pixel genau zu Skalieren und mit der Maus frei zu drehen.

Ich habe bereits viel gegoogelt und dieses Forum durchsucht jedoch nix passendes gefunden :( .

Das beste was ich bisher erreicht habe ist alle Bilder nur anzuzeigen, das ging mit QMovie. Damit kann ich jedoch nur Bewegliche GIFs und nur Skalieren :cry: .

Würde mich über Ideen und Ratschläge freuen :)
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Schauen, ob das Bild eine Animation ist: QImageReader::supportsAnimation(), dann sollte es auch mit QMovie funktionieren. Um das Movie auch drehen zu können, musst du selber malen. QMovie sendet ein SIGNAL, wenn ein neues Bild gemalt werden soll, dann einfach ein update triggern und im paintEvent das Bild malen, den painter vorher natürlich drehen. Du kannst natürlich auch ohne QMovie auskommen, und direkt selber alles mit QImageReader machen. Schau dir die Doku an, sollte klar sein, welche Funktionen fürs Timen der Frames interessant sind :)
Wenn es ein normales Bild ist, sollte es soweso kein Problem sein.

Du musst natürlich deiner Klasse (erben von QWidget oder QFrame, jenachdem, ob du ein rahmenloses Widget brauchst, oder auch ein Frame drumrum sein soll, wie bei QLabel) noch Funktionen zum rotieren und skalieren des Bildes geben.

Implementierung sollte jetzt kein so großes Problem mehr sein.
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Hallo franzf
danke erstmal für die Idee, aber ich habe große probleme mit Englich und werde aus QImageReader nicht schlau :(.
Ich weiß nicht wie ich jetzt damit die Bilder Skalieren oder drehen soll und schon gar nicht wenns um ein Bewegliches gif geht.
Auch mit QPainter habe ich bisher nur sehr wenig gearbeitet, weiß also nicht wie ich damit mein Bild "Drehen" kann :(.
Könntest du mir das anhand eines Beispiels erklären z.B. mit einem Beweglichen gif und einem jpg :?:.

Am endeffekt will ich ein Programm erstellen das alle gängigen Bilder Anzeigen(nur Bild ohne Fensterrahmen) kann und mir eben die Möglichkeit gibt diese zu Skalieren, mit der Maus zu Drehen ,und weiteres, komplette Barierefreicheit eben :wink:.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Sry, Programmieren geht auf Dauer ohne ausreichend Englischkenntnisse nicht gut. Hier im Forum kann und wird auch niemend bei (Verständnis)problemen mit der Doku diese dem Problem angepasst übersetzen. Da ist es wahrscheinlich schneller, eine komplette Lösung zu programmieren.

Aber vielleicht kommst du mit gebrochenem Deutsch besser zurecht:
Google-Übersetzung zu QImageReader

Sry, ist wirklich nicht bös gemeint, aber die Doku übersetzen oder die Passagen erklären sprengt den zeitlichen Rahmen der meisten hier :/
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Ich habe nicht erwartet das du mir die Doku übersetzt. Ich habe nur nach einer Erklärung / einem Beispiel gefragt, wie ich z.B. mit QPainter ein Bild drehen kann.

Programmieren braucht auch niemand für mich, kann ich selber.
Zur Info, ich habe schon mehrere Programme alleine Programmiert wie z.B. eine Medienverwaltung für eine Bibliothek. Komme also auch mit wenig Englich zurecht. Was nicht heißen soll das ich nicht lerne. Ich habe aber nicht vor zuerst Englich komplett zu lernen und dann erst weiter Programmieren, das kann man nämlich auch parallel machen :wink:.
Ich hoffe damit ist das missverständnis geklärt.

Bin weiter für alles offen :D .
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Pixmap malen:
QPainter::drawPixmap()
Painter drehen:
QPainter::rotate()
Damit das Bild also gedreht gemalt wird, musst du einfach vorher den painter drehen.
Schau dir auch QPainter::save() und QPainter::restore() an.
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

danke franzf
Hat gut funktioniert, kann jetzt Unbewegliche Bilder Skalieren und Drehen :D.
Das ich mit der Maus Drehe werde ich, denke ich schon hinkriegen.

Doch wie ich das auch mit Beweglichen gifs nach mache wüste ich jetzt nicht :( .
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Experimentierer hat geschrieben:Doch wie ich das auch mit Beweglichen gifs nach mache wüste ich jetzt nicht :( .
Hab ich oben schon gesagt:
QImageReader kann erkennen, ob das Bild animiert ist. Also: Die Datei prinzipiell mit QImageReader laden - egal ob animiert oder nicht.
Bei Animation==true kannst du entweder ein QMovie abspielen, oder direkt mit dem QImageReader arbeiten. Die Funktionen sollten selbsterklärend sein.
* loopCount gibt die Anzahl der loops wieder
* imageCount gibt die Anzahl der einzelnen Frames der Animation
* nextImageDelay gibt die Zeit in ms bis zum nächsten Bild wieder
* jumpToImage springt zu bestimmtem Bild
* currentImageRect gibt das QRect des aktuellen Bildes
* read liest das Bild und gibt es zurück.

Du musst jetzt das aktuelle Bild einlesen und zeichnen (panmtEvent), einen Timer mit singleShot() starten (mit nextImageDelay), am besten auf update(). im paintEvent mit einer günstigen Kombination aus den oben gelisteten Funktionen das passende Bild einlesen, mit (rotiertem und skaliertem) painter malen, und wieder mit QTimer::singleShot() den Timer auf den nächsten Frame losjagen :)
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Ich danke dir vielmals :D

Habe eigentlich nicht wirklich erwartet das ich tatsächlich antworten kriege mit den ich weiter kommen könnte, da ich von anderen kenne das die meist keine Hilfe oder nur doofe Kommentare bekommen wie z.B. "wen du keine Ahnung hast solltest du erst einmal Tutorials durchgehen" und so. Dachte mir ich teste es einmal und dann kam von dir nach dem Motto das ich ohne genug Englischkenntnisse es sowieso nicht hinkriege da hatte ich es schon fast aufgegeben.
Aber dann hast du mir die wichtigsten antworten gegeben und zwar so das ich es leiht verstehen konnte.

Ich werde jetzt öfters hier vorbeischauen und auch selber mal helfen wo ich kann.
Hoffe ich treffe hier noch mehr wie dich :D.

Werde es in den nächsten Tagen Implementieren. Denke das ich es schaffen werde, melde mich sobald ich ein Ergebnis habe könnte aber eine kleine weile dauern.
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Nach längerem hin und her habe ich es nun hinbekommen das ich alle Bilder anzeigen kann. Alleine mit QImageReader ging das nicht da er keine Animation beherrscht. Also habe ich mir ein QMovie für Bewegliche und ein QImange für Unbewegliche Bilder definiert. Ich lese meine Bilder in QImageReader, zähle die Frames und entscheide ob es ein Bewegliches oder Unbewegliches Bild ist.
Skalieren klappt auch und wie ich drehe hab ich auch schon eine Idee :D.
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Ich wahr wohl etwas zu voreilig, so einfach ist das Problem doch wohl nicht komplett gelöst. Ich kann zwar Skalieren, dafür fange ich das Event QWheelEvent im
bool BildFenster::eventFilter(QObject* o,QEvent * e)
{
...
if(e->type()==QWheelEvent::Wheel)
{
QWheelEvent *event = static_cast<QWheelEvent *>(e);
if(event->delta() == 120) //MausRad auf
{
++sBildSklaierungAktuell;
}else //MausRad runter
{
--sBildSklaierungAktuell;
}
setBildAktualisieren();
}
}
und genau hier entsteht das Problem, den wen ich das Mausrad runter drehe egal wie schnell erhalte ich IMMER "delta() = -120", aber wen ich nun es rauf drehe erhalte ich beim langsamen drehen "delta() = +120" und wen ich schnell drehe abwechselnd -120 und +120 :evil:. Dadurch ist es schwer das Bild zu vergrößern.

Könnte ich das irgendwie umgehen oder ist mein Ansatz komplett falsch :?:.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

Kaputte Maus?
Und warum denn jetzt eventFilter?!? Es gibt explizit das wheelEvent, das du reimplementieren kannst:

Code: Alles auswählen

#include <QWidget>
#include <QWheelEvent>
#include <QDebug>
#include <QApplication>

class Widget : public QWidget
{
    void wheelEvent(QWheelEvent *e) {
        qDebug() << e->delta();
    }
};

int main(int argc, char** argv) {
    QApplication app(argc, argv);
    Widget w;
    w.show();
    return app.exec();
}
Und ich kann in alle Richtungen so schnell scrollen, wie ich will, das delta passt immer...
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Nein meine Maus funktioniert, trotzdem habe ich noch 2 weitere getestet. Das Ergebnis wahr das selbe. Das ich beim schnellen hoch scrollen immer wieder das falsche bekommen habe. Dabei ist mir aber aufgefallen das es erst anfängt falsche Signale zu geben wen das Bild größer wird als der Desktop. Ich habe auch void wheelEvent(QWheelEvent *e) versuch. Ergebnis dasselbe :(.
An meinem System kann das auch nicht liegen habe es auch bei einem anderen getestet. Das Bild kann ich auch bis eine Auflösung von 10000x10000 Skalieren dauert aber locker mal eine bis zwei Minuten da ich immer langsamer hoch scrollen muss um das richtige Signal zu erhalten.
Hast du noch eine Idee woran das liegen kann oder wie ich das anders lösen kann?
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

10000x10000... passt das überhaupt auf deinen Monitor?
Ich würde dahingehend optimieren, immer nur Ausschnitte aus dem Bild zu zeichnen. Du bekommst ja im paintEvent das rect(), welches neu gezeichnet werden soll. Hier kannst du doch wunderbar einen Ausschnitt aus dem rieseigen pixmap (wie groß ist das eigentlich?) nehmen und den an passender Position zeichnen.
Du kannst auch einen Timer verwenden: So lange wheelEvents sammeln (also einfach zoomFaktor hochzählen), bis der Timer auch abgelaufen ist, und erst DANN zeichnen. Kommt ein wheelEvent bevor der Timer abgelaufen ist, Timer neu starten.

Bitte verwende auch immer gleich die passenden eventHandler. Auch wenn sich am Speed am Ende nichts verändert:
* eventFilter() ist die Einsprungstelle für andere Objekte, um an die events zu kommen (schickt ja nicht alles ein SIGNAL raus)
* Eine große Funktion, in der du ALLES machst, ist unübersichtlich, fehleranfällig und kostet dank der vielen if(type()...) und casts irgendwann ein kleines Stück Performance
* Aus OOP-Sicht ist die Trennung von Funktionalität in einzelne Aufgaben zu bevorzugen: paintEvent() zeichnet, wheelEvent() wheelert, mousePressEvent() presst :P

Ich schreib das nur nochmal, da deine letzten Posts so wirkten, als würdest du hauptsächlich den eventFilter verwenden, und die spezialisierten Funktionen als Alternativen betrachten.
Experimentierer
Beiträge: 18
Registriert: 1. Mai 2011 12:06

Beitrag von Experimentierer »

Nein natürlich passt das nicht auf meinen Monitor. Muss ja auch nicht.
Wie ich nur den Bildausschnitt Zeichne weiß ich nicht. Wehre aber natürlich viel effizienter wen ich das machen würde.
Das Bild möchte ich am liebsten bis zu 100000 X 100000 Skalieren können. Klappt leider nicht, da QImange bei 11000 X 11000 Schluss macht. Den sobald ich größer versuche zu skalieren erhalte ich, das mein QImange NULL ist. Kann ich das irgendwie ändern? Einen Timer will ich nicht verwenden da sonst das Skalieren rucklig wirken wird.
Deine Annahme ist richtig ich habe alle Events im eventFilter() aufgefangen und ausgewertet. Das man alle Events lieber in separate Methoden auslagern sollte hast du wohl recht, werde ich machen.
Mein Problem wäre damit aber leider nicht gelöst. Den ich habe bereits versucht das ich das wheelEvent() separat definite, hatte jedoch keinen unterschied gebracht. Auch so hatte ich immer wider falsche Signale.
Ich verwende keine Scrollbalken, den ich packe das Bild mit der Maus an und Bewege es zum gewünschten Punkt. Soll auch so bleiben.
Bin für Ideen immer offen und wen ich etwas effizienter machen kann ohne Funktionalität einzubüßen ist mir das absolut willkommen :D.

PS meinen Benutzernamen habe ich so gewählt weil ich wirklich viel rumexperimentiere, teste und versuche auch wen es heißt das es nicht gehen soll. Ich lerne gerne dazu und bin für Veränderungen offen.
Antworten