Prezentace se nahrává, počkejte prosím

Prezentace se nahrává, počkejte prosím

OSNOVA: a) Programování BMP b) Práce se sériovým portem Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E.

Podobné prezentace


Prezentace na téma: "OSNOVA: a) Programování BMP b) Práce se sériovým portem Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E."— Transkript prezentace:

1 OSNOVA: a) Programování BMP b) Práce se sériovým portem Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E PŘEDNÁŠKA 2

2 Programování BMP (1/19) Soubor typu BMP – pixelový RGB obrázek BMP je jednoduchý pixelový formát obrázků původně definovaný jako součást operačního systému OS/2. Později bzl přebrán i do Windows. Obrázky BMP jsou ukládány po jednotlivých pixelech nekomprimovaně (existuje i málo používaná varianta RLE komprese), přičemž každý pixel je definován barvou z definovatelné palety barev. Standardem jsou 2 barvy (1 bit na pixel), 16 barev (4 bity na pixel), 256 (8 bitů), (16 bitů) nebo cca 16,8 miliónů barev (24 bitů). V případě 24 bitů na pixel, každá barevná složka – čevená R, zelená G a modrá B má rozlišení 8 bitů (1 byte).

3 Programování BMP (2/19) Definice barvy pixelu

4 Programování BMP (3/19) Příklad při 24 bitech na pixel Data jsou uloženy v pořadí úroveň R-G-B od levého dolního rohu po řádcích.

5 Programování BMP (4/19) Každý korektní soubor typu BMP je složen z několika datových struktur, jejichž hodnoty položek jsou binárně zakódovány v BMP souboru. Pro zjednodušení programování jsou tyto struktury definovány ve WinAPI (nutno přilinkovat knihovnu windows.h ): Název strukturyVýznam BITMAPFILEHEADER hlavička BMP souboru BITMAPINFOHEADER informační hlavička o obrázku RGBQUAD[] tabulka barev (barvová paleta) BITS pole bitů obsahujících vlastní rastrová data (pixely)

6 Programování BMP (5/19) Uspořádání hlaviček, palety a dat v BMP souboru: Barvy jsou definovány jako součtové příspěvky složek R-G-B:

7 Programování BMP (6/19) Hlavička souboru typu BMP, tj. datová struktura BITMAPFILEHEADER, má délku čtrnácti bytů a obsahuje údaje o typu, velikosti a celkovém uspořádání dat v souboru. Název položky Délka položky Význam bfType 2 byty Identifikátor formátu BMP. Aktuální verze formátu BMP zde obsahuje ASCII kód znaků " BM ", tj. 0×42 a 0×4d hexadecimálně. bfSize 4 byty Celková velikost souboru s obrazovými údaji. Některé aplikace tuto položku ignorují a dosazují zde nulu. bfReserved1 2 byty Tento údaj je rezervovaný pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota.

8 Programování BMP (7/19) Název položky Délka položky Význam bfReserved2 2 byty I tento údaj je rezervovaný pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota. bfOffBits 4 byty Posun struktury BITMAPFILEHEADER od začátku vlastních obrazových dat.

9 Programování BMP (8/19) Datová struktura BITMAPINFOHEADER obsahuje základní metainformace o rastrovém obraze. Mezi tyto informace patří především jeho rozměry, tj. výška a šířka, dále pak identifikace použité komprimační metody a specifikace formátu rastrových dat. Celková velikost této struktury je vždy rovna 40 bytů. Název položky Délka položky Význam biSize 4 byty Tato položka specifikuje celkovou velikost datové struktury BITMAPINFOHEADER biWidth 4 byty Tato položka udává šířku obrazu zadávanou v pixelech biHeight 4 byty Tato položka udává výšku obrazu zadávanou taktéž v pixelech

10 Programování BMP (9/19) Název položky Délka položky Význam biPlanes 2 byty V této položce je zadaný počet bitových rovin pro výstupní zařízení. V BMP, jakožto formátu nezávislém na zařízení, je zde vždy hodnota 1. Položka existuje z historických důvodů. biBitCount 2 byty V této položce je specifikovaný celkový počet bitů na pixel. Podle počtu barev zde mohou být hodnoty 1, 4, 8 nebo 24 (to odpovídá postupně 2, 16, 256ti barvám popř. plnobarevnému režimu). biCompression 4 byty Udává typ komprimační metody obrazových dat. Musí být nastavené na jednu z hodnot: 0 (BI_RGB), 1 (BI_RLE8) nebo 2 (BI_RLE4).

11 Programování BMP (10/19) Název položky Délka položky Význam biSizeImage 4 byty Tato položka udává velikost obrazu v bytech. Pokud je bitmapa nekomprimovaná, může zde být nulová hodnota, protože ji je možno vypočítat z rozměrů obrázků a počtu bitů na pixel. biXPelsPerMeter 4 byty Udává horizontální rozlišení výstupního zařízení v pixelech na metr. Tato hodnota může být použita například pro výběr obrazu ze skupiny obrazů, který nejlépe odpovídá rozlišení daného výstupního zařízení. Většina aplikací však nemá potřebné informace o výstupním zařízení, a proto do této položky vkládá hodnotu 0.

12 Programování BMP (11/19) Název položky Délka položky Význam biYPelsPerMeter 4 byty Udává vertikální rozlišení výstupního zařízení v pixelech na metr. Opět, jako u předchozí položky, zde většina programů zapisuje hodnotu 0. biClrUsed 4 byty Udává celkový počet barev, které jsou použité v dané bitmapě. Jestliže je tato hodnota nastavena na nulu (což provádí většina aplikací), znamená to, že bitmapa používá maximální počet barev. Tento počet lze jednoduše zjistit z položky biBitCount. Nenulová hodnota může být použita například při optimalizacích zobrazování.

13 Programování BMP (12/19) Název položky Délka položky Význam biClrImportant 4 byty Udává počet barev, které jsou důležité pro vykreslení bitmapy. Pokud je tato hodnota nulová (téměř vždy), jsou všechny barvy důležité. Tento údaj je používán při zobrazování na zařízeních, které mají omezený počet současně zobrazitelných barev (například starší grafické karty se 16ti resp. 256ti barevnými režimy). Ovladač displeje může upravit systémovou paletu tak, aby zobrazil daný obrázek co nejvěrněji. Také je vhodné upravit paletu metodou seřazení jednotlivých barev podle důležitosti.

14 Programování BMP (13/19) RGBQUAD[] obsahuje pole definující barevnou paletu pro omezený počet barev (jinak nemusí být definováno, pak se použije plnobarevná paleta, tj. 1,68 mil. barev ). BITS obsahuje pole definující jednotlivé pixely, tak jak jdou za sebou, při kompresním RGB jsou to čísla jednotlivých barev, při nekompresním RGB obsahují úroveň složek R, G a B. V knihovně windovs.h je definována i struktura pro jeden pixel: RGBTRIPLE s položkami pro jednotlivé barvy s rozsahem unsigned char (0x00 – 0xFF) rgbtRed, rgbtGreen, rgbtBlue

15 Programování BMP (14/19) Příklad: Vygenerujte ze vstupního bezkompresního BMP obrázku, obrázek inverzní, obrázek stupňů šedi, obrázek jen s červenou složkou, jen se zelenou složkou, jen s modrou složkou. #include int main() { BITMAPFILEHEADER bmp_fh; //struct. BMP file header BITMAPINFOHEADER bmp_ih; //struct. BMP info header RGBTRIPLE bmp_rgb; //struct. triplet of one pixel unsigned char Red, Gre, Blu, Av; FILE *fRGB, *fRED, *fGRE, *fBLU, *fINV, *fBAW; size_t padd; int i, j;

16 Programování BMP (15/19) fRGB = fopen("RGB.bmp", "rb"); //old BMP fRED = fopen("RED.bmp", "wb"); //new BMP red fGRE = fopen("GREEN.bmp", "wb"); //new BMP green fBLU = fopen("BLUE.bmp", "wb"); //new BMP blue fINV = fopen("INVERT.bmp", "wb");//new BMP inverted fBAW = fopen("BANDW.bmp", "wb"); //new BMP black&white //BITMAPFILEHEADER copy to new BMP files fread(&bmp_fh, sizeof(bmp_fh), 1, fRGB);//old BMP fwrite(&bmp_fh, sizeof(bmp_fh), 1, fRED); fwrite(&bmp_fh, sizeof(bmp_fh), 1, fGRE); fwrite(&bmp_fh, sizeof(bmp_fh), 1, fBLU); fwrite(&bmp_fh, sizeof(bmp_fh), 1, fINV); fwrite(&bmp_fh, sizeof(bmp_fh), 1, fBAW);

17 Programování BMP (16/19) //BITMAPFILEHEADER copy to new BPM files fread(&bmp_ih, sizeof(bmp_ih), 1, fRGB); //old BMP fwrite(&bmp_ih, sizeof(bmp_ih), 1, fRED); fwrite(&bmp_ih, sizeof(bmp_ih), 1, fGRE); fwrite(&bmp_ih, sizeof(bmp_ih), 1, fBLU); fwrite(&bmp_ih, sizeof(bmp_ih), 1, fINV); fwrite(&bmp_ih, sizeof(bmp_ih), 1, fBAW); padd = 0; if((bmp_ih.biWidth * 3) % 4) // padding test padd = 4 - (bmp_ih.biWidth * 3) % 4;

18 Programování BMP (17/19) for(i = 0; i < bmp_ih.biHeight; i++) { for(j = 0; j < bmp_ih.biWidth; j++) { fread(&bmp_rgb, sizeof(bmp_rgb),1, fRGB); Red = bmp_rgb.rgbtRed; Gre = bmp_rgb.rgbtGreen; Blu = bmp_rgb.rgbtBlue; bmp_rgb.rgbtRed = Red; bmp_rgb.rgbtGreen = 0x00; bmp_rgb.rgbtBlue = 0x00; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fRED); bmp_rgb.rgbtRed = 0x00; bmp_rgb.rgbtGreen = Gre; bmp_rgb.rgbtBlue = 0x00; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fGRE);

19 Programování BMP (18/19) bmp_rgb.rgbtRed = 0x00; bmp_rgb.rgbtGreen = 0x00; bmp_rgb.rgbtBlue = Blu; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fBLU); bmp_rgb.rgbtRed = 0xFF - Red; bmp_rgb.rgbtGreen = 0xFF - Gre; bmp_rgb.rgbtBlue = 0xFF - Blu; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fINV); Av = (Red + Gre + Blu)/3; bmp_rgb.rgbtRed = Av; bmp_rgb.rgbtGreen = Av; bmp_rgb.rgbtBlue = Av; fwrite(&bmp_rgb, sizeof(bmp_rgb), 1, fBAW); }

20 Programování BMP (19/19) if(padd != 0) { fread(&bmp_rgb, padd, 1, fRGB); fwrite(&bmp_rgb, padd, 1, fRED); fwrite(&bmp_rgb, padd, 1, fGRE); fwrite(&bmp_rgb, padd, 1, fBLU); fwrite(&bmp_rgb, padd, 1, fINV); fwrite(&bmp_rgb, padd, 1, fBAW); } fclose(fRGB); fclose(fRED); fclose(fGRE); fclose(fBLU); fclose(fINV); fclose(fBAW); return 0; } Příklad: BPC2E_Ex98.c

21 Práce se sériovým portem (1/20) Sériový (COM) port Sériový port představuje nejjednodušší rozhraní pro spojení dvou procesorových jednotek – PC (DTE – Data Terminal Equipment) a obecně (periferního) zařízení (DCE – Data Communication Equipment) se dvěmi datovými linkami (komunikace tam a zpět je nezávislá). Sériový port může obsahovat další signální vodiče pro řízení sériového přenosu v režimu handshakingu.

22 Práce se sériovým portem (2/20) Se sériovým portem se pracuje podobně jako se souborem. Nejprve se musí otevřít (definovat proud k portu), zápisem a čtením do/z portu se provádí požadovaná komunikace. Součástí kanálu jsou buffery (vyrovnávací paměti), které tvoří datové rozhraní mezi programem a fyzickým hardwarem portu. U počítačů osazených jen USB portem, lze použít s emulátorem sériového portu (komunikace přes USB je však poloduplexní – jedna linka – data ven a pak dovnitř, ne současně). RS232 – základní standardní sériový port – definice přenosových rychlostí, signálů, úrovní napětí. Pro naše účely použijeme řadič sériového portu (pro Windows i Linux) definovaný v knihovně rs232.h, podrobnosti na: Popis nejdůležitějších funkcí knihovny rs232.h je uveden dále.

23 Práce se sériovým portem (3/20) Popis důležitých funkcí knihovny rs232.h int RS232_OpenComport(int comport_number, int baudrate, const char * mode) Otevře sériový port pro komunikaci: comport_number je číslo portu (začíná 0, ve Windows COM1 je 0, v Linuxu ttyS0 je 0), baudrate je přenosová rychlost v Bd mode je řetězec módu přenosu ve tvaru: počet datových bitů – parita – počet stopbitů Vrací 1 v případě chyby.

24 Práce se sériovým portem (4/20) int RS232_PollComport (int comport_number, unsigned char * buf, velikost int) Čte znaky ze sériového portu: buf je ukazatel do vyrovnávací paměti (řetězec), velikost je velikost vyrovnávací paměti v bajtech Vrací počet přijatých znaků do vyrovnávací paměti. int RS232_SendByte (int comport_number, unsigned char byte) Odešle byte byte přes sériový port. Vrací 1 v případě chyby.

25 Práce se sériovým portem (5/20) int RS232_SendBuf (int comport_number, unsigned char * buf, velikost int) Odešle více bytů přes sériový port: buf je ukazatel do vyrovnávací paměti, velikost je velikost vyrovnávací paměti v bajtech. Vrací -1 v případě chyby, jinak vrátí počet bajtů odeslaných. void RS232_cputs (int comport_number, const char * text) Odešle řetězec text přes sériový port. Řetězec musí být zakončen znakem null.

26 Práce se sériovým portem (6/20) void RS232_CloseComport (int comport_number) Zavře sériový port pro komunikaci. Další funkce knihovny rs232.h jsou určeny pro monitoring a ovládání handshakových signálů, více informací lze nalézt na:

27 Práce se sériovým portem (7/20) V následujících příkladech budeme prostřednictvím sériového portu ovládat řízený laboratorní zdroj Manson SDP2405. Sériový port je nutno nakonfigurovat na přenosovou rychlost 9600 Bd, bez parity s jedním stop bitem (více o RS232 např. na Řídicí příkazy pro tento zdroj jsou vždy textové řetězce zakončené znakem '\r'. Seznam příkazů: SESS00 – otevření komunikace s laboratorním zdrojem. Znaky 00 jsou povinné a zastupují adresu i v případě komunikace po RS-232, kdy z principu není žádná adresa požadována. Po vykonání tohoto příkazu se na zdroji objeví indikace REMOTE; ENDS00 – uzavření komunikace s laboratorním zdrojem;

28 Práce se sériovým portem (8/20) ENDS00 – uzavření komunikace s laboratorním zdrojem; VOLT00XXX – nastavuje požadované napětí na zdroji v rozmezí 1 až 40 V. Příkaz se skládá ze tří částí: VOLT – uvozuje nastavení napětí, 00 – povinná část zastupující adresu a XXX – které přestavují požadovanou hodnotu napětí ve stovkách mV. Například pro nastavení 7,5 V bude zaslaný příkaz ve tvaru VOLT Nezapomenout na první nulu před číslem 75 ; CURR00YYY – nastavuje požadovanou hodnotu výstupního proudu v rozmezí 0 až 5 A. Při dosažení této hodnoty přejde laboratorní zdroj do režimu konstantního zdroje proudu. Hodnota YYY má význam Y,YY A. Například pro proudové omezení na 300 mA je tedy nutné odeslat příkaz CURR00030 ; SOUT000 – připojení výstupních svorek. Po provedení tohoto příkazu se aktivuje výstup laboratorního zdroje;

29 Práce se sériovým portem (9/20) SOUT001 – slouží pro deaktivaci výstupu; GETD00 – slouží pro vyčítání aktuálních hodnot napětí, které je aktuálně na výstupních svorkách a proudu, který protéká výstupními svorkami zdroje. Tvar návratového řetězce je: VVVVCCCCM, kde VVVV je napětí v desítkách mV, CCCC je proud v mA a M indikuje, zda je zdroj v režimu proudového omezení (hodnota 1, jinak 0 ) Např reprezentuje svorkové napětí 7,49 V a protékající proud 0,306 A.

30 Práce se sériovým portem (9/20) Příklad: Sestavte program, který bude blikat se žárovkou 24 V/ 100 W připojenou ke zdroji Manson s periodou cca 0,5 s. K emulaci funkce blikání použijeme příkazy SOUT000 a SOUT001, časový definujeme pomocí funkce usleep() z knihovny unistd.h, kde parametrem je čas „uspání“ v mikrosekundách. Nejprve si sestavíme pomocnou funkci, která odešle řetězec na výstup sériového portu a přečte stav vstupního bufferu včetně implementace uspávacích intervalů. #include #include "rs232.h"

31 Práce se sériovým portem (10/20) int comtxrx(char *str, int cport) { char rx_str[21]; int m,n; printf("\r "); printf("\rSENT: %s \t", str); strcat(str, "\r"); RS232_cputs(cport, str); usleep(250000); // sleep for 0.25 second n=RS232_PollComport(cport, rx_str, 20); if(n>0) { printf("RECEIVED: "); for(m=0; rx_str[m]!='\0'; m++) if(rx_str[m]!='\n' && rx_str[m]!='\r') putchar(rx_str[m]); } usleep(250000); // sleep for 0.25 second return 0; } int comtxrx(char *str, int cport) { char rx_str[21]; int m,n; printf("\r "); printf("\rSENT: %s \t", str); strcat(str, "\r"); RS232_cputs(cport, str); usleep(250000); // sleep for 0.25 second n=RS232_PollComport(cport, rx_str, 20); if(n>0) { printf("RECEIVED: "); for(m=0; rx_str[m]!='\0'; m++) if(rx_str[m]!='\n' && rx_str[m]!='\r') putchar(rx_str[m]); } usleep(250000); // sleep for 0.25 second return 0; }

32 Práce se sériovým portem (11/20) int main() { int cport_nr; // COM port number int cport_bdr=9600; // COM port baudrate 9.6 kBd char cport_mode[]={'8','N','1',0};// COM port mode //- 8 bits, no parity, 1 stopbit, no control char tx_str[20]; // transmitting string printf("Insert COM port number: "); scanf("%d", &cport_nr); if(RS232_OpenComport(cport_nr-1, cport_bdr, cport_mode)) { printf("\nCan not open comport\n"); printf("Press ENTER"); getchar(); return(0); }

33 Práce se sériovým portem (12/20) else printf("\nComport is open!\n"); strcpy(tx_str, "SESS00"); comtxrx(tx_str,cport_nr-1); strcpy(tx_str, "CURR00500"); comtxrx(tx_str,cport_nr-1); strcpy(tx_str, "VOLT00240"); comtxrx(tx_str,cport_nr-1); while(1) { strcpy(tx_str, "SOUT000"); comtxrx(tx_str,cport_nr-1); strcpy(tx_str, "SOUT001"); comtxrx(tx_str,cport_nr-1); } return(0); } Příklad: BPC2E_Ex99.c + rs232.h

34 Práce se sériovým portem (13/20) Příklad: Sestavte program, který pomocí zdroje Manson změří ampérvoltovou charakteristiku žárovky 24 V/ 100 W, výsledky nechť jsou uloženy jako formát CSV. Port a jméno souboru jsou parametry při spouštění programu. Program bude postupně nastavovat napětí na výstupních svorkách zdroje pomocí příkazu VOLT00XXX a pomocí příkazu GETD00 bude vyčítat skutečnou změřenou hodnotu napětí a proudu. CSV (Comma-separated values) je jednoduchý textový formát pro ukládání číselných hodnoty oddělených čárkami (nebo středníky). Je určený pro výměnu tabulkových dat a umožňuje snadný přenos např. do MS Excelu (oddělovač středník). Budeme uvažovat následující formu: napětí';'proud'\n'

35 Práce se sériovým portem (14/20) int comtxrx(char *t_str, char *r_str, int cport) { int m,n; strcat(t_str, "\r"); RS232_cputs(cport, t_str); usleep(250000); // sleep for 0.25 second n=RS232_PollComport(cport, r_str, 20); for(m=0; r_str[m]!='\r' && r_str[m]!='\0'; m++); if(r_str[m]=='\r') r_str[m]='\0'; return 0; } Upravená funkce pro zápis a čtení textových zpráv ze sériového portu.

36 Práce se sériovým portem (15/20) int main(int argc, char *argv[]) { int cport_nr; // COM port number int cport_bdr=9600; // COM port baudrate 9.6 kBd char cport_mode[]={'8','N','1',0};// COM port mode //- 8 bits, no parity, 1 stopbit, no control char tx_str[20]; // transmitting string char rx_str[20]; // received string char test; char file_name[20]; double volt, volt_incr; char str_volt[20], str_curr[20]; char csv_str[13]; FILE *ptrf; int slen, i, j; int csv_ind[]={0, 1, 3, 4, 6, 8, 9, 10}; Hlavní program

37 Práce se sériovým portem (16/20) if(argc!=3) { printf("\nError: Incorrect number of parameters!\n"); printf("Press ENTER"); getchar(); return 0; } slen=strlen(argv[1]); if(slen>3) { printf("\nError: Incorrect characters in the COM port number!\n"); printf("Press ENTER"); getchar(); return 0; }

38 Práce se sériovým portem (17/20) else { test=1; for(i=0; i<(slen-1); i++) if(!isdigit(argv[1][i])) test=0; if(test) cport_nr=atoi(argv[1])-1; else { printf("\nError: COM port number consists non-numeric character!\n"); printf("Press ENTER"); getchar(); return 0; }

39 Práce se sériovým portem (18/20) if(RS232_OpenComport(cport_nr, cport_bdr, cport_mode)) { printf("\nCan not open comport\n"); printf("Press ENTER"); getchar(); return(0); } else printf("\nComport is open!\n"); ptrf=fopen(argv[2], "w"); strcpy(tx_str, "SESS00"); comtxrx(tx_str, rx_str, cport_nr); strcpy(tx_str, "CURR00500"); comtxrx(tx_str, rx_str, cport_nr);

40 Práce se sériovým portem (19/20) strcpy(tx_str, "VOLT00000"); comtxrx(tx_str, rx_str, cport_nr); strcpy(tx_str, "SOUT000"); comtxrx(tx_str, rx_str, cport_nr); csv_str[2]=','; csv_str[5]=';'; csv_str[7]=','; csv_str[11]='\n'; csv_str[12]='\0'; volt_incr=0.1; for(volt=2; volt<=24; volt+=volt_incr) { sprintf(str_volt, "%d", (int)(volt*10)); strcpy(tx_str, "VOLT00"); if(volt<1) strcat(tx_str, "0"); if(volt<10) strcat(tx_str, "0"); strcat(tx_str, str_volt);

41 Práce se sériovým portem (20/20) printf("%s\n", tx_str); comtxrx(tx_str, rx_str, cport_nr); strcpy(tx_str, "GETD00"); comtxrx(tx_str, rx_str, cport_nr); printf("%s\n", rx_str); for(i=0; i<8; i++) csv_str[csv_ind[i]]=rx_str[i]; fprintf(ptrf, "%s", csv_str); } fclose(ptrf); strcpy(tx_str, "SOUT001"); comtxrx(tx_str, rx_str, cport_nr); strcpy(tx_str, "ENDS00"); comtxrx(tx_str, rx_str, cport_nr); return(0); } Příklad: BPC2E_Ex100.c + rs232.h

42 Téma následující přednášky – Úvod do objektově orientovaného programování a C++ DĚKUJI ZA POZORNOST


Stáhnout ppt "OSNOVA: a) Programování BMP b) Práce se sériovým portem Jiří Šebesta Ústav radioelektroniky, FEKT VUT v Brně Počítače a programování 2 pro obor EST BPC2E."

Podobné prezentace


Reklamy Google