Ce este bmp în informatică. Care este extensia de fișier BMP? Stocarea datelor în format bmp

Acest articol este despre cum arată formatul grafic bmp. Deși acesta este unul dintre formatele mai simple, datorită faptului că există multe variante ale acestui format, nu toate punctele sunt evidente. Deci, nu mai turnați apă, să începem.

Structuri de format

Formatul bmp (din cuvintele BitMaP - bit map, sau, în rusă, bit array) este o imagine necomprimată (în mare parte) care este destul de ușor de citit și afișat în sistemul de operare Windows, care are funcții speciale API care ajută.

Mai întâi, să oferim o reprezentare grafică a datelor în bmp (imagine luată de pe MSDN).

La început există un antet de fișier (BITMAPFILEHEADER). Este descris după cum urmează:

bfType determină tipul fișierului. Aici ar trebui să fie BM. Dacă deschideți orice fișier BMP într-un editor de text (sau mai bine zis, într-un editor hexazecimal), veți vedea că primele două caractere sunt BM (din cuvântul BitMap, așa cum probabil ați ghicit deja).
bfSize este dimensiunea fișierului în sine în octeți. Strict vorbind, ar trebui să îl calculați (ceea ce este recomandat), dar am setat greșit dimensiunea fișierului (deși nu intenționat :)) și nu au fost probleme (ACDSee a citit fără probleme, programul meu a funcționat), dar nu vă recomand scrieți-o intenționat incorect, dintr-o dată va apărea un program conștiincios care va compara această dimensiune cu cea reală și va decide că nu este bmp, ci altceva. În mod ideal, toate programele, pentru a se asigura că acesta este un bmp real și nu un fals, ar trebui, în primul rând, să verifice dacă bfType conține „BM” (fără ghilimele) și, în al doilea rând, că bfSize este egal cu dimensiunea fișierului .
bfReserved1 și bfReserved2 sunt rezervate și trebuie să fie zero.
bfOffBits. Acesta este unul dintre cele mai importante domenii din această structură. Arată unde începe bitmap-ul în sine față de începutul fișierului (sau, după cum spune MSDN, „de la începutul structurii BITMAPFILEHEADER”), care descrie imaginea. Adică, pentru a fi garantat că ajungeți la începutul matricei, trebuie să scrieți:

typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LONG biWidth;
LUNG biÎnălțime;
biplanuri WORD;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
) BITMAPINFOHEADER, * PBITMAPINFOHEADER;

biSize este dimensiunea structurii în sine. Acesta trebuie inițializat după cum urmează: bih.biSize = sizeof(BITMAPINFOHEADER);
Aici vom presupune din nou că bih este declarat după cum urmează: BITMAPINFOHEADER bih;
biWidth și biHeight setați lățimea și, respectiv, înălțimea imaginii în pixeli.
biAvioane specifică numărul de avioane. Deocamdată este întotdeauna setat la 1.
biBitCount- Numărul de biți pe pixel. Vom vorbi mai multe despre asta mai jos.
bicompresie indică tipul de compresie. Nu fi surprins sau speriat că bmp experimentează brusc compresie. Eu personal nu am văzut mai mult de un bmp comprimat (dar nu spun că nu există). Dacă nu există compresie, atunci acest flag trebuie setat la BI_RGB. În acest articol vorbim despre formatul necomprimat, așa că nici măcar nu voi enumera alte steaguri. Se pare că aceeași structură este folosită în fișiere JPEG si PNG, pentru ca, incepand cu Windows 98, aici au aparut optiunile BI_JPEG, ceea ce arata ca aceasta poza este JPEG si BI_PNG, ca este PNG (nu stiu nimic despre formatul Jpeg, doar am facut aceste concluzii in functie de ceea ce este scris în MSDN).
biSizeImage indică dimensiunea imaginii în octeți. Dacă imaginea este necomprimată (adică câmpul anterior este setat la BI_RGB), atunci ar trebui scris un zero aici. biXPelsPerMeterȘi biYPelsPerMeter denotă, respectiv, rezoluția orizontală și verticală (în pixeli pe metru) a dispozitivului final pe care va fi scos bitmap-ul (raster). O aplicație poate folosi această valoare pentru a selecta dintr-un grup de resurse cel mai potrivit bitmap pentru dispozitivul dorit. Faptul este că formatul bmp este în esență un raster independent de hardware, adică când aspect ceea ce se întâmplă nu depinde de ceea ce este proiectat acest raster (ca să spunem așa). De exemplu, o imagine va arăta la fel, indiferent dacă este desenată pe un ecran de monitor sau imprimată pe o imprimantă. Dar rezoluția dispozitivelor este diferită și tocmai pentru a selecta cea mai potrivită imagine dintre cele disponibile sunt utilizați acești parametri.
biClrUsed determină numărul de culori utilizate din tabel. Dacă această valoare este zero, atunci rasterul utilizează numărul maxim de culori permis de valoarea biBitCount. Acest lucru este relevant doar pentru imaginile comprimate. Dacă biClrUsed este diferit de zero și biBitCount este mai mic de 16, atunci biClrUsed determină numărul curent de culori disponibile pentru motorul grafic sau driverul de dispozitiv. Dacă biBitCount este mai mare sau egal cu 16, atunci biClrUsed determină dimensiunea tabelului de culori utilizat pentru a optimiza paleta curentă a sistemului.
biClrImportant- acesta este numărul de culori importante. Determină numărul de culori necesare pentru a reprezenta desenul. Dacă această valoare este 0 (cum este de obicei), atunci toate culorile sunt considerate importante.

Tipuri de format BMP

Toate tipurile de format bmp conditionat poate fi împărțit în două tipuri: paletă și non-paletă. Adică dacă paleta este folosită într-un format dat sau nu. Vă rugăm să rețineți că paleta poate fi chiar și în formate fără paletă, dar nu este folosită acolo. În bmps fără paletă, culoarea este calculată direct din biții care intră în fișier, începând dintr-un anumit loc. Și în palete, fiecare octet descrie unul sau mai mulți pixeli, iar valorile octetului (sau biților) sunt indicele de culoare din paletă. Pentru început, voi oferi un tabel care să compare opțiuni posibile. Tipul de imagine (paletă sau fără paletă) depinde de câți biți sunt dați pe pixel, adică de valoarea biBitCount a structurii BITMAPINFOHEADER.

biBitCountFormat paletă sau fără paletăNumăr maxim posibil de culoriNote 1 Paletă2 O imagine de paletă în două culori, nu neapărat alb-negru. Dacă bitul raster (care este chiar mai jos) este resetat (egal cu 0), atunci aceasta înseamnă că prima culoare din paletă ar trebui să fie în acest loc, iar dacă este setată (egal cu 1), atunci a doua. 4 Paletă16 Fiecare octet descrie 2 pixeli. Iată un exemplu din MSDN Dacă primul octet din imagine este 0x1F, atunci acesta corespunde la doi pixeli, culoarea primului este a doua culoare din paletă (deoarece numărătoarea inversă începe de la zero), iar al doilea pixel este. a 16-a culoare a paletei. 8 Paletă256 Una dintre cele mai comune opțiuni. Dar, în același timp, cele mai simple. Paleta ocupă un kilobyte (dar este mai bine să nu contați pe ea). Un octet este o culoare. Mai mult, valoarea sa este numărul culorii din paletă. 16 Fără paletă2^16 sau 2^15Aceasta este cea mai confuză opțiune. Să începem cu faptul că nu are paletă, adică la fiecare doi octeți (unul cuvânt CUVÂNT) într-un raster definiți în mod unic un pixel. Dar iată ce se întâmplă: există 16 biți și există 3 componente de culoare (roșu, verde, albastru). Dar 16 nu vrea să fie împărțit la 3. Prin urmare, aici există două opțiuni. Primul este să folosiți nu 16, ci 15 biți, apoi există 5 biți pentru fiecare componentă de culoare. Deci putem folosi maximum 2^15 = 32768 culori și obținem triplu R-G-B= 5-5-5. Dar atunci o bucată întreagă din 16 este irosită în zadar. Dar se întâmplă că ochii noștri, printre toate culorile, percep mai bine verdele, așa că am decis să dăm un pic componenta verde, adică atunci obținem. triplu R-G-B = 5-6-5, iar acum putem folosi 2^16 = 65536 culori. Dar cel mai neplăcut lucru este că sunt folosite ambele opțiuni. MSDN sugerează că, pentru a distinge câte culori sunt utilizate, completați câmpul biClrUsed din structura BITMAPINFOHEADER cu această valoare. Pentru a selecta fiecare componentă, trebuie să utilizați următoarele măști. Pentru formatul 5-5-5: 0x001F pentru componenta albastră, 0x03E0 pentru verde și 0x7C00 pentru roșu. Pentru formatul 5-6-5: 0x001F - albastru, 0x07E0 - verde și, respectiv, 0xF800 componente roșii. 24 Fără paletă2^24 Și acesta este cel mai simplu format. Aici 3 octeți definesc 3 componente de culoare. Adică o componentă pe octet. Citim pur și simplu structura RGBTRIPLE și folosim câmpurile sale rgbtBlue, rgbtGreen, rgbtRed. Ei merg în ordinea aceea. 32 Fără paletă2^32 Aici 4 octeți definesc 3 componente. Dar, totuși, un octet nu este utilizat. Poate fi folosit, de exemplu, pentru canalul alfa (transparență). În acest caz, este convenabil să citiți rasterul folosind structuri RGBQUAD, care sunt descrise după cum urmează:

Stocarea datelor în format bmp

Ei bine, acum ajungem la partea cea mai interesantă. După structurile BITMAPFILEHEADER și BITMAPINFOHEADER vine paleta. Mai mult, dacă formatul nu are paletă, atunci s-ar putea să nu existe, totuși, nu ar trebui să contați pe el. Cert este că, atunci când tocmai începeam să înțeleg formatul bmp, am citit într-o carte că, se presupune că, dacă formatul nu are paletă, atunci nu are deloc paletă. Au fost chiar și două imagini - diagrame de format: una cu o paletă, cealaltă fără. Și la vremea aceea scriam un program care funcționează cu sârguință cu fișiere bmp. Și a trebuit să convertesc imaginile primite de la 256 de culori la 24 de biți (dacă există) în fișiere temporare. Și pur și simplu nu am creat o paletă pe 24 de biți (bfOffBits din structura BITMAPFILEHEADER a fost egală cu suma sizeof(BITMAPINFOHEADER) + sizeof (BITMAPINFOHEADER) și le-am lăsat neschimbate pe cele primite pe 24 de biți. Cu rasterele de 256 de culori totul a funcționat așa cum ar trebui, până când nu am dat peste o imagine pe 24 de biți care avea gunoi afișat în partea de jos în loc de partea necesară, nu am înțeles imediat ce era în neregulă până când am comparat dimensiunea. fișier sursă cu teoreticul, care ar fi trebuit să fie dacă nu ar exista paletă. Diferența s-a dovedit a fi exact 1 KB (exact 1024 de octeți). Era o paletă acolo. Prin urmare, nu vă bazați niciodată dacă există o paletă sau nu vă bazați pe dimensiunea acesteia (deși toate imaginile pe care le-am întâlnit aveau o dimensiune a paletei de 256 de culori, sau 1Kb), treceți întotdeauna prin fișier la începutul rasterului folosind bfOffBits. Paleta este o serie de structuri RGBQUAD care vin una după alta. Chiar dacă nu toate culorile sunt folosite în paletă (dar numai, de exemplu, 16), atunci adesea 256 de câmpuri sunt încă alocate pentru paletă. Și 256 * 4 = 1024, unde 4 este dimensiunea structurii RGBQUAD, adică se obține același kilobyte.

Imediat după paletă vine rasterul în sine. Aici lucrurile devin mai confuze. În primul rând, pixelii sunt descriși aici așa cum sunt scrise în tabelul de mai sus, în funcție de format. Și ele însele pot conține valoarea componentelor de culoare (pentru cele fără paletă), sau pot fi indecși ai unei matrice de palete. Imaginea în sine este înregistrată rând cu rând. În al doilea rând, imaginea pare să fie cu susul în jos. Adică linia de jos este scrisă mai întâi, apoi penultima linie și așa mai departe până în partea de sus. Și în al treilea rând, așa cum este scris, dacă dimensiunea liniei raster nu este un multiplu de 4, atunci aceasta este umplută cu 1 până la 3 octeți goli (zero), astfel încât lungimea liniei să fie un multiplu al paragrafului. Acesta este cel mai neplăcut lucru. Faptul este că pentru fiecare format trebuie să ajustați acest număr de octeți goli (deși îmi place să scriu o parte din paletă acolo, pur și simplu nu vreau să creez variabile suplimentare „zero” dacă acești octeți sunt oricum săriți și nimeni are nevoie de ele). Ofer un tabel cu formule care arată pentru ce format câți octeți trebuie adăugați la sfârșitul liniei. Acolo, variabila Width, după cum ați putea ghici, înseamnă lățimea imaginii. Toate aceste formule au fost stabilite experimental. Voi da un exemplu doar pentru cele mai utilizate formate. În rest, îl poți scrie singur.

Exemple de programe

Puteți descărca toate sursele, nu voi scrie prea multe aici. Voi da doar funcțiile cu comentarii.

Bună ziua 1. Crearea unei imagini în format bmp.
Aici este creată o imagine monocromatică. Există trei exemple de astfel de funcții: crearea bmp 8, 16 și 24 de biți. Voi da doar pentru 16 biți.

// Să creăm o imagine în format bmp 16 biți ca 5-5-5, care va fi pur și simplu monocromatic
void CreateBmp555(char * fname, WORD culoare)
{
MÂNERUL hFile;
DWORD RW;
int i, j;

// Declară structurile necesare
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
BYTE Palette[1024];

// Paleta
// Să avem o imagine de 35 x 50 pixeli
int Latime = 35 ;

int Înălțime = 50 ; memset(Palette, 0, 1024);
// În paletă avem zerouri, umpleți-le

memset (&bfh, 0 , sizeof (bfh) ) ; Bfh.bfType = 0x4D42 ;
// Să notăm că acesta este bmp "BM" bfh.bfOffBits = dimensiunea (bfh) + dimensiunea (bih) + 1024;
// Paleta ocupă 1 Kb, dar nu o vom folosi
bfh.bfSize = bfh.bfOffBits +
sizeof(culoare) * Latime * Inaltime + Înălțime * ((dimensiunea (culoarea) * Lățime) % 4 ) ;
// Calculați dimensiunea fișierului final
memset (&bih, 0 , sizeof (bih) ) ;
bih.biSize = sizeof(bih); // Asa ar trebui sa fie
bih.biBitCount = 16; // Folosim 5-5-5
bih.biCompression = BI_RGB;
// Fără compresie
bih.biHeight = Înălțime;
bih.biWidth = Latime;
bih.biPlanes = 1 ;

// Ar trebui să fie 1
// Și câmpurile rămase rămân 0
HFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);

dacă (hFișier == INVALID_HANDLE_VALUE)
întoarcere ;
// Scrieți anteturile

WriteFile (hFile, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile (hFile, & bih, sizeof (bih) , & RW, NULL ) ;
// Scrieți paleta< Height; i++ )
{
WriteFile(hFile, Palette, 1024, &RW, NULL);< Width; j++ )
{
pentru (i = 0; i
}

pentru (j = 0; j
WriteFile (hFișier, & culoare, dimensiunea (culoare) , & RW, NULL ) ;
}
// Aliniați-vă la chenar
}

WriteFile (hFile, Palette, (dimensiunea (culoare) * Width) % 4 , & RW, NULL ) ;

CloseHandle(hFile);

culoare - culoarea imaginii. Valoarea acestei variabile trebuie completată conform primului tabel. Puteți vizualiza imaginea rezultată în ACDSee, de exemplu. Tocmai am încercat să-l deschid în Photoshop, dar s-a dovedit că nu le poate citi în acest format, dar poți :).
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
Exemplul 2. Conversia unei imagini din formatul de 8 biți (256 de culori) în 24 de biți.
BOOL Convert256To24 (char * fin, char * fout)
int Latime, Inaltime;
Paleta RGBQUAD[ 256 ] ;
BYTE * inBuf;
DWORD RW;
RGBTRIPLE * outBuf;
int i, j;

MÂNERE hIn, hOut;
DWORD OffBits;
HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ;

dacă (hIn == INVALID_HANDLE_VALUE)
returnează FALSE;
{
HOut = CreateFile(fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ;
}

if (hOut == INVALID_HANDLE_VALUE)
CloseHandle(hIn);
// Citiți datele
ReadFile (hIn, & bfh, sizeof (bfh) , & RW, NULL ) ;

ReadFile (hIn, & bih, sizeof (bih) , & RW, NULL ) ;
ReadFile (hIn, Palette, 256 * sizeof (RGBQUAD) , & RW, NULL ) ;
// Setați indicatorul la începutul rasterului
SetFilePointer (hIn, bfh.bfOffBits, NULL, FILE_BEGIN) ;
Width = bih.biWidth ;

Height = bih.biHeight ;
OffBits = bfh.bfOffBits ;
// Alocați memorie

inBuf = nou BYTE [Width];
outBuf = nou RGBTRIPLE [ Width ] ; // Completați anteturile
bfh.bfOffBits = sizeof (bfh) + sizeof (bih) ;
// Să nu scriem o paletă

bih.biBitCount = 24;
dacă (hFișier == INVALID_HANDLE_VALUE)
bfh.bfSize = bfh.bfOffBits + 4 * Lățimea * Înălțimea + Înălțimea * (Lățimea % 4 ) ;
// Mărime fișier

// Iar restul rămâne neschimbat
// Scrieți paleta< Height; i++ )
{
WriteFile (hOut, & bfh, sizeof (bfh) , & RW, NULL ) ;
WriteFile(hFile, Palette, 1024, &RW, NULL);< Width; j++ )
{
WriteFile (hOut, & bih, sizeof (bih) , & RW, NULL ) ;
outBuf[ j].rgbtGreen = Paleta[ inBuf[ j] ] .rgbGreen ;
outBuf[ j].rgbtBlue = Paleta[ inBuf[ j] ] .rgbBlue ;
}
WriteFile (hOut, outBuf, sizeof (RGBTRIPLE) * Width, & RW, NULL );

// Scrie gunoi pentru aliniere
WriteFile (hOut, Palette, Width % 4 , & RW, NULL ) ;
SetFilePointer(hIn, (3 * Width) % 4, NULL, FILE_CURRENT) ;
}

șterge inBuf;
șterge afară Buf;
HOut = CreateFile(fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
CloseHandle(hOut);
returnează TRUE;
}

Numele fișierelor sursă și, respectiv, destinație trebuie trecute funcției.

Cum să ascundeți textul într-o imagine bitmap. Din păcate, nu am găsit niciun subiect pe această temă și am decis să umplu acest gol. Sub tăietură veți găsi o modalitate de a ascunde textul într-un bitmap, precum și o implementare în C#.

Formularea problemei

Ascundeți textul arbitrar din codificarea Windows-1251 într-o imagine bitmap pe 24 de biți și scoateți-l înapoi fără distorsiuni.

structura fișierului bmp

În primul rând, permiteți-mi să vă reamintesc ce este un fișier bitmap. Sunt sigur că știi toate acestea foarte bine, doar că va fi mai clar să descrii algoritmul pentru ascunderea textului pe baza materialului prezentat. Asa de. Orice fișier bmp este format din patru părți:
  1. Antetul fișierului
  2. Titlul imaginii (poate lipsi)
  3. Paleta (poate lipsi)
  4. Imaginea în sine
Antetul fișierului conține informații de serviciu, inclusiv adâncimea de biți a imaginii. Apropo, paleta nu este folosită pentru un desen pe 24 de biți. Deoarece am precizat clar în sarcină că vom lucra numai cu imagini pe 24 de biți, în mod ideal putem verifica imaginea de intrare pentru a respecta cerințele.
Acum să trecem la imaginea în sine. După cum știți, formatul bmp nu oferă compresie în mod implicit (deși există suport pentru compresie folosind algoritmul RLE). Astfel, fiecare pixel în cazul nostru este codificat cu 24 de biți, câte un octet pentru fiecare componentă de culoare. Prin urmare, putem codifica nici mai mult, nici mai puțin, ci exact 16777216 culori. Pentru claritate, iată o poză:

Ideea unui algoritm de ascundere a textului

Probabil ai ghicit deja care este ideea. Chestia este că ochiul unei persoane obișnuite (nu un artist sau fotograf profesionist) distinge mult mai puține culori decât cele indicate mai sus. Nicio carte nu are un răspuns clar la întrebarea câte culori poate distinge ochiul, dar cea mai mare cifră pe care am întâlnit-o este de 10 milioane. Rezultă că mai multe dintre cele opt biți alocate fiecărei componente de culoare pot fi împrumutați pentru scopurile noastre egoiste.
Câteva numere: de exemplu, să luăm și să scădem flagrant doi biți de ordin scăzut din componenta RGB. Adică din 24 de biți ne vor mai rămâne 18, care pot codifica exact 262144 de culori. Acum să luăm text în codificarea Windows-1251, în care fiecare caracter este reprezentat de 8 biți. Prin simplu calcule matematice constatăm că 3 caractere pot fi stocate în 4 pixeli. Astfel, într-o imagine de 1024x768, unde sunt 786432 pixeli, poți stoca 589824 caractere. Nu-i rău, nu? Pentru claritate, voi da două poze. Pe primul este imaginea originală, iar pe al doilea este o imagine în care cei doi biți mai puțin semnificativi din fiecare componentă de culoare sunt umpluți cu text. Permiteți-mi să fac o rezervare imediat că imaginile sunt convertite în png pentru a economisi trafic.

Imaginea originală:


Imagine care conține text


Dacă te uiți cu atenție, culorile apar mai terne în a doua imagine. Da, este. Dar tu și cu mine știm că este ceva în neregulă în imaginea prezentată și, dacă nu am fi știut, nu am fi ghicit că există un fel de text ascuns în ea. Apropo, în imagine este ascunsă sintagma „Hello World!!! =)" înmulțit de 100 de ori.
Asta e tot. După cum puteți vedea, ideea este extrem de simplă. Apropo, metoda prezentată se numește LSB (mulțumesc lui Frol pentru pont). În cele din urmă, puteți privi implementarea în C#.

Implementare in C#

Implementarea prezentată nu se califică pentru un „Cod perfect” demonstrează doar algoritmul descris în practică. În acest caz, nu urmăream frumusețea codului, ci mai degrabă claritatea.

În lecția de astăzi ne vom uita la primul format de fișier de pe calea noastră. Diferite formate de fișiere sunt concepute pentru a stoca informații diferite. Fiecare format specifică o modalitate de organizare a datelor într-un fișier.

Vom cunoaște multe formate de fișiere diferite: imagini, modele tridimensionale, fișiere audio, fișiere video. Să începem cu unul dintre cele mai simple formate grafice - BMP.

BMP - bitmap - bitmap. Conceptul de „mapping” este preluat din matematică. În matematică, o mapare este foarte apropiată de conceptul de funcție. Pentru simplitate, considerați cuvântul bitmap ca fiind o imagine (chiar dacă nu este).

Informații despre fișierul BMP

Fiecare fișier bitmap are un antet de 14 octeți. Câmpuri pentru acest antet:

2 octeți. șir BM (pe Windows).
4 octeți. Dimensiunea fișierului în octeți.

2 octeți. Câmp rezervat. Trebuie inițializat la zero.
4 octeți. Adresa de la care începe imaginea în sine. Sau cu alte cuvinte - o compensare față de începutul imaginii.

Să creăm o imagine de 100x100 pixeli. Fiecare pixel ocupă 32 de biți. Antetul fișierului va arăta astfel:

B.M.
14+40+100*100*4
0
0
14+40

Notă importantă: aceste numere sunt de fapt stocate ca o secvență de octeți. Sper că acest lucru este clar. Aici (și în exemplul următor) le-am aranjat într-o coloană pentru a ușura percepția.

Să ne ocupăm de al doilea domeniu. 14 - dimensiunea antetului fișierului. 40 este dimensiunea titlului imaginii (mai multe despre el mai jos), 100*100 este numărul de pixeli. Și în plus, deoarece am convenit că fiecare pixel va ocupa 32 de biți (4 octeți), trebuie să înmulțim numărul de pixeli cu patru.

Ultimul câmp: imaginea în sine începe imediat după antetul fișierului (14 octeți) și antetul imaginii (40 octeți).

Informații despre imagine BMP (antet imagine)

Există mai multe versiuni de BMP. Puteți determina versiunea după dimensiunea titlului imaginii. Vom folosi versiunea Windows V3, care ocupă 40 de octeți. Alte versiuni au 12, 64, 108, 124 de octeți.

În WinAPI pentru stocarea bmp versiuni Windows V3 utilizează structura BITMAPINFOHEADER.

Câmpuri de antet Windows V3:

4 octeți. Dimensiunea antetului. Întotdeauna setat la 40 de octeți.
4 octeți. Lățimea imaginii în pixeli.
4 octeți. Înălțimea imaginii în pixeli.
2 octeți. Acest câmp conține întotdeauna unul.
2 octeți. Adâncimea culorii este numărul de biți dintr-un pixel.
4 octeți. Metoda de compresie.
4 octeți. Marimea imaginii. Mărimea imaginii în sine este indicată aici - fără a ține cont de dimensiunea antetelor.
4 octeți. Rezoluție orizontală în pixeli pe metru (numărul de pixeli dintr-un metru).
4 octeți. Rezoluție verticală în pixeli pe metru (numărul de pixeli dintr-un metru).
4 octeți. Numărul de culori din paletă.
4 octeți. Numărul de culori importante din paletă.

Acum să vedem cum va arăta titlul imaginii în cazul nostru:

40
100
100
1
32
0
100*100*4
2795
2795
0
0

Pentru metoda de compresie, am ales 0 - fără compresie. Alte valori sunt posibile. Printre cele interesante: BI_JPEG (valoare - 4) - compresie folosită în imaginile jpeg și BI_PNG (valoare - 5) - compresie folosită în imaginile png.

Am setat rezoluția orizontală și verticală la 2795. În majoritatea editori grafici Când creați o imagine, rezoluția este setată la 71 de pixeli pe inch (ppi - pixel pe inch)). Deci, 71ppi este 2795 pixeli pe metru. Rezoluția este utilizată pentru a da lungimea fizică a imaginii (de exemplu, pentru ieșire către o imprimantă).

După titluri există o paletă de culori. Dacă nu este acolo, atunci imaginea începe imediat după titluri. Nu vom lua în considerare imaginile cu palete deocamdată.

Date de imagine BMP

O imagine este formată din pixeli. Formatul pixelilor este determinat de adâncimea culorii (vezi mai sus). În exemplul nostru am folosit 32 de biți pe pixel. Culoarea pe 32 de biți constă de obicei din patru canale: alfa (transparență), roșu, verde, albastru: ARGB (Alpha, Red, Green, Blue). Uneori canalul alfa nu este utilizat, caz în care imaginea poate ocupa încă 32 de biți, pur și simplu nu acordă atenție valorilor unui canal atunci când calculează. În acest caz, numele canalelor sunt scrise după cum urmează: XRGB.

Fiecare canal ocupă 8 biți (1 octet) și poate lua 256 de valori: de la zero la 255 (0x00 la 0xff).

În bmp, imaginea este stocată linie cu linie de jos în sus, adică. Liniile de jos sunt scrise mai întâi, apoi cele de sus. Asigurați-vă de acest lucru: încărcați una dintre imaginile de la primul exercițiu și salvați doar jumătate din liniile acelei imagini într-un alt fișier.

La o adâncime de culoare de 32 de biți, canalele în bmp sunt scrise după cum urmează: BGRA. În această ordine: albastru, verde, roșu, alfa.

Dimensiunea liniei de date din imaginea bmp trebuie să fie un multiplu de patru (în octeți). Dacă nu este cazul, atunci șirul este umplut cu zerouri. Acest lucru se întâmplă dacă sunt utilizați 1,2,4,8,16,24 biți pe canal. De exemplu, avem o imagine cu o lățime de 3 pixeli și folosim o culoare de 16 biți. Lățimea liniei: 16*3 = 48 (6 octeți). Dar lungimea șirului trebuie să fie un multiplu de patru, așa că se adaugă încă doi octeți și lungimea șirului este în în acest exemplu va fi egal cu opt octeți. Deși ultimii doi octeți ai fiecărei linii nu vor fi stocați Informatii utile. Este necesar să se țină cont de condiția ca dimensiunea liniei să fie un multiplu de patru atunci când se lucrează cu imagini care nu sunt pe 32 de biți.

Acum să continuăm cu exemplul nostru și să folosim codul pentru a crea o imagine. Fiecare pixel va fi inițializat cu o culoare aleatorie:

Std::ofstream os("temp.bmp", std::ios::binary); semnătură caracter nesemnat = ("B", "M"); unsigned int fileSize = 14 + 40 + 100*100*4; unsigned int rezervat = 0; unsigned int offset = 14 + 40; unsigned int headerSize = 40; unsigned int dimensiuni = ( 100, 100 ); nesemnat scurt colorPlanes = 1; bpp scurt nesemnat = 32; unsigned int compresie = 0; unsigned int imgSize = 100*100*4; unsigned int rezoluție = (2795, 2795); unsigned int pltColors = 0; unsigned int impColors = 0; os.write(reinterpret_cast (semnătură), sizeof(semnătură)); os.write(reinterpret_cast (&fileSize), sizeof(fileSize)); os.write(reinterpret_cast (&rezervat), sizeof(rezervat)); os.write(reinterpret_cast (&offset), sizeof(offset)); os.write(reinterpret_cast (&headerSize), sizeof(headerSize)); os.write(reinterpret_cast (dimensiuni), sizeof(dimensiuni)); os.write(reinterpret_cast (&colorPlanes), sizeof(colorPlanes)); os.write(reinterpret_cast (&bpp), dimensiunea(bpp)); os.write(reinterpret_cast (&compresie), dimensiunea(compresie)); os.write(reinterpret_cast (&imgSize), sizeof(imgSize)); os.write(reinterpret_cast (rezoluție), dimensiunea (rezoluție)); os.write(reinterpret_cast (&pltColors), sizeof(pltColors)); os.write(reinterpret_cast (&impColors), sizeof(impColors)); caracter nesemnat x,r,g,b; pentru (int i=0; i< dimensions; ++i) { for (int j=0; j < dimensions; ++j) { x = 0; r = rand() % 256; g = rand() % 256; b = rand() % 256; os.write(reinterpret_cast(&b),dimensiunea(b)); os.write(reinterpret_cast (&g), dimensiunea (g)); os.write(reinterpret_cast

(&r),dimensiunea(r));

os.write(reinterpret_cast (&x),dimensiunea(x));) ) os.close();

Ca urmare a executării acestui cod, un fișier temp.bmp va fi creat în folderul cu proiectul dvs. (dacă ați rulat programul prin depanator (F5)) sau în folderul Debug al soluției (dacă ați rulat fișierul executabil .exe), care poate fi deschis în orice vizualizator de imagini. Imaginea este formată din puncte colorate.

Foarte des, atunci când lucrează cu grafică, mulți utilizatori întâlnesc imagini în

Format BMP

. Astăzi, puțini oameni știu ce este. Acum ne vom uita la formatul grafic BMP mai detaliat. Mai mult decât atât, nu vom urmări doar istoria originii și evoluției sale, dar vom oferi și câteva metode simple de convertire în alte formate populare.

Ce este formatul BMP?

Adevărat, de atunci formatul grafic BMP a suferit multe modificări. Inițial s-a presupus că structura unei imagini a fost construită pe o combinație de pătrate mici, cunoscute astăzi ca pixeli. Se crede că fiecare pixel dintr-o imagine poate conține date despre o adâncime de culoare diferită (numărul de biți pe o astfel de unitate grafică). Valorile utilizate pentru a specifica adâncimea de biți a culorii apar după cum urmează: 1, 2, 4, 8, 16, 24, 32, 48, 64 de biți.

În acest caz, pentru valori mai mici de 8, culoarea este indicată numai folosind indexul paletei (tabelului) de nuanțe, iar pentru valorile de peste indicele este preluat din modelul standard RGB. Acesta din urmă conține variații de culoare obținute prin amestecarea roșu, verde și albastru.

După cum este deja clar, cu cât adâncimea de biți este mai mare, cu atât dimensiunea imaginii finale va fi mai mare. Trebuie spus că formatul de fișier BMP, atât în ​​acele vremuri îndepărtate, cât și în zilele noastre, arată ca un fel de mastodon, deoarece dimensiunea lui este destul de mare. Acest lucru se datorează faptului că imaginea în sine este necomprimată, în comparație, de exemplu, cu același format JPG. După dimensiune fișiere cu tipuri diferite extensiile care conțin aceeași imagine pot diferi nu numai de sute - zeci de mii de ori.

Cum se deschide formatul de fișier BMP?

În ceea ce privește deschiderea imaginilor de acest tip, orice sistem de operare Windows are instrumente încorporate pentru aceasta.

Deși aplicațiile de vizualizare nu fuseseră încă create, instrumentul principal de editare a rămas nativ Program de vopsea, inclus cu orice versiune de Windows. La acel moment, această aplicație accepta exclusiv formatul BMP.

După cum este deja clar, odată cu dezvoltarea tehnologiei și evoluția formatului în sine, programul s-a schimbat și el. Astăzi, capacitățile Paint sunt mult mai mari decât cele ale versiunilor sale inițiale.

În plus, odată cu apariția programelor pentru vizualizarea și editarea graficelor, formatul fișier BMP a fost declarat în suport tehnic iar în ele. Nu este surprinzător, deoarece el a fost „străbunicul” aproape tuturor extensiilor de fișiere de imagine cunoscute astăzi.

Puteți găsi o mulțime de programe pentru lucrul cu astfel de date grafice. Printre instrumentele de vizualizare, de exemplu, în Windows, puteți utiliza instrumentul standard, printre aplicații terță parte sunt destul de populare pachete software precum ACDSee sau Irfan View și multe altele.

În ceea ce privește editarea, puteți folosi orice doriți pentru munca dvs., de exemplu, la fel Adobe Photoshop, Corel Draw sau orice alt editor grafic care are chiar și un set minim de instrumente și capabilități.

Cel mai simplu mod de a converti formatul BMP

Acum să vedem cum să schimbați formatul BMP în cele mai simple moduri. Pentru a face acest lucru, puteți utiliza aceleași editori grafici.

Dacă luăm ca exemplu aplicație standard Paint, mai întâi se deschide în el fișierul BMP dorit, după care se selectează comanda „Salvare ca...” din meniul „Fișier”, unde în rădăcină, în linia de jos (meniul drop-down), puteți găsiți formatele acceptate.

De fapt, în orice alt editor grafic, tehnologia de conversie a unui bitmap este similară cu cea descrisă mai sus. În unele aplicații puteți găsi, de asemenea, comenzi de export, care, în principiu, nu sunt deosebit de diferite, deoarece atunci când le utilizați, întreaga procedură se rezumă din nou la selectarea unui alt suport acceptat. format grafic, diferit de BMP original.

Folosind convertoare

Una dintre cele mai moduri simple, permițându-vă să convertiți un alt tip de imagine în format BMP, ca să nu mai vorbim de utilizarea standardului Instrumente Windowsși editori grafici, este utilizarea unor convertoare specializate care funcționează automat.

Totul este simplu aici. Utilizatorul adaugă fișiere grafice pentru a fi convertite în fereastra programului, apoi selectează formatul final (în acest caz BMP) și apasă butonul pentru a începe procesul de conversie. Fișierele finale din noul formular vor fi salvate în folderul a cărui locație este setată implicit în aplicație sau specificată manual.

Apropo, același lucru este valabil și pentru procesul invers, când trebuie să convertiți formatul BMP în altul.

Cu toate numeroasele programe din acest domeniu de pe Internet, puteți găsi multe resurse care vă permit să efectuați astfel de transformări online. Numai în acest caz, utilizatorul încarcă fișiere pe site, selectează formatul final și apoi descarcă rezultatul pe computerul său. De acord, în comparație cu primele două metode, nu este foarte convenabil.

Concluzie

Asta este tot ce se poate spune despre formatul grafic BMP pe scurt. Din motive evidente, latura tehnică a problemei în ceea ce privește structura fișierului nu a fost luată în considerare. Este puțin probabil ca astfel de date să spună ceva utilizatorului obișnuit.

Dar, în concluzie, aș dori să adaug câteva cuvinte despre conversia fișierelor grafice în mod specific în formatul BMP necomprimat. Desigur, versiunea sa actuală ocupă mai puțin spațiu pe disc. Dar încă diferă de tipurile de date comprimate mai moderne. În principiu, formatul BMP în sine poate fi numit chiar oarecum învechit, deoarece puțini oameni îl folosesc astăzi. Prin urmare, conversia formatelor comprimate într-un tip de fișier grafic cu o extensie .bmp la scena modernă pare clar impracticabil.

BMP(din engleza Imagine bitmap) este un format de stocare a imaginilor raster dezvoltat de Microsoft.

Funcționează cu formatul BMP o cantitate mare programe, deoarece suportul acestuia este integrat în OS Windows și OS/2. Fișierele BMP pot avea extensii .bmp, .dib și .rle. În plus, datele în acest format sunt incluse în fișierele de resurse binare RES și fișierele PE.

Microsoft a dezvoltat, de asemenea, formatele ICO și CUR pentru nevoile sale, care au o structură similară cu BMP. În plus, structurile din acest format sunt folosite de unele funcții WinAPI ale subsistemului GDI.

Adâncimea culorii în acest format poate fi 1, 2, 4, 8, 16, 24, 32, 48 de biți pe pixel, dar adâncimea de 2 biți pe pixel nu este acceptată oficial. În acest caz, pentru adâncimi de culoare mai mici de 16 biți, se utilizează o paletă cu componente full-color cu o adâncime de 24 de biți.

În formatul BMP, imaginile pot fi stocate ca atare sau folosind niște algoritmi de compresie obișnuiți. În special, formatul BMP acceptă compresia RLE fără pierderi de calitate și sistemele de operare moderne și software vă permit să utilizați JPEG și PNG (aceste formate sunt încorporate în BMP ca container).

DIB și DDB

Când utilizați formatul DIB Bitmap independent de dispozitiv, raster independent de hardware), programatorul poate accesa toate elementele structurilor care descriu imaginea folosind un pointer obișnuit. Dar aceste date nu sunt folosite pentru a controla direct ecranul, deoarece sunt întotdeauna stocate în memoria sistemului și nu în memoria video dedicată. Format pixel în memorie cu acces aleator poate diferi de formatul care trebuie stocat în memoria video pentru a indica un punct de aceeași culoare. De exemplu, formatul DIB poate folosi 24 de biți pentru a specifica un pixel, iar în acest moment adaptorul grafic poate funcționa în modul HiColor cu o adâncime de culoare de 16 biți. În acest caz, punctul roșu strălucitor va fi specificat într-un format independent de hardware cu trei octeți 0x0000ff, iar în memoria video prin cuvântul 0xF800. Când copiați o imagine pe ecran, sistemul va petrece timp suplimentar transformând codurile de culoare din formatul de 24 de biți în formatul de tampon video.

Prezentare generală a structurii fișierelor

Fișierul BMP este format din patru părți:

  1. Antetul fișierului (BITMAPFILEHEADER)
  2. Denumirea imaginii (BITMAPINFOHEADER, poate lipsi). BITMAPV4HEADER (Win95, NT4.0) BITMAPV5HEADER (Win98/Me, 2000/XP)
  3. Paleta (poate lipsi)
  4. Imaginea în sine

BITMAFILEHEADER

Această structură conține informații despre tipul, dimensiunea și reprezentarea datelor din fișier. Dimensiune 14 octeți.

Typedef struct tagBITMAPFILEHEADER (WORD bfType; // offset 0 octeți de la începutul fișierului DWORD bfSize; // offset 2 octeți de la începutul fișierului, lungime 4 octeți WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits;

// offset 10 octeți de la începutul fișierului, lungime 4 octeți

  • ) BITMAPFILEHEADER, * PBITMAPFILEHEADER;
  • Tipul WORD trebuie să fie de 16 biți, tipurile DWORD și LONG trebuie să fie de 32 de biți, tipul LONG trebuie să fie semnat și se presupune că ordinea octeților este little endian.
  • bfType - tip de fișier, caractere „BM” (în HEX: 0x42 0x4d).
  • bfSize - dimensiunea întregului fișier în octeți.

bfReserved1 și bfReserved2 sunt rezervate și trebuie să conțină zerouri.

bfOffBits - conține offset-ul în octeți de la începutul structurii BITMAPFILEHEADER până la biții de imagine înșiși.

După antetul fișierului

BITMAPINFHEADDER

BiSize Mărimea acestei structuri în octeți. Formatul BMP a fost extins de-a lungul timpului, iar valoarea acestui câmp determină versiunea formatului.

  • biWidth Lățimea imaginii în pixeli. Pentru Win98/Me și Win2000/XP: Dacă câmpul biCompression conține BI_JPEG sau BI_PNG, aceasta este lățimea imaginii decomprimate.
  • biHeight Înălțimea imaginii în pixeli. Dacă conține o valoare pozitivă, imaginea este scrisă în ordinea de jos în sus (zero pixel în colțul din stânga jos). Dacă valoarea este negativă, imaginea este scrisă de sus în jos (zero pixel în colțul din stânga sus al imaginii). Câmpul biCompression trebuie să conţină valoarea BI_RGB sau BI_BITFIELDS. O astfel de imagine nu poate fi comprimată.
  • biPlanes Numărul de planuri de culoare și în format BMP conține unul.
  • biBitCount Numărul de biți pe pixel. Poate lua următoarele valori:
  • 0 - are sens pentru Win98/Me/2000/XP. Numărul de biți pe pixel determină formatul JPEG sau PNG.
    1 - imagine monocromă. Membrul bmiColors al structurii BITMAPINFO conține două elemente. Fiecare bit al unei imagini reprezintă un pixel; dacă bitul este zero, pixelul are culoarea primului element din tabelul bmiColors, în caz contrar - culoarea celui de-al doilea.
  • 24 - paleta nu este folosită, fiecare trei octeți ai imaginii reprezintă un pixel, un octet pentru intensitatea canalelor albastru, verde și respectiv roșu.
  • 32 - Dacă câmpul biCompression conține valoarea BI_RGB, imaginea nu conține o paletă. Fiecare patru octeți ai imaginii reprezintă un pixel, câte un octet pentru intensitatea canalelor albastru, verde și respectiv roșu. Cel mai semnificativ octet al fiecărui quad nu este de obicei folosit, dar permite stocarea datelor de canal alfa.
    Dacă câmpul biCompression conține valoarea BI_BITFIELDS, trei măști de culoare de patru octeți sunt stocate în paletă - pentru componentele roșu, verde și albastru. Fiecare pixel dintr-o imagine este reprezentat de patru octeți. WinNT/2000: măștile componente nu trebuie să se suprapună sau să se intersecteze. Windows 95/98/Me: sistemul acceptă un singur mod de compresie, complet similar cu modul fără compresie BI_RGB - cel mai semnificativ octet din fiecare patru este folosit ca canal alfa, următorii trei sunt rezervați pentru albastru, verde și roșu canale, respectiv: 0xAARRGGBB.
biCompression Tip de compresie pentru imagini comprimate:
Sens Identificator Comprimare
0 BI_RGB imagine necomprimată
1 BI_RLE8 Compresie RLE pentru imagini pe 8 biți
2 BI_RLE4 Compresie RLE pentru imagini pe 4 biți
3 BI_BITFIELDS imaginea nu este comprimată, paleta conține trei măști de 4 octeți pentru componentele de culoare roșu, verde și albastru. Folosit pentru imagini pe 16 și 32 de biți
4 BI_JPEG Win98/Me/2000/XP: compresie JPEG
5 BI_PNG Win98/Me/2000/XP: compresie PNG
6 BI_ALPHABITFIELDS WinCE: imaginea nu este comprimată, paleta conține patru măști de 4 octeți pentru componentele de culoare roșu, verde, albastru și transparent (canal alfa). Folosit pentru imagini pe 16 și 32 de biți
biSizeImage Dimensiunea imaginii în octeți. Poate conține zero pentru imaginile BI_RGB. Win98/Me/2000/XP: Dacă biCompression conține BI_JPEG sau BI_PNG, biSizeImage specifică dimensiunea memoriei tampon de imagine BI_JPEG sau BI_PNG.
biXPelsPerMeter Rezoluție orizontală în pixeli pe metru pentru dispozitivul țintă. O aplicație poate folosi această valoare pentru a selecta dintr-un grup de resurse de imagine cea mai potrivită imagine pentru dispozitivul curent. Pentru DPI 96, care este acceptat de Microsoft pentru monitoare, acesta va fi egal cu 3780 (dacă este calculat folosind formula (96 / 25,4) * 1000).
biYPelsPerMeter Rezoluție verticală în pixeli pe metru pentru dispozitivul țintă.

biClrUsed Numărul de indici de culoare utilizați în paletă. Dacă valoarea este zero, imaginea folosește numărul maxim de indici disponibili, în funcție de valoarea biBitCount și metoda de compresie specificată în biCompression.

Dacă conține o valoare diferită de zero și biBitCount este mai mic de 16, biClrUsed specifică numărul de culori pe care le va accesa driverul de dispozitiv sau aplicația. Dacă biBitCount este mai mare sau egal cu 16, biClrUsed este dimensiunea paletei utilizată pentru a optimiza performanța paletelor de sistem. Dacă biBitCount este 16 sau 32, paleta optimă urmează imediat după trei măști de patru octeți.

Într-o imagine împachetată, matricea de pixeli urmează imediat structura BITMAPINFO, biClrUsed trebuie să conțină zero sau dimensiunea reală a paletei.

biClrImportant Numărul de elemente de paletă necesare pentru afișarea imaginii. Dacă conține zero, toți indicii sunt la fel de importanți.

Structura BITMAPINFO combină BITMAPINFOHEADER și paleta, oferind o descriere completă a dimensiunilor și culorilor unei imagini.

Pentru a găsi paleta în structura BITMAPINFO, aplicația trebuie să folosească informațiile stocate în biSize după cum urmează:

Typedef struct ( DWORD bV4Size; LONG bV4Width; LONG bV4Height; WORD bV4Planes; WORD bV4BitCount; DWORD bV4V4Compression; DWORD bV4SizeImage; LONG bV4XPelsPerMeter; LONG bV4YPelsPerMeter; LONG bV4YPelsPerMeter;DWORD bV4YPelsPerMeter; DWORD bV4GreenMask; CIEXYZTRIPLE bV4Green DWORD;

Câmpurile de la începutul structurii până la și inclusiv bV4ClrImportant au același scop ca și câmpurile corespunzătoare ale structurii BITMAPINFOHEADER.

  • bV4RedMask - masca de culoare a componentei roșii a fiecărui pixel, utilizată numai dacă bV4Compression conține valoarea BI_BITFIELDS.
  • bV4GreenMask - masca de culoare a componentei verde a fiecărui pixel, utilizată numai dacă bV4Compression conține valoarea BI_BITFIELDS.
  • bV4BlueMask - masca de culoare a componentei albastre a fiecărui pixel, utilizată numai dacă bV4Compression conține valoarea BI_BITFIELDS.
  • bV4AlphaMask - masca care definește componenta canalului alfa.
  • bV4CSType - definește spațiul de culoare al imaginii.
  • bV4Endpoints este o structură CIEXYZTRIPLE care specifică coordonatele x, y și z a trei culori care corespund punctelor finale ale spațiului de culoare definit pentru imagine. Acest câmp este ignorat dacă bV4CSType nu conține o valoare LCS_CALIBRATED_RGB.
  • bV4GammaRed - curba de ton a componentei roșii. Ignorat dacă bV4CSType nu conține o valoare LCS_CALIBRATED_RGB. Indicat în format 16×16.
  • bV4GammaGreen - curba de ton a componentei verzi. Ignorat dacă bV4CSType nu conține o valoare LCS_CALIBRATED_RGB.
  • bV4GammaBlue - curba de ton al componentei albastre. Ignorat dacă bV4CSType nu conține o valoare LCS_CALIBRATED_RGB.

BITMAPV5HEADER

Win95/NT 4.0: Aplicațiile pot folosi BITMAPV4HEADER. Win NT 3.51 și versiunile anterioare trebuie să utilizeze structura BITMAPINFOHEADER.

Typedef struct ( DWORD bV5Size; LONG bV5Width; LONG bV5Height; WORD bV5Planes; WORD bV5BitCount; DWORD bV5Compression; DWORD bV5SizeImage; LONG bV5XPelsPerMeter; LONG bV5YPelsPerMeter; bVORD5VlImport.bVORD5Vl; GreenMask; DWORD bV5AlphaMask; 5 HEADER;

Pentru câmpurile de la începutul structurii până la și inclusiv bV5GammaBlue, numai diferențe de Versiuni anterioare- BITMAPINFOHEADER și BITMAPV4HEADER.

  • bV5CSType - definește spațiul de culoare al imaginii, poate lua următoarele valori:
LCS_CALIBRATED_RGB LCS_sRGB LCS_WINDOWS_COLOR_SPACE PROFILE_LINKED PROFILE_EMBEDDED
  • bV5Intent - poate lua următoarele valori:
LCS_GM_ABS_COLORIMETRIC LCS_GM_BUSINESS LCS_GM_GRAPHICS LCS_GM_IMAGES
  • bV5ProfileData - offset în octeți de la începutul structurii până la începutul datelor de profil (nume fișier de profil, un șir format exclusiv din caractere tabelul de coduri 1252 și se termină cu un octet zero). Ignorat dacă bV5CSType conține o altă valoare decât PROFILE_LINKED și PROFILE_EMBEDDED.
  • bV5ProfileSize - dimensiunea datelor de profil în octeți.
  • bV5Rezervat - rezervat. Conține zero.

Paletă

Paleta poate conține o secvență de câmpuri de patru octeți în funcție de numărul de culori disponibile (256 pentru o imagine de 8 biți). Cei trei octeți inferiori ai fiecărui câmp determină intensitatea componentelor roșii, verzi și albastre ale culorii; Fiecare pixel al imaginii este descris în acest caz de un octet care conține numărul câmpului de paletă în care este stocată culoarea acestui pixel.

Dacă un pixel de imagine este descris printr-un număr de 16 biți, paleta poate stoca trei valori de doi octeți, fiecare dintre acestea definind o mască pentru a extrage componentele de culoare roșie, verde și albastră din pixelul de 16 biți.

Este posibil ca un fișier BMP să nu conțină o paletă dacă stochează o imagine color necomprimată.

Date de imagine

O secvență de pixeli înregistrate într-o formă sau alta. Pixelii sunt stocați rând cu rând, de jos în sus. Fiecare linie de imagine este completată cu zerouri până la o lungime care este un multiplu de patru octeți.

În fișierele bmp cu o adâncime de culoare de 24 de biți, octeții de culoare ai fiecărui pixel sunt stocați în ordinea BGR (Albastru, Verde, Roșu).

În fișierele bmp cu o adâncime de culoare de 32 de biți, octeții de culoare ai fiecărui pixel sunt stocați în ordinea BGRA (albastru, verde, roșu, alfa)

Adâncimea de biți a imaginii

În funcție de numărul de culori reprezentate, fiecare punct este alocat de la 1 la 48 de biți:

  • 1 bit - imagine monocromă (două culori).
  • 2 biți - 4 culori posibile (moduri de operare CGA) (modul 2 biți nu este standardizat oficial, dar este utilizat).
  • 4 biți - imagine în 16 culori (moduri de operare EGA).
  • 8 biți (1 octet) - 256 de culori, ultimul dintre moduri care acceptă culori indexate (vezi mai jos).
  • 16 biți (2 octeți) - modul HiColor, Pentru 5-6-5 = 65536 nuanțe posibile, pentru 5-5-5 = 32768 nuanțe posibile.
  • 24 de biți (3 octeți) - TrueColor. Deoarece 3 octeți nu se potrivesc bine la puteri de doi (mai ales când se stochează date în memorie, unde alinierea datelor la granița unui cuvânt contează), se folosește adesea o imagine de 32 de biți. În modul TrueColor, fiecăruia dintre cele trei canale (în modul RGB) i se alocă 1 octet (256 valori posibile), numărul total de culori este .
  • 32 de biți (4 octeți) - acest mod este aproape similar cu TrueColor, al patrulea octet nu este de obicei utilizat sau conține canalul alfa (transparență).
  • 48 de biți (6 octeți) - un format rar folosit, cu acuratețe sporită a culorii (16 biți pe canal), susținut de un număr relativ mic de programe și echipamente.

Culori indexate

Când numărul de biți este de 1 (2 culori), 2 (4 culori), 4 (16 culori) sau 8 (256 de culori) per pixel, poate fi utilizat un mod special de culoare indexat. În acest caz, numărul corespunzător fiecărui pixel nu indică culoarea, ci numărul culorii din paletă. Prin utilizarea unei palete, este posibilă adaptarea imaginii la culorile prezente în imagine. În acest caz, imaginea nu este limitată culorile date, dar numărul maxim de culori utilizate simultan.

Exemplu de program

Următorul program deschide un fișier BMP de 24 de biți într-un XWindow, adâncimea de culoare ar trebui să fie de 32 de biți, nu funcționează la redări mai mici de culoare, deoarece complică exemplul:

/* Compilat cu linia: cc -o xtest xtest.c -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lm */#include #include #include #include #include #include #include #include #include #include #include #include "bitmap.h" /* Iată definițiile antetului BMP descrise mai sus în acest articol */ static XImage * CreateImageFromBuffer(Display*, unsigned char *, int, int) ; main(int argc, char * argv ) ( Display * dis; Window win; /* Fereastra noastră */ XEvent event; /* Evenimente */ GC gc;/* Context grafic */< 2 ) { perror ("use: xtest file.bmpXImage * imagine; int n, lățime, înălțime, fd, dimensiune; XImage * imagine; unsigned char * date; BITMAFILEHEADER bmp; BITMAPINFOHEADER inf; char * buf; dacă (argc \n"); ieșire(1);) if ((fd = open(argv[ 1 ] , O_RDONLY) ) == - 1 ) ( printf ("Eroare de deschidere bitmap) ); ieșire(1); ) read(fd, & bmp, sizeof (BITMAPFILEHEADER)); read(fd, & inf, sizeof (BITMAPINFOHEADER)); lățime = inf.biWidth ; inaltime = inf.biInaltime ; if ((dis = XOpenDisplay(getenv ("DISPLAY") ) ) == NULL) ( printf („Nu se poate conecta serverul X: %s\n” , strerror (errno) ); XImage * CreateImageFromBuffer(Display * dis, unsigned char * buf, int width, int height) ( int adâncime, ecran; XImage * img = NULL; int i, j; int numBmpBytes; size_t numImgBytes; int32_t * imgBuf; int ind = 0 ; int linie; /* Numerele rândurilor și coloanelor pentru a reflecta */ int new_ind; /* Index nou */ ecran = DefaultScreen(dis) ; depth = DefaultDepth(dis, ecran) ; temp = latime * 3 ; linie = temp + lățime % 4 ;< numBmpBytes; i++ ) { unsigned int r, g, b; /* Lungimea șirului ținând cont de aliniere */ numImgBytes = (4 * (lățime * înălțime) ) ; imgBuf = malloc(numImgBytes);/* Dimensiunea alocată BMP în fișier, ținând cont de aliniere */<< 8 | b << 16 ) << 8 ; ind++; } img = XCreateImage(dis, CopyFromParent, depth, ZPixmap, 0 , (char * ) imgBuf, width, height, 32 , 0 ) ; XInitImage(img) ; numBmpBytes = linie * înălțime; pentru (i = 0; i