Vlákno názorů k článku Grafický formát BMP - používaný a přitom neoblíbený od Ray - Jesli jsem to v clanku prehledl tak sorry,...

  • Článek je starý, nové názory již nelze přidávat.
  • 19. 10. 2006 8:04

    Ray (neregistrovaný)
    Jesli jsem to v clanku prehledl tak sorry, ale to ze se do WinAPI obrazek musi davat vertikalne otoceny neni tak uplne pravda. Pro radu (asi i vetsinu) funknci se mu da zadat 'zaporna' vyska, tedy -100 napriklad, a pak se tech 100 scan radku zadava 'normalnim' zpusobem :) Je to popsane i nekde v SDK a cloveku tohle dokaze usetrit dost prace, protoze aby system bezel kvuly jednomu portu do widli 'obousmerne' stoji hrozne prace (sice mame makra, ale dost to zneprehledni kod). A pripadne live obraceni zace CPU...

    R.
  • 19. 10. 2006 9:14

    Pavel Tisnovsky (neregistrovaný)
    Ano, ale u nekterych funkci to stale dela problemy, zejmena u klasicke SetDIBitsToDevice(). U StretchDIBits() uz ne, ale zdrzeni zpusobene opacnym obrazkem je znacne. Moc dobre vim o cem mluvim, kdyz jsem zobrazoval video pomoci WinAPI, tak se "nucene" obraceny obrazek vykresloval tak 5x pomaleji, nez pri neobraceni. U CreateDIBSection() to obraceni vsak nefunguje vubec.
  • 19. 10. 2006 10:04

    Ray (neregistrovaný)
    A ktere API jsou uplne bez problemu ? Aneb neni nad rozsireni nekterych fci typu "| 1" u HANDLE typu.

    Ja jsem s nima problem nemel a byly i bezproblemove kompatibilni, a to zejmena prave tebuo zminovana SetDIBitsToDevice (~desitky tisic instalaci softu na vsech moznych i nemoznych win verzi). A co se tohodle toho tyce, tak nikdy nebyl reportovan zadny bug. Dokonce jsem nepozoroval ani zadny rychlosni rozdil.

    Docela by mne zajimaly detajly, ikdyz uz po WIN zas tak moc primarne neprogramuju. Jesli mas minutku, budu rad jesli se podelis :)

    R.
  • 19. 10. 2006 11:35

    Pavel Tisnovsky (neregistrovaný)
    Pravda, s WinAPI jsem take mel problemy, ale zejmena to bylo spatnou dokumentaci (typicky se v ni nepopisovaly mezni stavy a rozdily mezi ruznymi verzemi Windows).

    Problem se zobrazovanim je hlavne s tou rychlosti, nacital jsem video (pres nami vyvijenou PCI kartu pomoc bus-master prenosu) a zobrazoval pomoci WinAPI. Prvni problem je se zarovnanim obrazovych radku, ale to se da se skripenim zubu vyresit firmwarem na karte. Dale s obracenim obrazku, to karta nezvladne a musi se to resit volanim SetDIBitsToDevice. Mozna to bylo ovladaci, ale na technologickych PC bylo obraceni obrazku pres SetDIBitsToDevice opravdu dost pomale a nedarilo se zobrazovat cely video tok.

    Nakonec jsem obrazky obracel sam, ale dovedete si asi predstavit, co to v realu udela z cachkou :-(

    Nekde mam vysledky nejakych mereni, sice nejsem u sveho PC, ale zkusim to najit a tady odpublikovat.

    Spise teoreticky je problem se specifikaci obdelniku, ktery se ma vykreslovat - obrazek se sice vykresluje zdola nahoru, ale obdelnik je zadany presne naopak. Obrazky najdete v knizce Charlese Petzolda (asi se nesmi v elektronicke podobe distribuovat, ale zkuste google:"petzold .chm").
  • 19. 10. 2006 11:47

    Pavel Tisnovsky (neregistrovaný)

    Tak jsem ty vysledky konecne nasel, mrknete se na to:

    Operace                Funkce            1bpp 8bpp 24bpp
    Přímé zobrazení        SetDIBitsToDevice  493  344   47 
    Změna měřítka          StretchDIBits      142  252  128 
    Horizontální zrcadlení StretchDIBits       17   36   11 
    Vertikální zrcadlení   StretchDIBits       20   51   13 
    Přímé zobrazení        DrawDibDraw        493  344   49 
    Změna měřítka          DrawDibDraw        141  248  208 
    

    Je vypsan pocet zobrazeni bitmapy za sekundu na systemu Celeron 900MHZ, 256MB RAM, GeForce MX200, obrazky mely rozliseni 756x287 pixelu. Samozrejme nejpomalejsi je horizontalni zrcadleni, ale i vertikalni je o dost pomalejsi.

    Zajimave take je, ze DrawDibDraw() je stejne rychle jako SetDIBitsToDevice(), i kdyz by se podle dokumentace melo jednat o dost rychlejsi funkci.

  • 20. 10. 2006 19:58

    anonymní
    Zdravim :)

    Diky za tabulku, je zajimava. Jen dotaz hledne otoceni: Jednalo se o volani SetDIBitsToDevice nebo skutecne Stretch ? (byt 1:1)

    R.
  • 23. 10. 2006 9:42

    Pavel Tisnovsky (neregistrovaný)
    V tabulce je pouze StretchDIBits() a opravdu na to toto bylo testovano.
  • 22. 10. 2006 1:49

    K2 (neregistrovaný)
    Člověče nešťastná, GDI je na zobrazování videa zcela nevhodný nástroj. Když už to dělám, tak použiju BitBlt, který je i podle MSDN rychlejší, než SetDIBitsToDevice; nebo ještě lépe používám DDB. Ale správně je samozřejmě použít DirectDraw, resp. dnes Direct3D, což je o řád rychlejší. Kdyby přehrávače médií zobrazovaly přes GDI, moc multimédií bychom ve Windows neužili :)
  • 22. 10. 2006 22:33

    Pavel Tišnovský (neregistrovaný)
    To všechno samozřejmě vím, ale je zde několik "ale":

    - BitBlt nemůžu použít, protože nemám formát kompatibilní s platným kontextem. A použít něco na způsob CreateCompatibleBitmap a potom BitBlt vyjde ještě hůře než SetDIBitsToDevice. Na "rychlé" bitmapy jsou zde funkce začínající na Draw...., ale jak jsem ukázal na tabulkách, tak v našem případě jsou stejně rychlé, jako ty klasické WinAPI. Opakuji, bitmapy dostávám z PCI karty, s žádným DDB si hrát tedy nebudu, protože to stejné za mě udělá SetDIBitsToDevice.

    - můžete mi prosím ukázat, jak zobrazit bitmapu v našem formátu (740x287@grayscale) pomocí DirectX? Samozřejmě je možné nahodit grayscale/paletový grafický režim, ale to nebude fungovat na všech počítačích, resp. ne všechny drivery umí 8bpp, takže sice přímý přístup do obrazové paměti mám, ale samotná zobrazovací smyčka je pomalejší než ono haněné SetDIBitsToDevice. Nehledě na to, že "ruční" přepočet mi zatíží CPU a to je věc, které se prostě musím zbavit, vše potřebuju hodit na grafickou kartu.

    Nakonec mě připadlo nejjednodušší celé slavné Directy i GDI prostě obcházet a zapisovat přímo do obrazové paměti. Třeba pro průmyslové počítače to není problém, tam stejně nikomu nebude vadit, že se bude obrazová paměť natvrdo přepisovat. A driver pro takovouto blbůstku je trapně jednoduchý: stačí zjistit počáteční adresu Video RAM (ehm, stejně bývá konstantní) z konfiguračních registrů PCI a potom tam nahrnout pixely naprosto stejným způsobem jako v případě Directů (bez obezliček typu Lock apod.)
  • 23. 10. 2006 23:55

    K2 (neregistrovaný)
    Pokud mluvíme o průmyslových počítačích, tak není problém používat drivery, které 8bpp umí. Dále u DirectX se nabízí možnost použít textury ve formátu D3DFMT_P8 (8-bit color indexed).

    Přímý zápis do paměti by byla alternativa, tedy pokud driver umí 8bpp, jinak bude mít překlad velmi podobné problémy, jaké zmiňujete.
  • 24. 10. 2006 9:13

    Pavel Tišnovský
    Zlatý podporovatel
    No problem s temi drivery prave je, ja jsem ty pocitace nevybiral a pouzita deska mela nejaky Intelacky cipset, ktery i pri 8bpp mel mezi pixely padding. Ale to uz je jedno, zeptam se tedy jinak: dneska uz neni nutne, aby byla hodnota "lPitch" delitelna osmi? Pokud uz to neni podminkou (v dobe, kdy jsem na tomto projektu delal, se jeste pouzival samostatny DirectDraw), tak s Directy problem nebude.

    S tim primym zapisem mate naprostou pravdu, jedina vyhoda byla absence volani Lock/Unlock.
  • 24. 10. 2006 14:42

    K2 (neregistrovaný)
    lPitch se týká pouze DirectDraw, ale přiznám se, že detaily dynamických textur jsem nestudoval. Každopádně cokoliv bude rychlejší, než GDI.
    Doporučil bych se podívat na DirectX SDK.
  • 25. 10. 2006 9:52

    Pavel Tišnovský
    Zlatý podporovatel
    Prave ze ten problem s lPitch muze cele slavne Directy odstavit, resp. odstavit funkci Blt a BltFast.

    Ja jsem dostaval z PCI zarizeni video ve formatu 740x287 pixelu. S tim neni problem, driver mi zaridil ulozeni do kontinualni pameti, tj. za 740 pixelem 1 radku nasledoval 1 pixel ze druheho radku apod. Problem vsak je, ze takto vytvorenou pixmapu NENI DirectX schopen prenest pomoci Blt ci BltFast a to proto, ze lPitch neni delitelny 8, ale jen 4. Proto bych musel:

    a) celou pixmapu pomoci movu "rozsekat" na jednotlive radky a mezi ne vlozit 4 dorovnavaci byty. To mi vsak zatizi CPU, ktery je tam proto, aby nad bitmapou provadel nejake vypocty.

    b) budu pixmapu prenaset sam bez pouziti Blt a BltFast, to vsak prinasi stejny problem jako bod a), ale je pravda, ze zatizeni je o 50% mensi. Jedine, v cem mi tady Directy pomuzou, je nastaveni grafickeho rezimu a funkce Lock a Unlock.

    c) pouziju SetDIBitsToDevice, protoze ten vyzaduje zarovnani pouze na 4 byty (dword). Zatizeni CPU byva male (zalezi na driveru), ale nastava zde ten zminovany problem s otocenim pixmapy, popr. se zpomalenim pri otaceni.

    Idealni reseni v tomto pripade neexistuje, snad jen zmena rozliseni videa, resp. prenosu celeho problemu na FPGA, ktere se na PCI karte nachazi.
  • 26. 10. 2006 22:39

    K2 (neregistrovaný)
    Za daných okolností bych buď použil to Direct3D (a data bych mu dával jako dynamickou texturu), nebo bych opravdu bitmapu přenášel sám za pomocí DirectDraw (dnes už zastaralého, v DX tuším 8 už není). Výhodou DirectDraw oproti přímému zápisu do videopaměti je lock, absence problémů s adresací, a běh na veškerém DX kompatibilním HW. Samozřejmě objít problém změnou velikosti/alignmentu videa na té PCI kartě se přímo nabízí.