Bitmapa – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Bitmapa – .NET – Fórum – Programujte.comBitmapa – .NET – Fórum – Programujte.com

 

Martin
~ Anonymní uživatel
1600 příspěvků
7. 2. 2010   #1
-
0
-

Ako vykreslit velku bitmapu (8000x6000) v C# tak aby to nebolo pomale? Chcem ju prezerat v okne, ale jej posuvanie je hrozne pomale.

Nahlásit jako SPAM
IP: 213.181.128.–
dannyk0
Věrný člen
7. 2. 2010   #2
-
0
-

PictureBox na tohle neni staveny. Ja bych se poohledl po nejakem reseni pres DirectX, OpenGL nebo neco podobneho. Podle me zadna klasicka GDI komponenta tohle zvladat poradne nebude.

Nahlásit jako SPAM
IP: 85.135.97.–
Jedu v c++,c#,assembler,ASP.NET,PHP,databaze,bezpecnost softwaru[br] -----------------------------------------------------------[br] Muj blog o programovani,hudbe a vsem moznem,co najdu na netu :) [br] http://dannyk.aspone.cz[br] -----------------------------------------------------------[br] Na foru mam nejake prispevky pod nickem Master,tak jen pro upresneni :)
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
7. 2. 2010   #3
-
0
-

To dannyk : No ok, ale napr. v Skicari alebo v Paint.NET (ktory je robeny v C#) ide posuvanie aj obrovskych obrazkov plynule a tie programi zrejme pouzivaju len GDI. Ci sa mylim?

Nahlásit jako SPAM
IP: 213.181.128.–
dannyk0
Věrný člen
7. 2. 2010   #4
-
0
-

Fakticky netusim, mozna by pomohlo u PictureBoxu pouzit DoubleBuffering, ale zvysi to pametovou narocnost, ovsem mohlo by to vyresit ten problem. Nicmene celkove bych se poohlidl po nejakem jinem reseni na Google.

Jeste me napada jedna moznost, a to primo vykreslovat do nejakeho rectangle. Ale jak na to musis pohledat.

Nahlásit jako SPAM
IP: 85.135.97.–
Jedu v c++,c#,assembler,ASP.NET,PHP,databaze,bezpecnost softwaru[br] -----------------------------------------------------------[br] Muj blog o programovani,hudbe a vsem moznem,co najdu na netu :) [br] http://dannyk.aspone.cz[br] -----------------------------------------------------------[br] Na foru mam nejake prispevky pod nickem Master,tak jen pro upresneni :)
liborb
~ Redaktor
+18
Guru
8. 2. 2010   #5
-
0
-

Tak jako tak si musíš bitmapu natáhnout do paměti. Takže o paměť se strachovat nemusíš. A pak vykresluj jenom požadovanou část (výřez). V C# jsem takovou věc neřešil, takže nevím, jestli je tam pro to nějaká přímá podpora (letmo jsem nahlédl do MSDN a našel DrawCachedBitmap, ale má nějak málo parametrů :smile1: ). Ve Win32 s pomocí GDI by se to řešilo načtením bitmapy, vytvoření MemoryDC a při vykreslování by se dělal pouze BitBlt výřezu (což je opravdu rychlé). Můžeš to použít i v tvém programu, ale pokud to chceš čislě v C#, tak musíš pohledat.

Nahlásit jako SPAM
IP: 85.207.166.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
8. 2. 2010   #6
-
0
-

To liborb : Robim to asi takto:
Najskor si vytvorim Bitmapu:

bm = new Bitmap(4000, 3000);
Graphics gr = Graphics.FromImage(bm);
gr.Clear(Color.White);
gr.Dispose();

Do tejto Bitmapy sa kresli, podobne ako v skicary ciary a pod. a bitmapa sa vykresluje v panely.

Rectangle vysec = new Rectangle(new Point(panel1.AutoScrollPosition.Y*(-1), panel1.AutoScrollPosition.X*(-1)), new Size(panel1.Width, panel1.Height));
Rectangle cast = new Rectangle();
cast = vysec;
cast.X = 0;
cast.Y = 0;
Graphics grfx = e.Graphics;
panel1.AutoScrollMinSize = bm.Size;
grfx.DrawImage(bm,cast, vysec, GraphicsUnit.Pixel);
grfx.Dispose();

vykresluje sa len cast nie cela bitmapa, a je to pomale ako keby som ju vykresloval rovno celu...
Nemam moc skusenosti co sa taky takychto narocnejsich veci s grafikou, neviem ako by som to urobil rychlejsim ...

Nahlásit jako SPAM
IP: 213.181.128.–
liborb
~ Redaktor
+18
Guru
8. 2. 2010   #7
-
0
-

Než do toho zabředneme :smile1: , zkus použít DrawImageUnscaled nebo DrawImageUnscaledAndClipped. Třeba se to zlepší na přijetelnou úroveň. Jinak buď DirectX nebo cestou, kterou jsem popsal výše.

Nahlásit jako SPAM
IP: 85.207.166.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
8. 2. 2010   #8
-
0
-

To liborb : Nepmohlo to, ide to stale rovnako. A DirectX vobec neovladam, akurat tak trosicka XNA a openGL,SDL pod C++, ten prvy sposob sa mi celkom poydava len by som potreboval nejaku ukazku zdrojoveho kodu...

Nahlásit jako SPAM
IP: 213.181.128.–
liborb
~ Redaktor
+18
Guru
9. 2. 2010   #9
-
0
-

Nu dobrá, tak to zkus přes BitBlt. Nejprve potřebuješ importovat použité funkce:



[DllImport("gdi32.DLL")]
static extern Boolean BitBlt(IntPtr hdcDest, Int32 nXDest, Int32 nYDest, Int32 nWidth, Int32 nHeight, IntPtr hdcSrc, Int32 nXSrc, Int32 nYSrc, UInt32 dwRop);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool DeleteDC(IntPtr hdc);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

[DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
static extern bool DeleteObject(IntPtr hObject);


jednu konstantu a 2 proměnné:



private const UInt32 SRCCOPY = 0x00CC0020;

IntPtr pSource;
IntPtr pOrig;



Načteš bitmapu (bmp) jako předtím. Při prvním vykreslení si vytvoříš MemoryDC a přiřadíš mu svojí bitmapu:



//OnPaint(PaintEventArgs e)

IntPtr pTarget = e.Graphics.GetHdc();

if (pSource == IntPtr.Zero) {
pSource = CreateCompatibleDC(pTarget);
pOrig = SelectObject(pSource, bmp.GetHbitmap());
}


následně už můžeš vykreslovat přes BitBlt (co znamenají ty čísla si najdeš v dokumentaci):


BitBlt(pTarget, 0, 0, 100, 100, pSource, 0, 0, SRCCOPY);


a nakonec vykreslení nesmíš zapomenout uvolnit získané HDC:


e.Graphics.ReleaseHdc(pTarget);


A samozřejmě musíš v Dispose uvolnit alokované zdroje:


IntPtr pNew = SelectObject(pSource, pOrig);
DeleteObject(pNew);
DeleteDC(pSource);

Nahlásit jako SPAM
IP: 85.207.166.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
9. 2. 2010   #10
-
0
-

To liborb : Moc to pomohlo, je to velmi rychle. Dik za pomoc ;)

Nahlásit jako SPAM
IP: 213.181.128.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
9. 2. 2010   #11
-
0
-

To liborb : A este jedna otazka. Ako data naspat vratim Bitmape? Pokial otvorim Bitmapu len na citanie tak to staci ale ked do nej nieco vykreslim a chcem to ulozit na disk tak mi ulozi len stav Bitmapy uplne na zaciatku.

Nahlásit jako SPAM
IP: 213.181.128.–
liborb
~ Redaktor
+18
Guru
9. 2. 2010   #12
-
0
-

Kreslit musíš do DC pSource, ale to už si asi zjistil, tj. budeš modifikovat bitmapu. A jak ji pak uložíš? To už to asi musíš s Win32 API funkcema dotáhnout až do konce :smile1: .

bmp.GetHbitmap() vrací handle bitmapy a spolu s pSource se ti hodí k použití funkce GetDIBits http://msdn.microsoft.com/en-us/library/dd144879%28VS.85%29.aspx (je tam dokonce i příklad na uložení). Samozřejmě ji musíš naimportovat jako ty předchozí atd. atd.

Nahlásit jako SPAM
IP: 85.207.166.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
9. 2. 2010   #13
-
0
-

To liborb : Vyriesil som to pomerne jednoducho:
IntPtr pNew = SelectObject(pSource, pOrig);
bm = System.Drawing.Bitmap.FromHbitmap(pNew);
bm.Save(@"C:\test.bmp");

Jeden problem som vyriesil a prisiel zase druhy... Ked mam velmi velku bitmapu (8000x6000) tak mi pri pokuse o :

BitmapData bd = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

Vypise kompilator chybu, ze "Out of memory", neviem kde je problem, asi dana funkcia nedokaze pracovat s takymi velkymi udajmy...

Nahlásit jako SPAM
IP: 213.181.128.–
liborb
~ Redaktor
+18
Guru
10. 2. 2010   #14
-
0
-

LockBits je vlastně ekvivalent k GetDIBits. Otázka je, jestli musíš přistupovat ke všem datům naráz, jestli by nestačilo vždy jen několik řádek.

Nahlásit jako SPAM
IP: 85.207.166.–
Anonymní uživatel
~ Anonymní uživatel
0 příspěvků
11. 2. 2010   #15
-
0
-

To liborb : No to bude isto tym. A este taka malicka otazka, dalo by sa nejako vytvorit premennu typu IntPtr a do nej ulozit hodnotu pSource?, to preto aby som mohol si zapamatat stav bitmapy v urcitom okamihu, ked som skusal napr. IntPtr cache = pSource; tak to neslo, rovnako tiez metodou BitBlt(cache, 0, 0, 100, 100, pSource, 0, 0, SRCCOPY);

Nahlásit jako SPAM
IP: 213.181.128.–
liborb
~ Redaktor
+18
Guru
12. 2. 2010   #16
-
0
-

pSource je vlastně HBITMAP. Je to "jenom" handle, nejsou to ty data. Takže cache = pSource neudělá vlastně nic. Přes BitBlt by to šlo, ale to by sis musel vytvořit "záložní" bitmapu (ve Win32 CreateCompatibleBitmap), vytvořit si zase HDC, přiřadit jí tuhle novou bitmapu a pak by si mohl udělat BitBlt.

Pokud si chtěl zálohu dat, tak přes ten LockBits to bylo správně.

Ovšem opět stejná otázka, je nutné dělat kopii celého toho billboardu, co máš místo "normální" bitmapy? :smile1:
Proč to vlastně chceš udělat? Pro různé varianty jsou různé možnosti ....

Nahlásit jako SPAM
IP: 85.207.166.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 37 hostů

Podobná vlákna

Bitmapa do nekolika MovieClip — založil Martin

Binární data - bitmapa — založil Petrr

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý