Grafikus C# – Windows Forms tanfolyam › 9.1 lecke Windows Forms · 9.1 lecke · képek A 1.12 leckében a PictureBox, Image, Bitmap és képbetöltés
PictureBox alapjait már megismerted. A 9. fejezetben a képekkel és a rajzolással mélyebben foglalkozunk. Ebben a leckében a képek betöltését és megjelenítését tanulod meg: a SizeMode beállításait, az Image és a Bitmap osztály különbségét, a képbetöltés csapdáit (zárolt fájl, OutOfMemoryException, nem támogatott formátum), a vágólapról és a húzással érkező képeket, és az erőforrásból betöltött ábrákat.
A lecke végére
- a
PictureBoxSizeModeértékeit a feladathoz igazítod; - különbséget teszel
ImageésBitmapközött, és újBitmapot hozol létre; - képet töltesz be a fájl zárolása nélkül (másolat), és kezeled a hibákat;
- ismered a támogatott formátumokat, és tudod, mit tehetsz egy nem támogatottnál;
- képet veszel át a vágólapról, húzással és az erőforrásokból (
Properties.Resources); - kiolvasod a kép adatait (méret, formátum, felbontás).
Mielőtt elkezded
Ehhez a leckéhez az 1.12 lecke (PictureBox, ImageList), a 7.8 lecke (OpenFileDialog) és a 7.4 lecke (MessageBox) szükséges.
A PictureBox és a SizeMode
| SizeMode | Viselkedés | Mikor? |
|---|---|---|
Normal | Eredeti méret, bal felső sarokból; ami nem fér ki, levágódik. | Pontos, pixelre eső megjelenítés. |
StretchImage | A képet a doboz méretére nyújtja (az arány torzulhat). | Ritkán: csak ha az arány nem számít. |
Zoom | Arányosan nagyítja vagy kicsinyíti a dobozba (az üres rész marad). | Képnézegető, előnézet (a leggyakoribb). |
CenterImage | Eredeti méretben középre teszi, a túlnyúló részt levágja. | Ikonok, kis ábrák. |
AutoSize | A doboz a kép méretére nő. | Ha a doboz igazodik a képhez. |
pbKep.SizeMode = PictureBoxSizeMode.Zoom; // arányos beillesztés
pbKep.BackColor = Color.WhiteSmoke; // a Zoom üres sávjainak színe
pbKep.BorderStyle = BorderStyle.FixedSingle;
// az Image tulajdonság: kész kép (Image példány) megjelenítése
pbKep.Image = bitmap;
// az ImageLocation: útvonalból tölt (a PictureBox maga olvassa be); Load és LoadAsync is van
pbKep.ImageLocation = utvonal;
pbKep.LoadCompleted += (s, e) =>
{
if (e.Error != null) { lblInfo.Text = "A kép nem tölthető be."; }
};Image tulajdonságnak kész képet adsz. Az ImageLocation útvonalat (vagy webcímet), amelyet a doboz maga tölt be, akár a háttérben (LoadAsync). A hibát a LoadCompleted esemény adja.Zoom arányosan illeszt, ezért a doboz egyik oldalán üres sáv marad: állíts neki jó háttérszínt (BackColor).PictureBox a képet nem módosítja: a nagyítás és a kicsinyítés csak a megjelenítésre vonatkozik. A kép tényleges átméretezése a 9.2 lecke témája.PictureBox Dock = Fill vagy Anchor beállítása és a Zoom együtt adja a jó viselkedést (6.2 lecke).Jósolj!
A PictureBox mérete 400 × 200, a kép 100 × 100 képpontos, a SizeMode értéke Zoom. Mekkora lesz a kép a képernyőn, és hol?
Jóslat ellenőrzése
200 × 200 képpontos (a doboz magassága szab határt, az arány megmarad), a doboz közepén, két oldalán 100–100 képpontos üres sávval. A Zoom a kis képet is nagyítja (életlenebb lehet).
Image és Bitmap: mi a különbség?
Az Image az absztrakt ősosztály (bármilyen kép), a Bitmap a képpontokból álló kép. Rajzoláshoz és szerkesztéshez Bitmap kell. Új, üres Bitmap a méretével jön létre, a fájlból betöltött is átalakítható:
// 1. üres vászon: méret megadásával (a képpontok átlátszó feketék)
Bitmap vaszon = new Bitmap(400, 300);
// 2. másolat egy meglévő képről (önálló, a forrástól független)
Bitmap masolat = new Bitmap(forrasKep);
// kép adatai
lblInfo.Text = masolat.Width + " × " + masolat.Height + " képpont, "
+ masolat.PixelFormat + ", "
+ masolat.HorizontalResolution.ToString("0") + " dpi";
// egy képpont színe (lassú, csak kis képen vagy kevés pontra)
Color szin = masolat.GetPixel(10, 10);
masolat.SetPixel(10, 10, Color.Red);
// a formátum felismerése a RawFormat tulajdonsággal
string formatum = "ismeretlen";
if (forrasKep.RawFormat.Equals(ImageFormat.Png)) { formatum = "PNG"; }
else if (forrasKep.RawFormat.Equals(ImageFormat.Jpeg)) { formatum = "JPEG"; }
else if (forrasKep.RawFormat.Equals(ImageFormat.Gif)) { formatum = "GIF"; }
else if (forrasKep.RawFormat.Equals(ImageFormat.Bmp)) { formatum = "BMP"; }Width és Height képpontban adott. A HorizontalResolution (dpi) a nyomtatáshoz fontos, a képernyőn a pixel számít.LockBits kell (haladó téma).Format32bppArgb: átlátszósággal, Format24bppRgb: nélküle). A JPEG nem tárol átlátszóságot.Jósolj!
Egy JPEG-ből betöltött kép PixelFormat értéke Format24bppRgb. A kódod SetPixel(10, 10, Color.FromArgb(0, 255, 0, 0)) hívással átlátszó pontot próbál beállítani. Mi látszik a képen?
Jóslat ellenőrzése
A pont nem lesz átlátszó: az alfa csatornát nem tároló formátum eldobja az átlátszóságot (piros vagy fekete pont jelenik meg). Ha átlátszóság kell, új Bitmapot hozz létre Format32bppArgb formátummal, és arra rajzolj.
Biztonságos képbetöltés
A legegyszerűbb betöltés (Image.FromFile(utvonal)) két ismert hibát hoz: (1) a kép zárolja a fájlt, amíg az Image él, ezért nem törölhető, nem írható felül (a saját programodból sem); (2) érvénytelen vagy nem támogatott kép esetén OutOfMemoryException kivételt dob (a név félrevezető: nem a memória fogyott el). A megoldás: a kép betöltése, másolat készítése, a forrás azonnali felszabadítása, és try–catch:
// zárolás nélküli betöltés: a fájl azonnal szabad, a visszaadott Bitmap önálló
private Bitmap KepBetolt(string utvonal, out string hiba)
{
hiba = "";
try
{
using (Image forras = Image.FromFile(utvonal))
{
return new Bitmap(forras); // a másolat nem hivatkozik a fájlra
}
}
catch (OutOfMemoryException)
{
hiba = "A fájl nem érvényes vagy nem támogatott képformátum.";
}
catch (FileNotFoundException)
{
hiba = "A fájl nem található.";
}
catch (IOException ex)
{
hiba = "A fájl nem olvasható: " + ex.Message;
}
catch (UnauthorizedAccessException)
{
hiba = "Nincs jogosultság a fájl olvasásához.";
}
return null;
}
// a megjelenítés: a régi kép felszabadítása az újra cserélés előtt (9.8 lecke)
private void Mutat(Bitmap uj)
{
Image regi = pbKep.Image;
pbKep.Image = uj;
if (regi != null)
{
regi.Dispose(); // csak az új kép beállítása UTÁN
}
}new Bitmap(forras)) a képpontokat a memóriába viszi, így a forrás szabadítható.using a forrás Image-et felszabadítja, a másolat él tovább. Nagy képnél a másolás memóriát és időt igényel: ezt a 9.8 lecke részletezi.PictureBox a régi képet nem szabadítja fel: ha nem Dispose-olod, a memória nő, amíg a szemétgyűjtő nem dolgozik. Előbb az újat állítsd be, utána szabadítsd a régit.Jósolj!
A kódod pbKep.Image = Image.FromFile(utvonal) módon tölt, majd a felhasználó a Törlés gombra kattintva törölné a fájlt (File.Delete(utvonal)), amíg a kép látszik. Mi történik?
Jóslat ellenőrzése
IOException (a fájlt másik folyamat használja): a betöltött kép zárolja a fájlt, a saját programod miatt. A másolattal betöltött képnél a törlés működik.
Vágólap, húzás és erőforrás
// 1. kép a vágólapról (Ctrl+V)
private void Beillesztes()
{
if (Clipboard.ContainsImage())
{
Mutat(new Bitmap(Clipboard.GetImage())); // másolat: a vágólap képe nem a miénk
}
}
// 2. húzás az ablakra (AllowDrop = true a Formon)
private void Form1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] utak = (string[])e.Data.GetData(DataFormats.FileDrop);
string hiba;
Bitmap kep = KepBetolt(utak[0], out hiba);
if (kep != null) { Mutat(kep); } else { lblInfo.Text = hiba; }
}
// 3. a projekt erőforrásából (Properties → Resources → Add Existing File)
pbLogo.Image = Properties.Resources.logo; // a név az erőforrás neve; futás közben a programba ágyazva vanClipboard.GetImage() a vágólapon lévő képet adja (másik program képét is). A ContainsImage() előbb megmondja, van-e ott kép.FileDrop formátum a fájlok útvonalának tömbjét adja. A húzott fájl bármi lehet: a KepBetolt hibakezelése itt is kell.Properties.Resources.név minden hívásra új példányt ad: ne hívd ciklusban, tedd változóba.PictureBox.LoadAsync(url) webcímről is tölt (a háttérben). Idegen internetes forrás képét óvatosan kezeld; a hibát a LoadCompleted adja.Jósolj!
A Paint vagy egy időzítő minden másodpercben a pbKep.Image = Properties.Resources.logo; sort hajtja végre. Mi történik 10 perc alatt a program memóriájával?
Jóslat ellenőrzése
A memória folyamatosan nő: a Resources.logo minden hívása új Bitmapot készít, és a régit senki nem szabadítja fel (Dispose). Egyszer töltsd változóba, és azt használd.
Mit tegyél ide: a képnézegető ablak egy képpel (Zoom), a kép adataival és a „Kép beillesztve a vágólapról” üzenettel.Javasolt fájlnév: winforms-9-1-kepnezegeto.webp · Alt szöveg: A képnézegető program
Hibakeresés: te vagy a hibadetektív
Mi a baj, és hogyan javítod?
Gondold végig az okot, és csak utána nyisd le a megoldást.
1. OutOfMemoryException, pedig van szabad memória
pbKep.Image = Image.FromFile("jegyzet.txt"); // nem képHiba és javítás
A GDI+ ezt a kivételt dobja érvénytelen képfájlnál. Védd try–catch blokkal, és mondd meg a felhasználónak: a fájl nem támogatott képformátum.
2. A fájl nem törölhető, mert „használatban van”
A kép megjelenítése után a program nem tudja átnevezni vagy törölni a fájlt. Az Ok és javítás
Image.FromFile zárolja a fájlt. Töltsd be másolattal (new Bitmap(forras)), és szabadítsd a forrást (using).
3. Piros X a PictureBox-ban
using (Bitmap kep = new Bitmap(200, 100))
{
pbKep.Image = kep; // a using vége felszabadítja a megjelenített képet
}Hiba és javítás
A using a blokk végén megsemmisíti a képet, amelyet a PictureBox még használ: a következő rajzoláskor piros X (vagy kivétel) jelenik meg. A megjelenített képet ne szabadítsd fel; csak a régit, az új beállítása után.
4. A kép torzult
A kép megnyúlt a dobozban. A Ok és javítás
SizeMode értéke StretchImage. Használd a Zoom módot (arány megtartása).
5. Nő a memóriahasználat új kép betöltésekor
Sok kép megnyitása után a program lassul. A régi képet nem szabadítod fel. Az új kép beállítása után hívd a régi Ok és javítás
Dispose() metódusát (lásd a Mutat metódust).
6. A WebP képet nem nyitja meg
A felhasználó .webp fájlt nyit meg, és hibát kap. A GDI+ nem támogatja a WebP formátumot. Jelezd érthetően (ez a formátum nem támogatott), vagy használj külső könyvtárat (NuGet), illetve kérd az átalakítást PNG-be.Ok és javítás
Mini projekt: képnézegető
Készíts egyszerű képnézegetőt:
- Felület:
pbKep(Dock = Fill,SizeMode = Zoom,BackColorvilágosszürke), alulFlowLayoutPanela gombokkal: Megnyitás..., Előző, Következő, Beillesztés; acmbModaSizeModekiválasztásához (Zoom, Nyújtás, Eredeti méret, Középre);lblInfoaz állapotsorban. - Megnyitás: az
OpenFileDialog(Multiselect = true, szűrő: Képek (*.png;*.jpg;*.jpeg;*.bmp;*.gif)) a kiválasztott fájlokat egy listába (List<string>) teszi; az első jelenik meg. - Léptetés: Előző és Következő (a lista végén körbe); a ← és → billentyű is (
ProcessCmdKeyvagyKeyPreview, 5.4 lecke). - Betöltés zárolás nélkül: a
KepBetoltmetódus másolatot ad; a hibákat (nem támogatott, hiányzó, jogosultság) az állapotsor jelzi, és a program a következő képre léphet. - Adatok: az
lblInfomutatja a fájl nevét, méretét képpontban, a fájlméretet (KB), a formátumot és a sorszámot (3 / 12). - Vágólap és húzás: Ctrl+V beilleszti a vágólap képét (Beillesztett kép felirattal); a képfájl ablakra húzása megnyitja a fájlokat.
- Felszabadítás: új kép beállítása után a régi
Dispose; a program zárásakor a megjelenített kép is. - Teszteld: több kép, nem képfájl (.txt átnevezve .png-re), nagy kép, fájl törlése megjelenítés közben (a másolat miatt működik), WebP, vágólapról beillesztés, húzás, a
SizeModemódok.
Megoldás megnyitása (próbáld ki előbb önállóan!)
A képfájlok listája és az aktuális index kezeli a léptetést; a kép megjelenítése a Mutat metóduson át történik, amely a régit felszabadítja.
private List<string> fajlok = new List<string>();
private int index = -1;
private void Form1_Load(object sender, EventArgs e)
{
this.AllowDrop = true;
this.KeyPreview = true;
cmbMod.Items.AddRange(new object[] { "Zoom", "Nyújtás", "Eredeti méret", "Középre" });
cmbMod.SelectedIndex = 0;
ofd.Filter = "Képek (*.png;*.jpg;*.jpeg;*.bmp;*.gif)|*.png;*.jpg;*.jpeg;*.bmp;*.gif|Minden fájl (*.*)|*.*";
ofd.Multiselect = true;
}
private Bitmap KepBetolt(string utvonal, out string hiba)
{
hiba = "";
try
{
using (Image forras = Image.FromFile(utvonal))
{
return new Bitmap(forras);
}
}
catch (OutOfMemoryException) { hiba = "Nem érvényes vagy nem támogatott kép: " + Path.GetFileName(utvonal); }
catch (FileNotFoundException) { hiba = "A fájl nem található: " + Path.GetFileName(utvonal); }
catch (IOException ex) { hiba = "A fájl nem olvasható: " + ex.Message; }
catch (UnauthorizedAccessException) { hiba = "Nincs jogosultság: " + Path.GetFileName(utvonal); }
return null;
}
private void Mutat(Bitmap uj)
{
Image regi = pbKep.Image;
pbKep.Image = uj;
if (regi != null) { regi.Dispose(); }
}
private string Formatum(Image kep)
{
if (kep.RawFormat.Equals(ImageFormat.Png)) { return "PNG"; }
if (kep.RawFormat.Equals(ImageFormat.Jpeg)) { return "JPEG"; }
if (kep.RawFormat.Equals(ImageFormat.Gif)) { return "GIF"; }
if (kep.RawFormat.Equals(ImageFormat.Bmp)) { return "BMP"; }
return "egyéb";
}
private void Megjelenit(int ujIndex)
{
if (fajlok.Count == 0) { return; }
// legfeljebb egyszer körbe: a hibás fájlokat átugorjuk
for (int probalkozas = 0; probalkozas < fajlok.Count; probalkozas++)
{
int i = ((ujIndex + probalkozas) % fajlok.Count + fajlok.Count) % fajlok.Count;
string hiba;
Bitmap kep;
string utvonal = fajlok[i];
kep = KepBetolt(utvonal, out hiba);
if (kep != null)
{
index = i;
Mutat(kep);
long meret = new FileInfo(utvonal).Length;
lblInfo.Text = Path.GetFileName(utvonal) + " – " + kep.Width + " × " + kep.Height + " képpont, " + Formatum(kep) + ", " + (meret / 1024) + " KB (" + (index + 1) + " / " + fajlok.Count + ")";
return;
}
lblInfo.Text = hiba;
}
}
private void btnMegnyit_Click(object sender, EventArgs e)
{
if (ofd.ShowDialog(this) == DialogResult.OK)
{
fajlok = new List<string>(ofd.FileNames);
Megjelenit(0);
}
}
private void btnKovetkezo_Click(object sender, EventArgs e) { Megjelenit(index + 1); }
private void btnElozo_Click(object sender, EventArgs e) { Megjelenit(index - 1); }
private void cmbMod_SelectedIndexChanged(object sender, EventArgs e)
{
PictureBoxSizeMode[] modok = { PictureBoxSizeMode.Zoom, PictureBoxSizeMode.StretchImage, PictureBoxSizeMode.Normal, PictureBoxSizeMode.CenterImage };
pbKep.SizeMode = modok[cmbMod.SelectedIndex];
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Right) { btnKovetkezo.PerformClick(); e.Handled = true; }
else if (e.KeyCode == Keys.Left) { btnElozo.PerformClick(); e.Handled = true; }
else if (e.Control && e.KeyCode == Keys.V) { btnBeillesztes.PerformClick(); e.Handled = true; }
}
private void btnBeillesztes_Click(object sender, EventArgs e)
{
if (Clipboard.ContainsImage())
{
Mutat(new Bitmap(Clipboard.GetImage()));
lblInfo.Text = "Beillesztett kép a vágólapról.";
}
else
{
lblInfo.Text = "A vágólapon nincs kép.";
}
}
private void Form1_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
}
private void Form1_DragDrop(object sender, DragEventArgs e)
{
fajlok = new List<string>((string[])e.Data.GetData(DataFormats.FileDrop));
Megjelenit(0);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
if (pbKep.Image != null) { pbKep.Image.Dispose(); }
}Mit tegyél ide: a kész képnézegető egy fényképpel, a gombokkal és az adatsorral.Javasolt fájlnév: winforms-9-1-kesz.webp · Alt szöveg: A kész képnézegető
Három önálló gyakorlófeladat
Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.
1. Kép színe egérkattintásra
A felhasználó a képre kattint, és a program kiírja a kattintott képpont színét (RGB). A PictureBox Zoom módban van: hogyan számolod a kép koordinátáját?Egy lehetséges megoldás
Zoom módban az egér koordinátáját a megjelenítési arányból és az eltolásból kell visszaszámolni (a 9.5 lecke). Egyszerűbb: Normal módban a koordináta közvetlenül a kép koordinátája.private void pbKep_MouseClick(object sender, MouseEventArgs e)
{
Bitmap kep = pbKep.Image as Bitmap;
// Normal módban: e.X és e.Y a kép pontja (ha a kép kisebb a doboznál, ellenőrizzük a határt)
if (kep != null && e.X < kep.Width && e.Y < kep.Height)
{
Color c = kep.GetPixel(e.X, e.Y);
lblSzin.Text = "RGB(" + c.R + ", " + c.G + ", " + c.B + ")";
pnlSzin.BackColor = c;
}
}
2. Üres vászon létrehozása
Az Új kép gomb 400 × 300 képpontos fehér A Bitmapot hoz létre. Hogyan töltöd fehérre (a Bitmap alapból átlátszó fekete)?Egy lehetséges megoldás
Graphics.FromImage segítségével a Clear(Color.White) metódussal (9.3 lecke), using blokkban.Bitmap vaszon = new Bitmap(400, 300);
using (Graphics g = Graphics.FromImage(vaszon))
{
g.Clear(Color.White);
}
Mutat(vaszon);
3. Kép adatai egy ablakban
A Tulajdonságok gomb egy modális ablakban mutatja a kép adatait (méret, formátum, felbontás, fájlméret). Hogyan adod át az adatot (7.7 lecke)? Az adatokat szövegként (vagy kis adatosztályban) a konstruktor kapja, az ablak csak megjeleníti. A Egy lehetséges megoldás
Bitmapot ne add át az ablaknak (így nem keveredik a felszabadításuk).
Gyakorlótár: 6 további feladat
Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.
Alap szint
1. SizeMode választás
Melyik (a) SizeMode: (a) fényképek előnézete; (b) 16 × 16-os ikon középen; (c) a doboz igazodjon a képhez?Megoldás megnyitása
Zoom; (b) CenterImage; (c) AutoSize.
2. Mi a különbség?
Mi a különbség az Az Image.FromFile és a new Bitmap(Image.FromFile(...)) között a fájlzárolás szempontjából?Megoldás megnyitása
Image.FromFile által adott kép zárolja a fájlt, amíg él. A másolat (new Bitmap(...)) önálló: a forrás Dispose hívása után a fájl szabad. (A másolat készítésénél a forrást using blokkal kell szabadítani.)
Közepes szint
3. Fájlméret olvasható alakban
A fájlméretet B, KB, MB egységben írd ki. Hol van ilyen metódus korábbról? A 7.8 lecke Megoldás megnyitása
Meret(long) metódusa: a 1024-gyel osztás ciklusa.
4. Kép mentése másként
A megjelenített képet PNG-ként mentenéd. Melyik metódust használod, és mire kell vigyáznod? Az Megoldás megnyitása
Image.Save(útvonal, ImageFormat.Png) metódust (részletek a 9.2 leckében). Ne ugyanarra a fájlra mentsd, amelyből a kép betöltődött, ha a kép zárolja (a másolatos betöltés ezt megszünteti).
Kihívás szint
5. Mappa képeinek bélyegképei
Egy mappa képeit kis (96 pixel) bélyegképként mutasd Mindegyik bélyegkép külön FlowLayoutPanelben. Mire kell figyelned a memória miatt?Megoldás megnyitása
Bitmap, ezért a mappa váltásakor az összes régit fel kell szabadítani (Dispose), a nagy eredeti képeket pedig csak a bélyegkép elkészítéséig tartani (9.2 és 9.8 lecke).
6. Lassú kép betöltése a háttérben
Egy hálózati meghajtón lévő nagy képet a felület lefagyása nélkül töltenél be. Mi a megoldás elve? A betöltés háttérszálon (Megoldás megnyitása
Task.Run), az eredmény megjelenítése a felület szálán (await, 11. fejezet). Addig a PictureBox.LoadAsync is használható útvonalra.
Gyors önellenőrzés
Válaszolj fejben, és csak utána nyisd le a választ. A Az A GDI+ lustán olvassa a fájlt, ezért nyitva tartja; másolattal oldható meg. Általában: a fájl nem érvényes vagy nem támogatott képformátum. BMP, JPEG, PNG, GIF, TIFF (a WebP-t nem). Az új kép beállítása után ( Minden hívás új 1. Melyik SizeMode tartja meg az arányt?
Zoom (és az eredeti méretű Normal, CenterImage); a StretchImage torzít.2. Mi az Image és a Bitmap viszonya?
Image az ősosztály, a Bitmap képpontokból álló, szerkeszthető kép.3. Miért zárolja a fájlt az Image.FromFile?
4. Mit jelent a OutOfMemoryException képbetöltéskor?
5. Melyik képformátumokat támogatja a GDI+?
6. Mikor szabadítod fel a régi képet?
Dispose), különben a megjelenített kép megsemmisülne.7. Miért veszélyes a Properties.Resources.kép ciklusban?
Bitmapot készít: változóba kell tenni.
Mit tudsz már?
- A
PictureBoxmódjait feladathoz igazítod. - Különbséget teszel
ImageésBitmapközött, és új vásznat hozol létre. - Képet töltesz be zárolás nélkül, hibatűrően.
- Képet veszel át a vágólapról, húzással és az erőforrásból.
- A régi képeket felszabadítod, és elkerülöd a gyakori hibákat.
Következő lecke: Képek igazítása, méretezése és mentése
A kép tényleges átméretezése jó minőségben, forgatás, tükrözés, vágás és mentés különböző formátumokban.



