Coding 4 fun: Een alternatieve manier voor graphics in Windows. Transcript van SDN sessie 14 dec, 2009 Door : Nico Pronk,
[email protected]
Inhoud Inleiding .......................................................................................................................................... 2 De wereld van Bitmaps en DIBs...................................................................................................... 3 Device Dependent Bitmaps (DDB) .............................................................................................. 3 Device Independent Bitmap (DIB) ............................................................................................... 4 Metainformatie ......................................................................................................................... 4 Verschillende header versies ................................................................................................... 5 Een standaard ontbreekt, maar er zijn wel regels .................................................................... 6 De kleurentabel........................................................................................................................ 6 De pixeldata, compressie en codecs ........................................................................................ 6 Addressable DIBs........................................................................................................................ 7 Windows functies ............................................................................................................................ 8 Rasterfuncties ............................................................................................................................. 8 Compressie/decompressie functies ............................................................................................. 9 Toch een device context? ............................................................................................................ 9 Een library voor de DIB ................................................................................................................. 10 DIB object (PFL_Dib)................................................................................................................. 10 Standaard methods................................................................................................................ 10 Undo functionaliteit ................................................................................................................ 10 Unsafe methods..................................................................................................................... 11 Paging ................................................................................................................................... 11 ColorInfo Class (PFL_ImgColorFillInfo) ..................................................................................... 12 RotationInfo Class (PFL_ImgRotationInfo) ................................................................................ 12 DeformInfo class (PFL_ImgDeformInfo) .................................................................................... 12 De DIBcontrol Class (PFL_DibControl) ...................................................................................... 12 De DIBwindow Class (PFL_DibWindow) ................................................................................... 12 Gebruik van de lib in de praktijk .................................................................................................... 14 Waarvoor te gebruiken? ............................................................................................................ 14 Performance issues ................................................................................................................... 14 Wat kan het niet ? (Huidige stand van zaken) ........................................................................... 15 Demo’s ......................................................................................................................................... 16 DIB demo 1: DIBble ................................................................................................................... 16 DIB demo 2: Sodoku ................................................................................................................. 17 DIB demo 3: VideoCapture ........................................................................................................ 17 Vragen .......................................................................................................................................... 18 Informatiebronnen ......................................................................................................................... 19
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Inleiding Begin 2009 had ik wat tijd over om wat privé klusjes op te knappen. Een van die klusjes was een capture programma voor een webcam die gekoppeld was aan een telescoop. Vooral bij het gebruik van goedkope webcams zijn de beelden van een dermate kwaliteit dat je geen fatsoenlijke foto kunt maken. De lichtcondities zijn hier voor een webcam ronduit slecht, waardoor je veel ruis krijgt. Natuurlijk zijn er zat programma’s te krijgen die dat voor je doen. Die hebben echter als nadeel dat je eerst een filmpje moet maken met een normaal capture programma. Daarna kan een ‘imagestack’ programma gebruikt worden die uiteindelijk een foto produceert. De uiteindelijke foto is dan een geoptimaliseerd gemiddelde van de beelden uit het filmpje. Een soort elektronisch ontwikkel proces, waar redelijk wat tijd overheen gaat voordat je een resultaat te zien krijgt. Nu ben ik iemand van de snelle hap en ik wilde proberen om dat real time voor elkaar te krijgen. VO kende ik, dus dat leek de kortste weg. Ik begon met een simpel programma dat gebaseerd was op de video for windows technologie. Een oude technologie die gebaseerd is op MCI devices. Al snel raakte ik verzeild in de wereld van bitmaps met als gevolg dat een kleine bibliotheek ontstond waarmee je op relatief eenvoudige wijze Device Independent Bitmaps kan maken, kan onderscheppen vanuit een video stream, bewerken en op disk kunt opslaan. Ik had gebruik kunnen maken van veel windows GDI functies maar dat was niet het doel. De Windows GDI functie kunnen, voor zover ik weet, wel omgaan met bitmaps, maar niet omgaan met een DIB. Zeker weten doe ik dat echter niet. Feit is, dat toen ik eenmaal aan de gang ging veel zelf heb geschreven. Dat had als groot voordeel dat ik de totale controle had over iedere pixel in een DIB. De hierdoor gecreëerde bibliotheek heeft hierom misschien wel, denk ik, een paar unieke eigenschappen. Mijn uiteindelijke doel, live gemiddelde beelden halen uit een webcam, heb ik echter nog steeds niet gehaald. Ik ga in deze sessie kort in op de achtergrond van de Device Dependent Bitmaps en de Device Independent Bitmaps. Hoe zitten deze in elkaar, welke versie er zijn, welke problemen kunnen we verwachten en hoe we een DIB op het laagste niveau kunnen bewerken. We kijken ook kort naar verschillende Windows functies voor bitblock transfer, waarmee een DIB op een window kan worden getoond. Daarna zal ik ingaan op de library om aan het eind verschillende demo’s e laten zien die met deze library gemaakt zijn.
2
Coding 4 fun: Graphics in windows almost without a device context
December 2009
De wereld van Bitmaps en DIBs Device Dependent Bitmaps (DDB) Bitmaps zijn rastergraphics. Vaak zijn ze een representatie van een afbeelding. We komen ze overal tegen. Bijvoorbeeld de CCD van een (video)camera produceert bitmaps. De inhoud van een bitmap kom overeen met de pixels van een bepaald apparaat. Als we naar de CCD kijken dan is een bitmap een array van pixels, waarbij 1 pixel een gemiddelde presentatie is van de werkelijkheid.. De bitmap heeft een breedte, een hoogte en een kleurdimensie. Deze drie samen bepalen de grootte van de bitmap in bytes. Bijvoorbeeld een bitmap van 100x100 pixels en een kleurdimensie van 16 kleuren heeft een hoeveelheid geheugen nodig van 100x100x4=40000 bits = 5000 bytes. In eerste instantie hing de ontwikkeling van de bitmap nauw samen met de ontwikkeling van de videokaarten. Een bitmap kan dan ook voorgesteld worden als een blok videogeheugen waarbij de pixels van het beeldscherm overeenkomen met geheugenplaatsen in de bitmap. Historie zoals deze samenhangt met de ontwikkeling van de videokaart: • • • •
Monochrome bitmaps: 1 bit per pixel (Hercules videokaart) 16 Kleuren bitmaps. 4 Bits per pixel. Waarbij de bitmap was opgedeeld in blokken per kleur. (IRGB methode) 16 -256 kleuren: Vga en Svga, 8 bits per pixel. Moderne videokaarten 16 miljoen kleuren: 24 bits per pixel (voor elke kleur 256 waarden)
Een groot nadeel van de bitmap is dat deze niet portable is. Voor ieder output (of input) device moet een aparte bitmap gemaakt worden. Een ander nadeel is dat geen kleurinformatie aanwezig is. De kleurinformatie is afhankelijk van het gebruikte device. Vandaar dat in Windows 3.0 de Device Independent Bitmap, afgekort DIB, werd geïntroduceerd.
3
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Device Independent Bitmap (DIB) Het doel van dit hoofdstuk is niet om de DIB tot in het kleinste detail te beschrijven. Daarvoor zijn boeken en Internet uitgevonden. De onderstaande beschrijving is dan ook verre van compleet. Wel wil ik laten zien wat je zoal tegen kunt komen als je DIBs aan de slag gaat.
Metainformatie Belangrijk verschil van een DIB ten opzichte van een DDB is de meta-informatie. (informatie die iets over gegevens vertelt) Een DIB bestaat uit meta-informatie en de data zelf. De meta-informatie kan het volgende aangeven: • • • • • •
De grootte van de meta-informatie in bytes De hoogte en de breedte van de DIB in pixels De codering Een kleurtabel De grootte van de DIB data in bytes Hoe de data is georganiseerd
De metainformatie in detail Voor DIBs wordt onderscheid gemaakt tussen een DIB als file en een DIB in het geheugen. Een DIB als file is hetzelfde als een DIB in het geheugen, maar wordt voorafgegaan door een fileheader. De fileheader zoals deze in VO bestaat STRUCT _WINBITMAPFILEHEADER MEMBER bfType AS MEMBER bfSize AS MEMBER bfReserved1 AS MEMBER bfReserved2 AS MEMBER bfOffBits AS
ALIGN 2 WORD DWORD WORD WORD DWORD
Altijd… Grootte van de data Wordt nooit gebruikt Wordt nooit gebruikt Geeft aan waar de bitmap data begint
De fileheader wordt direct gevolgd door een de bitmapinfo die op haar beurt weer bestaat uit een winbitmapinfoheader en een kleurtabel. STRUCT _WINBITMAPINFO MEMBER bmiHeader IS _WINBITMAPINFOHEADER MEMBER DIM bmiColors[1] IS _WINRGBQUAD
Kleurtabel
STRUCT _WINBITMAPINFOHEADER MEMBER biSize AS DWORD MEMBER biWidth AS LONG MEMBER biHeight AS LONG MEMBER biPlanes AS WORD MEMBER biBitCount AS WORD MEMBER biCompression AS DWORD MEMBER biSizeImage AS DWORD MEMBER biXPelsPerMeter AS LONG MEMBER biYPelsPerMeter AS LONG MEMBER biClrUsed AS DWORD MEMBER biClrImportant AS DWORD
Grootte van infoheader in bytes Breedte van de bitmap in pixels Hoogte van de bitmap in pixels Is altijd 1 (ALTIJD) Aantal bits per pixel 1,2,4,16,24,32 FOURCC code Grootte van de DIB data in bytes horizontale resolutie verticale resolutie Aantal gebruikte kleuren ??
DIB als file DIB in het geheugen (packed DIB)
Fileheader Bitmapinfo Kleurtabel Data
Tabel 1 Schematische weergave van de DIB structuur
4
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Verschillende header versies Een header die alleen uit de members biSize t/m biBitCount bestaat wordt ook wel een coreheader genoemd. Dit is de header zoals deze in os 2 voorkomt. De expanded header zoals die in de _WINBITMAPINFOHEADER is gedefinieerd wordt in Windows gebruikt. Naast de bovenstaande versies bestaan er nog meer versies. De extra informatie die in deze versies zijn opgenomen hebben allemaal betrekking op kleurmanagament. Alle voorgaande versies van DIBS zijn gebaseerd op RGB (Rood, Groen, Blauw) waarden van een monitor of grafische kaart. De RGB waarde van een monitor hoeft echter niet noodzakelijker wijs overeen te komen met die van een printer. Vandaar dat extra informatie is opgenomen waarmee wordt geprobeerd om meer apparaat onafhankelijke kleurondersteuning te bieden. Hoe deze informatie in elkaar zit valt buiten de scope van dit verhaal. Wie daar toch in is geïnteresseerd kan eventueel bij MSDN zoeken op colormanagament, www.icc.org en de CIE. (Zie ook informatiebronnen) De versie 4 en versie 5 header laat ik toch even zien, zoals ze in VO zijn gedefinieerd. Versie 4 header
Versie 5 Header
STRUCT _WINBITMAPV4HEADER MEMBER bV4Size AS DWORD MEMBER bV4Width AS LONG MEMBER bV4Height AS LONG MEMBER bV4Planes AS WORD MEMBER bV4BitCount AS WORD MEMBER bV4V4Compression AS DWORD MEMBER bV4SizeImage AS DWORD MEMBER bV4XPelsPerMeter AS LONG MEMBER bV4YPelsPerMeter AS LONG MEMBER bV4ClrUsed AS DWORD MEMBER bV4ClrImportant AS DWORD MEMBER bV4RedMask AS DWORD MEMBER bV4GreenMask AS DWORD MEMBER bV4BlueMask AS DWORD MEMBER bV4AlphaMask AS DWORD MEMBER bV4CSType AS DWORD MEMBER bV4Endpoints IS _WINICEXYZTRIPLE MEMBER bV4GammaRed AS DWORD MEMBER bV4GammaGreen AS DWORD MEMBER bV4GammaBlue AS DWORD
STRUCT _WINBITMAPV5HEADER MEMBER bV5Size AS DWORD MEMBER bV5Width AS LONG MEMBER bV5Height AS LONG MEMBER bV5Planes AS WORD MEMBER bV5BitCount AS WORD MEMBER bV5V4Compression AS DWORD MEMBER bV5SizeImage AS DWORD MEMBER bV5XPelsPerMeter AS LONG MEMBER bV5YPelsPerMeter AS LONG MEMBER bV5ClrUsed AS DWORD MEMBER bV5ClrImportant AS DWORD MEMBER bV5RedMask AS DWORD MEMBER bV5GreenMask AS DWORD MEMBER bV5BlueMask AS DWORD MEMBER bV5AlphaMask AS DWORD MEMBER bV5CSType AS DWORD MEMBER bV5Endpoints IS _WINICEXYZTRIPLE MEMBER bV5GammaRed AS DWORD MEMBER bV5GammaGreen AS DWORD MEMBER bV5GammaBlue AS DWORD MEMBER bV5Intent AS DWORD MEMBER bV5ProfileData AS DWORD MEMBER bV5ProfileSize AS DWORD MEMBER bV5Reserved AS DWORD
5
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Een standaard ontbreekt, maar er zijn wel regels We weten dus dat er geen standaard is we hebben te maken met verschillende versie die we allemaal in de praktijk kunnen tegenkomen. En..het wordt nog erger. Wel kunnen we ons vasthouden aan de volgende regels: • • • • •
Bij een DIBfile is de fileheader altijd 14 bytes. De bitmapinfo volgt direct op de fileheader. Na de bitmapinfo volgt altijd de kleuren tabel. De kleuren tabel wordt altijd gevolgd door de pixeldata. Bij een 24 bit DIB bestaat er in de regel geen kleurtabel De grootte van de metainformatie is gegeven, zodat we aan de hand van deze grootte altijd kunnen bepalen met welke versie we te maken hebben.
De kleurentabel De kleurtabel bestaat uit een array van words (zogenaamde winrgbquads). Hoe de tabel gevuld is hangt nauw samen met de kleurdiepte: Kleurdiepte 1 bit 4 bit
8 bit
16,24 en 32 bit
biClrUsed 0 of 2 0 of 16 2-15
aantal kleurdefinities altijd 2 winrgbquads altijd 16 entries aantal aangegeven in biClrUsed
0 of 256 1-255
256 entries aantal aangegeven in biClrUsed
Meestal 0
Geen entries
1-xxx
Aantal aangegeven in biClrUsed
Opmerkingen
Maximale waarde van een pixel is biClrused-1 Maximale waarde van een pixel is biClrused-1 Oudere programma’s verwachten vaak geen kleurentabel bij 24 bit DIBs. In de regel gebeurt dit dan ook niet.
Tabel 2: Mogelijke kleurtabellen bij verschillende kleurdiepten
De pixeldata, compressie en codecs Naast dat de pixelbits verschillend kunnen zijn kan het ook nog zo zijn dat de data in een DIB anders is georganiseerd, dan wat ‘normaal’ wordt verwacht. ‘Normaal’ is dat de bits per regel van onder naar boven zijn georganiseerd. Dat wil zeggen: De eerste rij data is de onderste rij van een afbeelding. Echter als de hoogte negatief is opgegeven wil dat zeggen dat de DIB andersom is georganiseerd. De eerste rij data is dan de bovenste rij pixels in een afbeelding. Pixeldata kan ook gecomprimeerd zijn. Dit kan van alles zijn. Hoe de DIB-data is gecomprimeerd wordt aangegeven in het biCompression veld.
6
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Het biCompression veld is opgebouwd uit 4 bytes. De zogenaamde Fourcc bytes. Voor de ‘standaard’ DIB kan dit veld de volgende waarden hebben: Kleurdiepte 1 bit 4 bit 8 bit 16 bit 24 bit 32 bit
Waarde Altijd BI_RGB BI_RGB of BI_RLE4 BI_RGB of BI_RLE8 BI_RGB FourCC code
Opmerking
Voorbeelden FourCC ‘MJPG’ YUV
Andere waarden dan BI_RGB geven aan dat de DIB gecomprimeerd is volgens een bepaalde methode. Welke methode dat is kunnen we onder andere vinden op www.fourcc.org.
Addressable DIBs Een DIB die niet gecomprimeerd is, is een addressable DIB. Dat wil zeggen dat voor we voor iedere pixel van de DIB een exacte plaats in de DIB-pixeldata kunnen aanwijzen. De plaats van een pixel is uiteraard afhankelijk van de kleurdiepte. Voor een lijn geldt de volgende rekenregel: X_Membytes = kleurdiepte bits per pixel * breedte in pixels Hierbij geldt als afspraak dat het uiteindelijk aantal bytes altijd een veelvoud van 4 is. Dus uiteindelijk wordt de regel dan: X_Membytes = 4 * ((kleurdiepte bits * breedte in pixels + 31) / 32) Om de 1e bit van een pixel op punt X,Y te kunnen bepalen wordt dit dan: Mempos x,y = X_Membytes * Y + X * kleurdiepte bits Een Addressable DIB is erg fijn, want het betekent dat we de inhoud van de data gericht kunnen manipuleren.
7
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Windows functies Hier wil ik in het kort een aantal functies aangeven waarmee in Windows een DIB op een window kan worden geprojecteerd. Ook wil ik kort aangeven hoe met compressie om kan worden gegaan. Voor uitgebreide info zie de win32 documentatie en Petzhold (zie bronnen)
Rasterfuncties Windows beschikt over diverse functies om rasteroperaties uit te voeren. Deze rasterfuncties zorgen ervoor dat de inhoud van een DIB op een bepaald device terecht komt. In de hele DIB library zoals die gemaakt is wordt gebruik gemaakt van twee functies: SetDIBitsToDevice() en StretchDIBits() SetDIBitsToDevice() kopieert de inhoud van een DIB (Geheel of gedeeltelijk) 1 op 1 naar een device. Het device kan een window zijn, maar ook een printer. StretchDIBits() kan hetzelfde doen, echter deze functie kan de DIB ook verkleinen en vergroten. Ook de aspect ratio kan veranderd worden. Daarnaast kan bij stretchDIBits() ook nog een zogenaamde ROP code worden opgegeven. Met de ROP code kunnen we allerlei interessante operaties uitvoeren volgens onderstaande tabel. Code BLACKNESS
Hex Waarde 0x000042
DSTINVERT MERGECOPY
0x550009 0xC000CA
MERGEPAINT
0xBB0226
NOTSRCCOPY NOTSRCERASE
0x330008 0x1100A6
PATCOPY PATINVERT
0xF00021 0x5A0049
PATPAINT
0xFB0A09
SRCAND
0x8800C6
SRCCOPY SRCERASE
0xCC0020 0x440328
SRCINVERT
0x660046
SRCPAINT
0xEE0086
WHITENESS
0xFF0062
Omschrijving Fills the destination rectangle using the color associated with index 0 in the physical palette. This color is black for the default physical palette. Inverts the destination rectangle. Merges the colors of the source rectangle with the specified pattern by using the Boolean AND operator. Merges the colors of the inverted source rectangle with the colors of the destination rectangle by using the Boolean OR operator. Copies the inverted source rectangle to the destination. Combines the colors of the source and destination rectangles by using the Boolean OR operator and then inverts the resultant color. Copies the specified pattern into the destination bitmap. Combines the colors of the specified pattern with the colors of the destination rectangle by using the Boolean XOR operator. Combines the colors of the pattern with the colors of the inverted source rectangle by using the Boolean OR operator. The result of this operation is combined with the colors of the destination rectangle by using the Boolean OR operator. Combines the colors of the source and destination rectangles by using the Boolean AND operator. Copies the source rectangle directly to the destination rectangle. Combines the inverted colors of the destination rectangle with the colors of the source rectangle by using the Boolean AND operator. Combines the colors of the source and destination rectangles by using the Boolean XOR operator. Combines the colors of the source and destination rectangles by using the Boolean OR operator. Fills the destination rectangle using the color associated with index 1 in the physical palette. This color is white for the default physical palette.
Tabel 3: Ropcodes, Overgenomen van Msdn 8
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Compressie/decompressie functies Als we te maken hebben met een gecomprimeerde DIB, kunnen we gebruik maken van een Codec om de DIB te de-comprimeren en opnieuw te comprimeren. Op deze manier kunnen we bijvoorbeeld een beeld onderscheppen uit een video stream, het beeld decomprimeren, het bewerken om het als laatst weer te comprimeren en verder te laten gaan in de stream. We kunnen op deze manier bijvoorbeeld een programma maken weermee je de inhoud van avi files kunt bewerken. Denk hierbij aan ondertiteling, fade-in fade out enzQ.. Niet iedere codec kan opnieuw comprimeren. Veel codecs kunnen alleen maar decomprimeren omdat ze gemaakt zijn om streams te decoderen voor bijvoorbeeld een mediaspeler. Het kan dus zijn dat we een andere compressor gebruiken dan de dé-compressor. Algemeen: • •
Kijk welke FourCC er in het bicompression field staat Enumerate de compressors totdat in de (dé)compressor aangeeft dat deze geschikt is voor de gevraagde fourcc code.
Als alternatief zou een eigen compressie/decompressie routine geschreven kunnen worden als het om eenvoudige compressie technieken gaat (RLE,YUV etc) Windows functies t.b.v. compressie/dé-compressie: IcOpen() IcClose() IcInfo ICImageDecompress ICImagecompress
Functie voor het openen van een compressor of om te kijken welke compressors er zijn. Sluiten van een compressor Opvragen van de compressor mogelijkheden Dé-compressie van een enkel beeld Compressie van een enkel beeld.
Voor meer info zie win32 documentatie.
Toch een device context? Uiteindelijk komen we er niet onderuit. Op een bepaald niveau in Windows moeten we met een device context werken. De truuk is echter dat je met bepaalde basisklassen dit maar eenmalig hoeft te doen. Voorbeelden van deze basisklassen zien we laten als de DIBControl en de DIBWindow klassen. Voor de rest wordt de inhoud bepaald door de DIB een DIBobject. De device context bepaalt uiteindelijk waar de inhoud van een DIB naartoe gaat. Dit kan een windows zijn, een control, de desktop maar ook bijvoorbeeld een printer. Het enige wat de DIBControl en DIBWindow doen is bitblock transfers. De blokken geheugen worden direct naar het geheugen van een window of control gekopieerd.
9
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Een library voor de DIB Vooraf. De status van de lib zoals die nu is is een vorm van hobby code. Op diverse plekken wordt kort door de bocht gegaan en met name voor het onderscheppen van DIBs uit een stream geldt dat deze niet fool proof is: Er wordt in beperke mate rekening gehouden met de diverse verschijningsvormen van een DIB. Voor alle methods die in deze library voorkomen geldt dat ze voor een 24 bit gelden. 1,4,8,16 of 32 bit DIB’s worden niet ondersteund, tenzij gebruik wordt gemaakt van een compressie techniek. In dit laatste geval zal de DIB eerst worden geconverteerd naar 24 bit, vervolgens kunnen bewerkingen worden uitgevoerd en zal daarna de DIB weer worden gecomprimeerd. Het kan zijn dat een DIB wel kan worden gedé-comprimeerd, maar dat dit omgekeerd niet gaat. In dat geval worden bewerkingen wel uitgevoerd, maar zijn dan in het resultaat niet zichtbaar. In de library wordt gebruik gemaakt zijn diverse klassen aanwezig: -De DIB klasse, die de daadwerkelijke DIB beheert, en alle methods heeft voor het bewerken van de gekoppelde DIB. -Ondersteunende klassen: ColorInfo, DeformInfo, RotationInfo en DIBText.
DIB object (PFL_Dib) Standaard methods Maken en of lezen van een DIB • CreatePDIB() Hiermee wordt een packed DIB gemaakt (DIB in het geheugen) • Fileread() Hiermee kan een bmp worden gelezen. Methods t.b.v. het tekenen van basis elementen ImgDrawLine() ImgDrawEllipse() ImgDrawTriangle() ImgDrawRect() ImgDrawText() ImgDrawPoint() Kleurbeheer ColorFillInfo Klasse Beinvloeden van het tekenen DeformInfo Klasse en RotationInfo klasse
Undo functionaliteit De undo mogelijkheid bestaat uit het opslaan van stukjes uit de DIB, voordat een ‘teken’ actie wordt uitgevoerd. Het aantal undo’s is instelbaar of is geheel uit te schakelen. Ook kan de undo tijdelijk worden uitgeschakeld. (Suspend)
10
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Unsafe methods Van elke ImgDrawxxx method bestaat dezelfde method, uitgebreid met een N. Bijvoorbeeld ImgdrawLineN. Het verschil van de ‘N’ methods t.o.v. de normale methods is: Normale methods • • •
Opgegeven kleur mag color, colorfill of null_object zijn. Bij color als object wordt een colorfillinfo gemaakt, bij null_object wordt een standaard colorfill object gebruikt. Undo mogelijkheid afhankelijk van SuspendUndo en undomanual. Automatische compressie/decompresie.
‘N’ methods • •
Geen undo mogelijkheid Altijd een colorfill object
Paging Met paging kunnen leuke effecten worden bereikt. Eigenlijk is dit al een truuk die je al in de vroegste games met wat meer grafische ‘toeters en bellen’ tegenkwam. Waar het op neerkomt is dat verschillende frames gemaakt kunnen worden die je kunt bewaren. In een later stadium kunnen deze frames dan weer stuk voor stuk opgeroepen worden. Bij het oproepen wordt de huidige DIB die bijvoorbeeld in een window getoond wordt overschreven met de opgeroepen DIB. Hierna kunnen de standaard bewerkingen weer toegepast worden. Zo kunnen we bijvoorbeeld vooraf, bij initialisatie, verschillende achtergronden maken daar overheen, later, andere zaken toe te voegen. Het real time maken van de achtergronden kost veel tijd, stel bijvoorbeeld een halve seconde per achtergrond. Hetgeen zou resulteren in een performance van minimaal 2 beelden per seconde. Door gebruik te maken van pagesave in de initialisatie en pagerestore in de loop van het programma kunnen we een animatie aanzienlijk versnellen. De opgeslagen achtergronden worden in het geheugen in een keer naar de DIB gekopieerd worden. PageSave() Pagerestore() PageDelete()
Sla de huidige DIB op in een array Restore een DIB uit de array Verwijder een dib uit de array
Speciaal: Methods voor onderscheppen bij videocapture of andere MCI bronnen (AVI) SetData() ImgProcess() ProcessStart() ProcessEnd()
//Voeden van het DIB geheugen in een DIB object //Aanbrengen van wijzigingen , Contrast, Brightness e.d. //Zorgt voor decompressie indien nodig //Zorgt voor compressie indien nodig na het uitvoeren van bewerkingen
Met Setdata() kan een DIB uit een videostream worden onderschept en in het DIBobject worden gestopt om te kunnen analyseren en te bewerken. Meer info hierover bij de Videocapture demo.
11
Coding 4 fun: Graphics in windows almost without a device context
December 2009
ColorInfo Class (PFL_ImgColorFillInfo) Met de colorinfo class wordt de kleur van een te tekenen object bepaald. Naast de standaard kleuren kan ook een kleurverloop worden ingesteld. Het uniek van de ColorInfo class is echter dat je het verloop kunt laten verplaatsen. Zo kun je 1 colorinfo class gebruiken voor meerdere objecten die je wilt tekenen. Tot op het laatste moment kun je het verloop dan beïnvloeden. Bij een eventuele override van de colorinfo class kun je zelf de kleur per pixel bepalen. Indien geen colorinfo class is gedefinieerd en er wordt gebruik gemaakt van de ‘safe’ methods dan is de kleur standaard wit.
RotationInfo Class (PFL_ImgRotationInfo) De rotationinfo class maakt het mogelijk om in een DIB te kunnen tekenen, maar door een rotationinfo object toe te passen wordt al het getekende op een andere plaats neergezet. De rotationinfo class heeft genoeg aan 2 parameters. Een x en een y coordinaat die het centrum van de rotatie aangeven.
DeformInfo class (PFL_ImgDeformInfo) Met de deform info class kan de positie van een pixel veranderd worden, dit zonder dat de orginele routine hoeft te worden aangepast. De deform info class heeft 1 method: Deform(x longint ptr,y longint ptr) X en y worden erin gestopt en komen er ‘anders gepostioneerd uit. Voorbeeld: Method deform2D(lix AS LONGINT PTR, liy AS LONGINT PTR) AS LONGINT PASCAL CLASS Mydeform Longint(liy):=Longint(liy)+10 RETURN S_OK
In het bovenstaande voorbeeld geldt dat voor elke pixel die met het deform object wordt ‘vervormd’, de pixel 10 pixels hoger staat.
De DIBcontrol Class (PFL_DibControl) De DIBcontrol class is gebaseerd op customcontrol. Het enige wat deze class doet is het beheren van een DIB Object en het tonen van de DIB inhoud middels de Expose method. Daarnaast is het gebruik van een milliseconde timer vereenvoudigd, zodat makkelijker iets op een timer event kan worden afgehandeld. Dit omdat de standaard timer in VO een resolutie van minimaal 1 seconde heeft.
De DIBwindow Class (PFL_DibWindow) Voor de DIBwindow Class geldt hetzelfde als voor de DIBControl class. Ook hier wordt een DIB middels een expose call op het window geprojecteerd. (Over de totale canvasarea) Ook hier is een milliseconde timer standaard aanwezig.
12
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Camera support Er is een aparte lib voor camera support die gebaseerd is op de PFL_Dib klasse in combinatie met Video For Windows technologie. VFW is oud, heel oud en het is de vraag hoe lang MS dit zal blijven supporten. Aan de andere kant: Als VFW niet meer ondersteund wordt dan zullen heel wat oudere programma’s niet meer werken. Het is wel mijn wens om dit t.z.t. om de schrijven naar een andere technologie. In het DIB object zijn wel voorzieningen opgenomen om bewerkingen op aangeboden beelden te kunnen toepassen. Deze zijn opgenomen in de IMGProcess method van de DIB en omvat onder andere: ruisreductie, contrastbijstelling, helderheidbijstelling, kleurbijstelling, flipping en bewegingsdetectie.
13
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Gebruik van de lib in de praktijk Waarvoor te gebruiken? Eenvoudige presentaties Een simpele registratie door middel van een usb camera waarbij bijvoorbeeld direct de persoonsgegevens in de foto zelf worden opgenomen. Simpele animaties: ‘Heel eigen’ voortgangs balken
Performance issues Vloeiende beelden Als we een simpele test uitvoeren in VO, dan blijkt dat, onder normale omstandigheden we op de demonstratie machine een maximale schrijf performance halen van 50.000.000 pixels per seconde. Test: pPixel:=MemAlloc(_SizeOf(_winRGBTRIPLE)) FOR y:=1 TO 10 STEP 1 fBeg:=Pfl_GregorianSeconds() //Meet starttijd //20.000.000 keer Schrijven 1 pixel FOR x:=1 UPTO 20000000 STEP 1 pPixel.rgbtBlue:=255 pPixel.rgbtGreen:=255 pPixel.rgbtRed:=255 NEXT fEnd:=Pfl_GregorianSeconds() //Meet Eindtijd fEl:=fEnd-fBeg fTi:=fEl/20000000 fIs:=1/fTi PFLTraceShw "Elapsed",fEl PFLTraceShw "Time/Item",fTi PFLTraceShw "Items/sec",fIs PFLTraceShw "Items/sec",fIs/25 NEXT MemFree(pPixel)
Dat lijkt veel maar als we het getal door 25 delen, in verband met 25 beelden per seconde, dan komen we uit op 2.000.000 pixels per 1/25 seconde. En dan hebben we nog niets gedaan, alleen maar een pixelkleur setten. Als we gebruik gaan maken van andere bewerkingen dan zal dit alleen maar afnemen. In de DIBble demo is een test opgenomen waarbij daadwerkelijk het maximale wordt geprobeerd en dan blijkt dat we op een snelheid uitkomen van 2.000.000 – 3.000.000 pixels per seconde. Voor 1 beeld is dit dan 120.000 pixels. Di betekent dat we dan in 1/25 seconde een plaatje kunnen bewerken van 400 x 300 pixels. Dat is ronduit traag. Als het gaat om camera support dan wordt de zaak alleen maar moeilijker, dat neemt echter niet weg dat we er leuke dingen mee kunnen doen.
14
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Wat kan het niet ? (Huidige stand van zaken) Fonts zijn nog een probleem Er wordt nu gebruik gemaakt van een eigen bitmap waarbij de letters niet proportioneel zijn. simpelweg een bitmap copy. Door middel van de windows GDI functie zou dat wel gerealisseerd kunnen worden maar, dan hebben we geen mogelijkheid voor deform en colorinfo. Andere formaten: Formaten zoals GIF en JPG of andere formaten worden niet ondersteund. Het is alleen mogelijk om BMP te laden en te bewerken.
15
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Demo’s DIB demo 1: DIBble In deze applicatie worden de diverse mogelijkheden van de DIBlib, tot in het extreme toe, gedemonstreerd. De applicatie is geschreven om de diverse onderdelen van de DIBlib te kunnen testen en te beoordelen. Simpele demo’s Diverse verschillende demo’s die de mogelijkheden van lib laten zien: Lijnen, driehoeken, rechthoeken en cirkels Colorfillinfo en Deforminfo, toegepast op de diverse simpele demo’s Mogelijke toepassingen: grafieken en klok Het DIBble programma heeft een toepasbare grafieken class. Per grafiek kunnen verschillende datasets worden opgegeven als array. De demo is realtime gebruik makend van de paging techniek. Bij initialisatie wordt de achtergrond getekend en bewaard, in de loop van het programma wordt deze achtergrond bij ieder frame teruggezet en worden de grafieken ingevuld. De grafieken kunnen ook ‘gedeformeerd’ worden getoond. Ook hier geldt hetzelfde. De achtergrond wordt eerst gedeformeerd getekend bij initialisatie. In de loop van het programma worden de grafieken gedeformeerd ingevuld. Stars Bij ‘Stars’ wordt gebruik gemaakt van de paging techniek. Eerst wordt 1 achtergrond getekend waarbij een algemene achtergrond wordt gemaakt. Vervolgens worden er negen verschillende achtergronden gemaakt. Bij iedere nieuwe achtergrond wordt een vierkant getekend die door middel van een deform object wordt geprojecteerd op een bol. Na initialisatie van deze achtergrond wordt de eerste gemaakte achtergrond, die zonder bol, weer verwijderd. In de loop van het programma worden alleen maar sterren getekend. De achtergronden worden per beeld teruggezet aan de hand van een page teller die in het programma meeloopt. Bij stars wordt het maximaal haalbare eruit gehaald. Zeker omdat iedere ster die in het beeld zichtbaar is een object is, die op basis van random tijd uit elkaar kan spatten in andere sterren die op hun beurt ook weer kunnen exploderen. Soms zit er wat vertraging in. Op de testmachine lijkt een grens van 2000 sterren het maximaal haalbare. Per ster is ook een color info object aanwezig. Het colorinfo object verplaatst mee met de ster. Waterfall Waterfall haalt ook het maximaal haalbare eruit. Met name omdat er hier met gevulde rechthoeken wordt gewerkt. 16
Coding 4 fun: Graphics in windows almost without a device context
December 2009
DIB demo 2: Sodoku Een applicaties waar gebruik wordt gemaakt van de DIB control. De inhoud van de control wordt volledig bepaald door de DIB die reageert op events van de control.
DIB demo 3: VideoCapture Demonstratie van het onderscheppen van DIBs in een video capture stream. In deze applicatie wordt gebruik gemaakt van video for windows de avicap32 dll. Video for windows is beperkt. Zo kun je bijvoorbeeld niet een camera opgeven die gebruikt moet worden. Het kan wel, maar wordt volledig genegeerd. Het is beter, zeker tegenwoordig, om directdraw/directshow te gebruiken of WPF. Waar het bij deze demo om gaat is het onderscheppen van beelden en het bewerken daarvan. Er wordt gebruik gemaakt van de Vfw callbackfuncties. Om het mogelijk te maken om met meerdere camerawindows te kunnen werken is een aparte class geschreven waarmee de callbackfuncties aan een capturewindow class hangen. Als bewerkingsmogelijkheden kunnen alle mogelijkheden uit de library toegepast worden, echter we moeten er wel rekening mee houden dat als we veel doen, de zaak behoorlijk vertraagd wordt. Vandaar dat een aantal zaken in 1 routine zijn opgenomen, de Imgprocess() method: • • • • • •
Het filteren van kleuren Bewerken van contrast waarden Bewerken van de helderheid Negatief Vertical flip Ruisreductie op basis van helderheid, luminantie en RGB waarden per kleur
Per aangeboden beeld zullen alle pixels van het beeld bekeken worden. Als het gaat om luminantie dan geldt dat de zaak aardig vertraagd wordt omdat hevig gebruik wordt gemaakt van floats, en die zijn langzaam. Wat er gebeurt is het volgende: •
Er wordt een beeld aangeboden vanuit de stream
•
Dit beeld wordt onderschept met een callbackfunctie die door het VFW window wordt aangeroepen. Met Setdata wordt de data in het DIBobject geschreven. Door middel van Setdata() worden in het DIB object verschillende beelden vastgehouden om zo, voor bijvoorbeeld ruisreductie, gemiddelde beelden te kunnen maken.
•
Het aangeboden beeld gaat vervolgens door de Imgprocess() method heen waarmee gecombineerde bewerkingen per pixel er op worden losgelaten.
•
Als de bewerkingen voltooid zijn wordt het beeld indien nodig weer gecomprimeerd en bewerkt teruggegeven.
Op deze manier zou eventueel ook een applicatie kunnen worden geschreven waarmee je complete avi files kunt bewerken. 17
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Vragen Alhoewel het een hobby project is, denk ik dat het misschien bruikbaar is voor anderen. Echter er is al zoveel. Als je kijkt naar DOT net, dan is dit zeer omvangrijk. Andere technieken die gebruikt kunnen worden: DirectDraw / DirectShow (C++) OpenGL Dot Net: WPF Heeft een Library zoals deze nog wel toekomst? Is er überhaupt vraag naar m.b.t. de mogelijkheden? Heeft deze library added value? Het voordeel is dat de library is dat ze lichtgewicht is. Je kunt met weinig handelingen snel iets maken op een bekende wijze zonder dat je je uitgebreid moet verdiepen in bijvoorbeeld DirectX. Het is universeel. De code zou gemakkelijk naar bijvoorbeeld JAVA kunnen worden getransporteerd.
18
Coding 4 fun: Graphics in windows almost without a device context
December 2009
Informatiebronnen msdn.microsoft.com, win32 programming: Video for windows, MCI Charles Petzhold: Programming Windows Fifth Edition ISBN:1-57231-995-X Informatie m.b.t. compressie: www.fourcc.org Codevoorbeelden: www.codeproject.com Colormanagement:
Publicatie van de CIE (Commission Internationale de L’Eclairage) 15.2.1986 “Colormetry,Second Edition”
ICC Profile Format: www.icc.org
19