Programozás 3
1
2016
Képfájlok beolvasása és megjelenítése Előzmények Eddig a Rajzolás, Grafika és az Interaktivitás lap programját készítettük el. Ennek a programnak néhány új funkcionalítással ellátott verziója letölthető a szerverről. Nevezzük át a GrafikaQtvel könyvtárat pl. GrafikaQtvel_rajzolas-ra. A tanszéki fájl szerverről töltsük le, és bontsuk ki a GrafikaQvel_fraktal.7z fájlt, ami a program a Visual Studio 2016, és QTCreator alatt lefordítható verziója. Ez annyiban különbözik az előző Interaktivitás lapot használó programtól, hogy van benn néhány pótlólagos segítő függvény pl. az eredeti koordináták visszaállítására. A Camvas osztály lehetőségei is kibővültek azzal, hogy képes a gumiszalag kezelésére és a gumiszalagos kiválasztás végén egy SIGNAL-ban elküldi a kiválasztott terület adatait egy QRect strukturában. Ez használható bármilyen Canvas objektumon kijelölésre. Egy új függvény: void AllowSelections(bool allow) { _selectionAllowed = allow; }
engedélyezi, vagy letiltja a kijelölést. A MousePressEvent(), MouseMoveEvent() és MouseReleaseEvent() pedig lekezeli azt, illetve a LastPosChanged(QMouseEvent *) melett elküldi a void RectangleSelected(QRect); SIGNAL-t is. Bónuszként a Fraktál lap is él, és a fraktálok közül a Mandelbrot halmaz megjelenítésére és abba belenagyításra is képes. Ez sok apró feladat megoldását követelte meg1 - akit érdekel nézze meg a kódot és, ha kérdése van szívesen segítek – de minket csak annyi érint, hogy a kép pontjainak megjelenítéséhez a Canvas::SetPixel(QPoint,QColor) függvényt használjuk.
1
Pl.a számolás félbeszakítását, hogy egy újat kezdhetjünk.
Programozás 3
2
2016
Képeken végezhető műveletek 1. Betöltés fájlból. Sok képformátum van ezek közül a Qt nem mindegyiket támogatja. 2. Kiírás fájlba adott képformátumba. 3. Az eredeti, vagy a feldolgozott kép megjelenítése 4. Nagyítás/kicsinyítés 5. Forgatás speciális szögekkel (90o, -90o, 180o) 6. Tükrözés vízszintesen és függőlegesen 7. Forgatás tetszőleges szöggel 8. Beillesztés a látható képterületbe 9. 1:1 méretű megjelenítés. Ekkor lehet, hogy az egész kép nem fér bele a látható részbe, ilyenkor általában ide-oda lehet húzogatni a látható részt 10. Speciális fotószűrők alkalmazása: pl. élesítés, elmosás, negatív kép, átszínezés 11. Élkeresés 12. Képek összerakása egy képpé (rétegek kezelése), miközben az egyes pixeleken az összetevő képek pixeleiből adott szabályok szerint határozzuk meg. Ilyen szabály lehet pl., hogy csak az eredmény a sötétebb pixel lesz. 13. … A QImage (QPixmap) ezen feladatok mindegyikének megoldására alkalmas. Mi a QImage-t fogjuk használni2.
Koordináta transzformációk A QMatrix osztály Egy 2D transzformációt speciális mátrixokkal írhatunk le. Ezek a QMatrix és a QTransform. A QMatrix csak 2D transzformációkat tesz lehetővé, a QTransform tetszőleges 3D transzformációkat 2D-ben. Egy QMatrix így néz ki:
2
Az itt bemutatott függvényeknek más túlterhelt változataik is lehetnek, és a QImage-nak sokkal több függvénye van, ami hasonló feladatokra használható. Pl. a load() függvénynek két verziója van és képek betölthetőek a loadFromData() függvényekkel is.
Programozás 3
3
2016
A transzformációkat mátrix szorzással kaphatjuk meg. Ha pl. r = (x, y) a transzformáció előtti, r' = (x', y') a transzformáció utáni koordináták és m egy QMatrix, akkor r' = m·r, ill. x'= m11·x + m21·y + dx és x'= m22·y + m12·x + dy A visszatranszformáláshoz az inverz mátrixot használjuk, amit az m-ből az inverted() függvényével kaphatunk meg. A mátrix elemeit megadhatjuk a konstruktorokban: QMatrix (qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) QMatrix(const QMatrix &matrix)
vagy később is a void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
függvénnyel, illetve az egyes transzformációkhoz tartozó függvényekkel. A mátrix elemeit az m11( ), m12( ),m13( ), dx( ), ill. dy( ) függvényekkel kérhetjük le. A mátrix determinánsát a determinant() függvény. Az isInvertible() megmondja a mátrix invertálható e. A transzformációk lehetnek: eltolások, forgatások, tengelyre, vagy pontra tükrözések és nyírási deformációk. amikkel lényegében egy ferdeszögű koordinátarendszerre térünk át. Az y tengelyhez derékszögű rendszerben az x = 0 érték tartozik. Az x irányú sx tényezőjű nyírás azt jelenti, hogy az y tengely Y magasságban levő pontja az eredeti x tengelytől sx * Y távolságra kerül. Az sx=1.0 érték az y tengely 45 fokos szögű elforgatásának felel meg3. Pl egy 100 x 100pixeles négyzetre:
Ez a képernyő, illetve egy widget koordinátarendszerében, ahol az y tengely lefelé mutat – tehát az x tengelyre tükrözve van balra forgatásnak felel meg. 3
Programozás 3
sx=0, sy=0
4
sx=1.0, sy=0
2016
sx=0, sy=1
Az egyes transzformációk megadásának függvényei:
translate(QPointF &eltolás) – eltolja a koordinátarendszert egy vektorral
rotate(qreal szög_fokokban) – Egy fokokban mért szögű elforgatás QMatrix-át a rotate(qreal ) írja le. Pozitív szög az óramutató járásával ellentétes irányú forgatást jelent – matematikailag. Mivel azonban a koordinátarendszer y tengelye a Widgetek esetében általában lefelé mutat, vagyis a koordinátarendszer a normál koordinátarendszereink tükörképe, ezért a pozitív szög jobbra fog forgatni.
scale(qreal x_szorzó, qreal y_szorzó) – átskálázza a koordinátarendszert a két szorzóval, vagyis minden a koordináta a szorzóval több pixelt jelent.
shear(qreal sx, qreal sy) – nyíró transzformációt végez
Több transzformáció egymás utáni elvégzése az egyes transzformációs mátrixok szorzatával írható le. A reset( ) függvény egységmátrixot csinál a mátrixból, ahol az x, y eltolások is 0-k és az isIdentity() függvény megmondja, hogy a mátrix az egységmátrix-e. A sokszorosan túlterhelt map( ) függvények az argumentumaiknak megfelelő mennyiségeket (valós, vagy pixel koordináták, QPoint, QPointF,QLine, QLineF,QPolygon,QPolygonF, QRect, QRectF, stb) transzformálják a mátrixszal. Természetesen a szokásos mátrix műveletek is definiálva vannak. A QTransform osztály Bár a QMatrix-al sok transzformáció elvégezhető ezek mind a 2D síkbeli transzformációk. A QTtransform mátrix azonban valódi 3 x 3-as mátrix. Rendelkezik a QMatrix minden transzformációjával (rotate(), scale(), shear() és translate()), de térbeli transformációkra is ad lehetőséget. Pl. egy alakzatot/képet elforgathatunk vele bármelyik. tengely körül: QTransform &QTransform::rotate(qreal szög_fokban, Qt::Axis tengely = Qt::ZAxis)
A tengely lehet Qt::XAxis, Qt::YAxis és Qt::ZAxis. A QTransform &QTransform::rotateRadian(qreal szög, Qt::Axis tengely = Qt::ZAxis)
Programozás 3
5
2016
függvény radiánban megadott szöggel forgat el. A forgatás iránya most is attól függ, hogy valós, vagy képernyő/widget koordinátákat használunk. A mátrixelemek ugyanúgy megadhatóak a konstruktorokban, illetve a setMatrix() függvénnyel, mint a QMatrix esetében: QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33 = 1.0) QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) QTransform(const QMatrix &matrix) void setMatrix (qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33)
A QT-ben a QTransform a javasolt transzformációs mátrix.
Képek megjelenítése QPainter-rel végezve a transzformációkat: A QTransform és QMatrix osztályok leírják a transzformációkat, de a képek megjelenítését a QPainter osztály végzi. A kirajzolás során a QPainter objektumok is QMatrix-okat, illetve QTransform-ot használnak. A QPainter transzformációi megfelelnek a mátrixok transzformációinak. Pl. egy szöveget 45 fokos szögben elforgatva így írhatunk ki: void SimpleTransformation :: paintEvent( QPaintEvent * ) { QPainter painter( this ); painter . rotate( 45 ); painter . setFont( QFont ( "Helvetica", 24 )); painter . setPen( QPen ( Qt:: black , 1 )); painter . drawText( 20, 10, "Ferde szöveg" ); }
Ahogy a mátrixoknál több transzformációt is végezhetünk egyszerre egymás után meghívva az egyes transzformációs függvényeket. A QPainter transzformációkat pl. a következő egyszerű teszt programmal lehet kipróbálni (sp1,sp2… az egyes (Double) Spin Boxok nevei fentről lefele, a btn pedig a Tool Button):
Programozás 3
6
A program GUI-ja main.cpp #include "pteszt.h" #include
int main(int argc, char *argv[]) { QApplication a(argc, argv); Pteszt w; w.show(); return a.exec(); }
pteszt.h #ifndef PTESZT_H #define PTESZT_H #include #include "ui_pteszt.h" class Pteszt : public QMainWindow { Q_OBJECT public: Pteszt(QWidget *parent = 0); ~Pteszt(); protected: void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; private: Ui::PtesztClass ui; private slots: void on_btn_clicked(); }; #endif // PTESZT_H
2016
Programozás 3
7
2016
pteszt.cpp #include "pteszt.h" #include #include Pteszt::Pteszt(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); } Pteszt::~Pteszt() { } void Pteszt::paintEvent(QPaintEvent *event) { QPainter painter; painter.begin(this); qreal sx, sy; sx = ui.sp1->value(); sy = ui.sp2->value(); painter.translate(ui.sp4->value(), ui.sp5->value()); painter.shear(sx, sy); painter.rotate(ui.sp3->value()); painter.scale(ui.sp6->value(), ui.sp7->value()); painter.setPen(QPen(Qt::blue, 3, Qt::DashLine)); painter.setBrush(QBrush(Qt::red, Qt::BDiagPattern)); painter.drawRect(20, 20, 200, 100); painter.end(); } void Pteszt::on_btn_clicked() { update(); }
A Qimage transzformációi Ezekkel a transzformációkkal akár egy képet is rárajzolhatnánk a Canvas-ra a QPainter::drawImage() függvénnyel. Ennek azonban az a hátránya, hogy néhány4 művelet OSX és/vagy Windows alatt nem működne, illetve az, hogy minden paintEvent-ben újra el kellene végezni a transzformációkat a teljes képen, ami időigényes. Ehelyett kihasználjuk, hogy ugyanezeket a műveleteket a QImage is ismeri (sőt ezeknél többfélét is), ezért elő tud állítani magából egy másik, transzformált QImage-t, amit azután megjeleníthetünk. A következő paintEvent-ben ezt a QImage-t már csak ki kell rajzolni, nem kell újra elvégezni a képen a transzformációt. Ebből következően két QImage-re van
4
általunk egyébként nem használt…
Programozás 3
8
2016
szükségünk: az egyik az eredeti fájlból betöltött, a másik a transzformált. A transzformált QImage-t előállító függvények a következők5:
Tükrözés függőlegesen, vagy vízszintesen mirrored(bool horizontal = false, bool vertical = true) Ez egy tükrözött képet ad vissza. Az eredeti kép nem változik meg.
Átméretezés: QImage QImage::scaled(const QSize &téglalap, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation) Ez egy olyant átméretezett képet ad vissza, aminek a méretét a megadott téglalap adja meg az aspectRatioMode (oldal arány) alapján:
. Itt a szaggatott vonal jelzi a téglalapot. A használt módszert a transformMode adja meg. Ha ez Qt::FastTransformation, akkor a simítás nélküli transzformáció történik, szemben a Qt::SmoothTransformation esetében, ami bilineáris szűrést használ. Egyik módszer sem igazán alkalmas nagy nagyításokra. Az eredeti kép most sem változik meg. Van olyan változata is, ahol a QSize helyett a szélességet és magasságot külön adhatjuk meg: QImage QImage::scaled(int width, int height, Qt::AspectRatioMode aspectRatioMode = Qt::IgnoreAspectRatio, Qt::TransformationMode transformMode = Qt::FastTransformation)
Hasonló tarszformációkat végeznek a QImage scaledToWidth(int width, Qt::TransformationMode mode = Qt::FastTransformation) QImage scaledToHeighth(int height, Qt::TransformationMode mode = Qt::FastTransformation)
5
A szokásos kapcsolat a QMatrix és a QImage transzformációs függvényei között: pl. a scale() a mátrix transzformáció függvénye, a scaled() viszont egy scale()-d mátrixszal előállított másik képet ad.
Programozás 3
9
2016
függvények is. Ezek megtartják az oldalak arányát.
Képek elforgatása, eltolása, nyírása, nagyítása és kicsinyítése mátrixokkal írható le. Pl egy balra 90 fokos elforgatás programja: void Canvas::rotateLeft90() { QMatrix m; m = m.rotate(-90); _actImage = _actImage.transformed(m, Qt::SmoothTransformation); }
A kép ilyen transzformációját a QMatrix osztállyal adhatjuk meg és a transformed() függvényt kell meghívni hozzá: QImage QImage::transformed(const QMatrix &matrix, Qt::TransformationMode mode = Qt::FastTransformation)
A koordinátarendszer átskálázását is leírhatjuk mátrixokkal. Ehhez ugyancsak a transformed() függvényt és egy nagyítási mátrixot használunk, amit a QMatrix QMatrix &QMatrix::scale(qreal sx, qreal sy) függvénye ad meg.
A QTransform mátrixot csak a transformed() függvényben használjuk.
Képformátumok és a QImage Ahogy már beszéltünk róla a QIamge a képformátumok közül az alábbiakat alapból ismeri: BMP
Windows Bitmap
Read/write
GIF
Graphic Interchange Format (optional) Read
JPG
Joint Photographic Experts Group
Read/write
JPEG
Joint Photographic Experts Group
Read/write
PNG
Portable Network Graphics
Read/write
PBM
Portable Bitmap
Read
Programozás 3
10
2016
PGM
Portable Graymap
Read
PPM
Portable Pixmap
Read/write
TIFF
Tagged Image File Format
Read/write
XBM
X11 Bitmap
Read/write
XPM
X11 Pixmap
Read/write
Más képformátumok beolvasásához és írásához készíthetünk külső modulokat (plugin), amikkel kiegészíthetjük a QImage funkcionalítását. Az ismert képfájlokat a load(const QString &fileName, const char *format = nullptr)
függvénnyel fogjuk betölteni6. Képeket betölthetünk fájlból, vagy a forrásprogramhoz tartozó resource-ból is. Az utóbbi esetben a fájl neve helyett a resource nevét kell használni, ami mindig ':/'-el kezdődik. Pl. a GrafikaQT-vel program esetében a resource-ban található7 egyik kép neve :/GrafikaQTvel/ellipse.png. A QImage-ben tárolt kép pixelekből áll, tehát raszteres grafika. Minden pixelhez egy egész szám tartozik. Ennek a mérete a kép bit-mélységétől függ, amit a depth() függvénnyel kérdezhetünk le. Egy adott bit-mélységhez több formátum is tartozhat. A formátumot a format() függvénnyel kérhetjük le, ami egy QImage_Format enum értékeit adja vissza. A beolvasott képeket – átszínezéseket kivéve - ugyanúgy manipuláljuk a formátumtól függően. A bit-mélység és az integer méretének kapcsolata: 1 bit/pixel (egyszínű monochrome kép) – 1 bájtban 8 pixel adatai vékony- és vastag végű formátumban8. Maguk a színek egy két elemű táblázatban vannak megadva. Ez egy indexelt formátum 8 bit/pixel – 256 szürkeárnyalatos, vagy 256 elemű szín-táblázatot használó formátumok
Betölthetnénk a megfelelő konstruktorral is vagy a loadFromData() függvénnyel, de ezeket nem fogjuk használni. 7 A jelenlegi QT verziók a resourc-okat a végrehajtható fájlba rakják bele, nem külön fájlként használjék. 8 Vastag végű (big endian) – legnagyobb helyi értékű bit a bal oldali pixel, vékony végű (little endian) – ez a jobb oldali pixel. 6
Programozás 3
11
2016
16 bit/pixel – pixelenként 2 bájtot (_int16) elfoglaló, a három szín komponenst (R,G és B) 4-4-4, 5-5-5 vagy 5-6-4 biten megadó formátum. A 4-4-4 nek van egy másik variációja, ahol még egy 4 bites alfa csatorna is meg van adva: 4-4-4-4. Ez a formátum egy előszorzott ARGB formátum, ami azt jelenti, hogy az R,G és B komponensek már eleve meg vannak szorozva az alfa csatorna értékének 255-ödével. Az 5-5-5 formátumnál a fennmaradó bit mindig 0. 24 bit/pixel – pixelenként 4 bájtot (_int32) elfoglaló formátumok. A nem használt bitek mindig 0-k: 85-6-5 előszorzott ARGB , 6-6-6 RGB, 6-6-6-6 előszorzott ARGB, 8-5-6-5 és 8-5-5-5 előszorzott ARGB, 8-8-8 RGB 32 bit/pixel. – pixelenként 4 bájtot (_int32) elfoglaló formátumok. 8-8-8 RGB, felső 8 bit 1-es, AARRGGBB, előszorzott ARGB formátum9, bájt rendezett formátumok10: RRGGBBAA (big endian), AABBGGRR (little endian) és ezek előszorzott változata
A Qimage alapértelmezett konstruktora egy NULL képet állít elő.NULL képet kaphatunk más, méreteket és formátumot is megadó konstruktorokkal is, ha a szükséges kép memória nem allokálható. Ezt az isNull() függvénnyel ellenőrizhetjük. Mi kizárólag nem indexelt RGB képekkel foglalkozunk, és a kép formátumának vagy QImage::Format_RGB32, vagy QImage::Format_RGB888 –ot állítunk be. Amikor egy adott méretű QImage-t hozunk létre nem egy másik képből, akkor az egyes pixelek értéke határozatlan lesz. Azokat kirajzolás előtt mindig be kell állítani, pl. a fill() függvények valamelyikével
A Kép lap programja A GUI módosítása A szokásos módon kapcsoljunk át a bal oldalon a Képek oldalra, azután adjunk hozzá a jobb oldali stckPages Stacked Widget-hez egy új, 5. lapot (currentIndex = 4) és nevezzük át pnlImages –re! Rakjunk rá erre a lapra egy widgetet, léptessük elő Canvas-szá, nevezzük át canvas3-á és a lap elrendezését állítsuk vízszintesre! Mentsük el a változtatásokat!
9
Előfordulhat, hogy RR, GG vagy BB > AA, ekkor a viselkedés nem definiált. Ha a megfelelő bájt sorrendű gépen olvassuk be bájtonként, akkor ugyanazt a színt adja meg mindkettő.
10
Programozás 3
12
2016
A grafikaqtvel.cpp/.h módosítása Adjuk hozzá az 5. lapra kapcsolást az on_tbxMenu_currentChanged(int index) SLOT-hoz! Adjunk SLOT deklarációkat az összes widget lekezeléséhez grafikaqtvel.h header fájlhoz! Ezek a clicked() SIGNAL-ok a gombokhoz, a, textChanged(QString) signal a beviteli mezőhöz, a currentIndexChanged(int index) signal a lenyíló Combo Box-hoz és a valueChanged() signal a QDoubleSpinBox és QSlider objektumokhoz. A Beolvasás és a Megjelenítés gomb legyen alapból inaktív. A Beolvasás gombot akkor tegyük aktívvá, ha egy létező kép fájl neve van a beviteli mezőben és a fájl még nincs bent a memóriában, más esetekben legyen inaktív. Az ehhez tartozó feltételek tehát: a gomb aktív, ha -
a beviteli mező szövegét kézzel átírtuk (és nem a böngészés (btnImageBrowse) gomb írta át)
-
a beviteli mezőben levő szöveg egy létező kép fájl neve
-
ez a név nem azonos a memóriában levő fájl nevével
A Megjelenítés gomb akkor aktív, ha van kép a memóriában. Amikor a btnImageBrowse gombbal választottunk fájlt, akkor a képet azonnal olvassuk be a _loadedImage-be, függetlenül attól, hogy mi van a memóriában. A fentiekhez egyfelől szükségünk van a beolvasott fájl nevére. Adjunk hozzá egy QString _imageName;
változót a GrafikaQTvel osztály privát részéhez. Másfelöl, amikor a beviteli mező szövegét átírja a böngészéssel megadott név a Beolvasás gomb inaktív kell, hogy legyen. Ehhez elég, ha az _imageName-et előbb állítjuk be, mint a beviteli mező szövegét Írjuk meg a btnImageRead gombhoz tartozó SLOT-ot a fájl beolvasására, a btnImageBrowse gombhoz tartozó SLOT-ot a fájl böngészésére, és az edtImageFile bevitelő mezőhöz tartozót a szövegváltoztatás lekezelésére! A fájl beolvasó gomb csak akkor aktív, amikor érvényes fájl név van a beviteli mezőben. Először elmenti ezt, majd beolvastatja és megjelenítteti a képet a Canvas-szal.
Programozás 3
13
2016
void GrafikaQTvel::on_btnImageRead_clicked() { _imageName = ui.edtImgFile->text(); // név elmentése if (ui.canvas3->ReadImage(_imageName)) // kép beolvasás és megjelenítése ui.btnImageDisplay->setEnabled(true); else ui.btnImageDisplay->setEnabled(false); }
A böngészéshez kiindulásként átmásolhatjuk a kódot a btnBrowse2_clicked() függvényből, csak a fájl típusokat kell átírni a kép típusokra11 . void GrafikaQTvel::on_btnImageBrowse_clicked() { QString fileName = QFileDialog::getOpenFileName(this, QString("Kép fájl megnyitása"), "./", QString("Kép fájlok (*.BMP,*.GIF,*.JPG,*.JPEG,*.PNG);;X11 kép fájlok (*.PBM,*.PGM, *.PPM, *.XBM,*.XPM)" )); if (!fileName.isEmpty()) // volt létező fáj név { ui.edtImgFile->setText(fileName); } }
Ezután az if –be berakjuk a kódot a kép nevének letárolására és a kép betöltésére: if (!fileName.isEmpty()) // volt létező fájl név { _imageName = fileName; // név elmentése on_btnImageRead_clicked(); // kép beolvasás és megjelenítése ui.edtImgFile->setText(fileName); // kép név a beviteli mezőbe }
Itt felhasználtuk a betöltő gomb SLOT függvényét, hogy ne kelljen a beolvasási kódot megismételni12. . A beviteli mező programja ugyanaz, mint az edtFile_textChanged() volt kiegészítve a beolvasás gomb feltételes aktívvá tételével. A megjelenítés gombbal itt nem foglalkozunk: void GrafikaQTvel::on_edtimageFile_textChanged(QString s) { bool bEnable = !s.isEmpty() && QFile::exists(s); ui.btnImageDisplay->setEnabled(bEnable); 11
Egy kereskedelmi forgalomba kerülő programban minden kép típushoz csak egy bejegyzés tartozna, itt egyszerűsítettünk. 12 Attól még, hogy a gomb inaktív a SLOT függvénye programból használható.
Programozás 3
14
2016
}
A Canvas osztály módosítása Egészítsük ki tehát a Canvas osztályt képek kezelésére! A fentiek szerint két QImage-re van szükségünk. Adjunk hozzá két QImage-et, egyet (_loadImege) a betöltött kép tárolására, a másikat (_actImage) az aktuális megjelenítéshez a private részhez: QImage _loadedImage; QImage _actImage;
// lemezről betöltött eredeti kép // aktuális kép