Denne artikkelen handler om hvordan bmp-grafikkformatet ser ut. Selv om dette er et av de enklere formatene, på grunn av det faktum at det finnes mange varianter av dette formatet, er ikke alle punkter åpenbare. Så slutt å helle vann, la oss komme i gang.
Format strukturer
Bmp-formatet (fra ordene BitMaP - bitmap, eller, på russisk, bitarray) er et ukomprimert (for det meste) bilde som er ganske enkelt å lese og vise i Windows OS, som har spesielle API-funksjoner som hjelper.
La oss først gi en grafisk representasjon av dataene i bmp (bilde hentet fra MSDN).
I begynnelsen er det en filoverskrift (BITMAPFILEHEADER). Det er beskrevet som følger:
bfType bestemmer filtypen. Her skal han være BM. Hvis du åpner en BMP-fil i en tekstredigerer (eller enda bedre, i en heksadesimal editor), vil du se at de to første tegnene er BM (fra ordet BitMap, som du sikkert allerede har gjettet).
bfStørrelse er størrelsen på selve filen i byte. Strengt tatt bør du beregne det (noe som anbefales), men jeg satte filstørrelsen feil (men ikke med vilje :)) og det var ingen problemer (ACDSee lest uten problemer, programmet mitt fungerte), men jeg anbefaler deg ikke skriv det bevisst feil , plutselig dukker det opp et samvittighetsfullt program som vil sammenligne denne størrelsen med det ekte og bestemme at det ikke er bmp, men noe annet. Ideelt sett bør alle programmer, for å sikre at det er en ekte bmp og ikke en falsk, for det første sjekke at bfType inneholder "BM" (uten anførselstegn), og for det andre at bfSize er lik filstørrelsen .
bfReserved1 og bfReserved2 er reservert og må være null.
bfOffBits. Dette er et av de viktigste feltene i denne strukturen. Den viser hvor selve punktgrafikken begynner i forhold til begynnelsen av filen (eller, som MSDN sier, "fra begynnelsen av BITMAPFILEHEADER-strukturen"), som beskriver bildet. Det vil si, for å være garantert å komme til begynnelsen av matrisen må du skrive:
typedef struct tagBITMAPINFOHEADER
{
DWORD biSize;
LANG biBredde;
LANG biHøyde;
WORD biPlanes;
WORD biBitCount;
DWORD bikomprimering;
DWORD biSizeImage;
LANG biXPelsPerMeter;
LANGE biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrViktig;
) BITMAPINFOHEADER, * PBITMAPINFOHEADER;
biSize er størrelsen på selve strukturen. Den må initialiseres som følger: bih.biSize = sizeof(BITMAPINFOHEADER);
Her vil vi igjen anta at bih er erklært som følger: BITMAPINFOHEADER bih;
biWidth og biHeight angi bredden og høyden på bildet i piksler, henholdsvis.
biPlanes angir antall fly. Foreløpig er den alltid satt til 1.
biBitCount- Antall biter per piksel. Vi snakker mer om dette nedenfor.
bikompresjon angir typen komprimering. Ikke vær overrasket eller redd for at bmp plutselig opplever kompresjon. Jeg personlig har ikke sett mer enn én komprimert bmp (men jeg sier ikke at de ikke eksisterer). Hvis det ikke er noen komprimering, må dette flagget settes til BI_RGB. I denne artikkelen snakker vi om det ukomprimerte formatet, så jeg vil ikke en gang liste opp andre flagg. Det ser ut til at den samme strukturen brukes i JPEG- og PNG-filer, fordi fra Windows 98 dukket det opp alternativer BI_JPEG, som viser at dette bildet er JPEG og BI_PNG, at det er PNG (jeg vet ikke noe om Jpeg-formatet, Jeg har nettopp gjort disse konklusjonene basert på det som er skrevet i MSDN).
biSizeImage angir størrelsen på bildet i byte. Hvis bildet er ukomprimert (det vil si at forrige felt er satt til BI_RGB), skal det skrives en null her. biXPelsPerMeter Og biYPelsPerMeter angir henholdsvis den horisontale og vertikale oppløsningen (i piksler per meter) til den endelige enheten som punktgrafikken (rasteret) skal sendes ut på. En applikasjon kan bruke denne verdien til å velge fra en gruppe ressurser den mest passende punktgrafikken for den ønskede enheten. Faktum er at bmp-formatet i hovedsak er et maskinvareuavhengig raster, det vil si når utseendet til det oppnådde ikke avhenger av hva dette rasteret projiseres på (så å si). Et bilde vil for eksempel se likt ut uansett om det er tegnet på en skjerm eller skrevet ut på en skriver. Men oppløsningen til enhetene er forskjellig, og det er nettopp for å velge det mest passende bildet fra de tilgjengelige at disse parametrene brukes.
biClrUsed bestemmer antall farger som brukes fra tabellen. Hvis denne verdien er null, bruker rasteret det maksimale antallet farger som tillates av biBitCount-verdien. Dette er kun relevant for komprimerte bilder. Hvis biClrUsed ikke er null og biBitCount er mindre enn 16, bestemmer biClrUsed gjeldende antall tilgjengelige grafikkmotor- eller enhetsdriverfarger. Hvis biBitCount er større enn eller lik 16, bestemmer biClrUsed størrelsen på fargetabellen som brukes til å optimalisere den gjeldende systempaletten.
biClrViktig- dette er antallet viktige farger. Bestemmer antall farger som trengs for å avbilde tegningen. Hvis denne verdien er 0 (som den vanligvis er), anses alle farger som viktige.
Typer BMP-format
Alle typer bmp-format betinget kan deles inn i to typer: palett og ikke-palett. Det vil si om paletten brukes i et gitt format eller ikke. Vær oppmerksom på at paletten til og med kan være i palettfrie formater, men den brukes ikke der. I palettfrie bmps beregnes fargen direkte fra bitene som går i filen, med utgangspunkt i et bestemt sted. Og i paletter beskriver hver byte en eller flere piksler, og byte- (eller bit-verdier) er fargeindeksen i paletten. Til å begynne med vil jeg gi en tabell som sammenligner de mulige alternativene. Bildetypen (palett eller palettfri) avhenger av hvor mange biter som gis per piksel, det vil si biBitCount-verdien til BITMAPINFOHEADER-strukturen.
biBitCount | Palett eller ikke-palettformat | Maksimalt mulig antall farger | Notater | 1 | Palett | 2 | Et tofarget palettbilde, vel å merke, ikke nødvendigvis svart-hvitt. Hvis rasterbiten (som er like under) tilbakestilles (lik 0), betyr dette at den første fargen fra paletten skal være på dette stedet, og hvis den er satt (lik 1), så den andre. | 4 | Palett | 16 | Hver byte beskriver 2 piksler. Her er et eksempel fra MSDN. Hvis den første byten i bildet er 0x1F, så tilsvarer den to piksler, fargen på den første er den andre fargen fra paletten (fordi nedtellingen starter fra null), og den andre pikselen er den 16. fargen på paletten. | 8 | Palett | 256 | Et av de vanligste alternativene. Men samtidig de enkleste. Paletten tar opp en kilobyte (men det er bedre å ikke stole på det). Én byte er én farge. Dessuten er verdien fargenummeret i paletten. | 16 | Ingen palett | 2^16 eller 2^15 | Dette er det mest forvirrende alternativet. La oss starte med det faktum at det er palettfritt, det vil si at hver to byte (ett WORD-ord) i rasteret definerer en piksel unikt. Men her er hva som skjer: det er 16 biter, og det er 3 fargekomponenter (rød, grønn, blå). Men 16 ønsker ikke å bli delt på 3. Derfor er det to alternativer her. Den første er å bruke 15 biter i stedet for 16, så er det 5 biter for hver fargekomponent. På denne måten kan vi bruke maksimalt 2^15 = 32768 farger og få en trippel R-G-B = 5-5-5. Men så går en hel bit av 16 tapt forgjeves. Men det hender at øynene våre, blant alle farger, oppfatter grønt bedre, så vi bestemte oss for å gi denne ene biten til den grønne komponenten, det vil si at vi får trippel R-G-B = 5-6-5, og nå kan vi bruke 2^16 = 65536 farger. Men det mest ubehagelige er at begge alternativene brukes. MSDN foreslår at for å skille hvor mange farger som brukes, fyll biClrUsed-feltet fra BITMAPINFOHEADER-strukturen med denne verdien. For å velge hver komponent må du bruke følgende masker. For 5-5-5 format: 0x001F for blå komponent, 0x03E0 for grønn og 0x7C00 for rød. For 5-6-5-formatet: henholdsvis 0x001F - blå, 0x07E0 - grønn og 0xF800 røde komponenter. | 24 | Ingen palett | 2^24 | Og dette er det enkleste formatet. Her definerer 3 byte 3 fargekomponenter. Det vil si én komponent per byte. Vi leser ganske enkelt RGBTRIPLE-strukturen og bruker dens rgbtBlue, rgbtGreen, rgbtRed felt. De går i den rekkefølgen. | 32 | Ingen palett | 2^32 | Her definerer 4 byte 3 komponenter. Men én byte brukes ikke. Den kan for eksempel brukes til alfakanalen (transparens). I dette tilfellet er det praktisk å lese rasteret ved hjelp av RGBQUAD-strukturer, som er beskrevet som følger: |
Datalagring i bmp-format
Vel, nå kommer vi til den mest interessante delen. Etter strukturene BITMAPFILEHEADER og BITMAPINFOHEADER kommer paletten. Dessuten, hvis formatet er palettfritt, er det kanskje ikke der, men du bør ikke stole på det. Faktum er at da jeg akkurat begynte å forstå bmp-formatet, leste jeg i en bok at visstnok, hvis formatet er palettfritt, så har det ingen palett i det hele tatt. Det var til og med to bilder - formatdiagrammer: ett med palett, det andre uten. Og på den tiden skrev jeg et program som flittig opererer med bmp-filer. Og jeg måtte konvertere innkommende bilder fra 256 farger til 24-biters (hvis noen) til midlertidige filer. Og jeg lagde rett og slett ikke en palett i 24-bit (bfOffBits fra BITMAPFILEHEADER-strukturen var lik summen av sizeof(BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER), og lot de innkommende 24-bitsene være uendret. Med 256-fargers raster fungerte som det skulle, helt til jeg ikke kom over et 24-bits bilde som hadde søppel vist nederst i stedet for den nødvendige delen. Jeg skjønte ikke umiddelbart hva som var galt. Før jeg sammenlignet størrelsen på originalfilen med den teoretiske som burde vært der hvis det ikke fantes en palett. Forskjellen viste seg å være nøyaktig 1 KB (nøyaktig 1024 bytes). Det var en palett. Regn derfor aldri med om det finnes en palett og ikke stol på dens størrelse (selv om alle bildene jeg kom over hadde en palettstørrelse på 256 farger, eller 1Kb), flytt alltid gjennom filen til begynnelsen av rasteret ved å bruke bfOffBits. Paletten er en rekke RGBQUAD-strukturer som følger hverandre. Til og med hvis ikke alle farger er brukt i paletten (men bare for eksempel 16), er det ofte fortsatt tildelt 256 felt for paletten. Og 256 * 4 = 1024, hvor 4 er størrelsen på RGBQUAD-strukturen, dvs. den samme en kilobyte oppnås.
Umiddelbart etter paletten kommer selve rasteret. Det er her ting blir mer forvirrende. For det første beskrives pikslene her som skrevet i tabellen ovenfor, avhengig av formatet. Og de kan selv inneholde verdien av fargekomponentene (for palettfrie), eller de kan være indekser for en palettarray. Selve bildet tas opp linje for linje. For det andre ser bildet ut til å være opp ned. Det vil si at den nederste linjen skrives først, deretter den nest siste linjen, og så videre helt til toppen. Og for det tredje, som skrevet i, hvis størrelsen på rasterlinjen ikke er et multiplum av 4, så fylles den med 1 til 3 tomme (null) byte slik at lengden på linjen er et multiplum av avsnittet. Dette er det mest ubehagelige. Faktum er at for hvert format må du justere dette antallet tomme byte (selv om jeg liker å skrive en del av paletten der, vil jeg bare ikke lage ekstra "null" variabler hvis disse bytene blir hoppet over uansett og ingen trenger dem). Jeg gir en tabell med formler som viser for hvilket format hvor mange byte som skal legges til på slutten av linjen. Der betyr Width-variabelen, som du kanskje gjetter, bredden på bildet. Alle disse formlene ble etablert eksperimentelt. Jeg vil gi et eksempel bare for de mest brukte formatene. For resten kan du skrive det selv.
Eksempel programmer
Du kan laste ned alle kildene. Jeg skal ikke skrive mye her. Jeg vil bare gi funksjonene med kommentarer.
Hei 1. Lage et bilde i bmp-format.
Her skapes et monokromatisk bilde. Det er tre eksempler på slike funksjoner: å lage bmp 8, 16 og 24 biter. Jeg gir bare for 16-bit.
// La oss lage et bilde i bmp-format 16 biter som 5-5-5, som ganske enkelt vil være monokromatisk
void CreateBmp555(char * fname, WORD-farge)
{
HÅNDTER hFile;
DWORD RW;
int i, j;
// Erklære nødvendige strukturer
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
BYTE-palett[1024]; // Palett
// La oss ha et bilde på 35 x 50 piksler
int Bredde = 35;
int Høyde = 50;
memset(Palett, 0, 1024); // I paletten har vi nuller, fyll dem
memset (&bfh, 0 , sizeof (bfh) );
Bfh.bfType = 0x4D42 ; // La oss betegne at dette er bmp "BM"
bfh.bfOffBits = størrelse på (bfh) + størrelse på (bih) + 1024 ; // Paletten tar opp 1Kb, men vi vil ikke bruke den
bfh.bfSize = bfh.bfOffBits +
sizeof(color) * Bredde * Høyde +
Høyde * ((størrelse på (farge) * Bredde) % 4 ); // Beregn størrelsen på den endelige filen
memset (&bih, 0 , sizeof (bih) );
bih.biSize = sizeof(bih); // Det er slik det skal være
bih.biBitCount = 16 ; // 16 biter per piksel
bih.biClrUsed = 32768 ; // Vi bruker 5-5-5
bih.biCompression = BI_RGB; // Uten komprimering
bih.biHeight = Høyde;
bih.biWidth = Bredde;
bih.biPlanes = 1 ; // Bør være 1
// Og de resterende feltene forblir 0
HFile = CreateFile(fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
komme tilbake ;
// Skriv overskriftene
WriteFile (hFile, & bfh, sizeof (bfh) , & RW, NULL );
WriteFile (hFile, & bih, sizeof (bih) , & RW, NULL );
// Skriv paletten
WriteFile(hFile, Palette, 1024, &RW, NULL);
for (i = 0 ; i<
Height;
i++
)
{
for (j = 0 ; j<
Width;
j++
)
{
WriteFile (hFile, & color, sizeof (color) , & RW, NULL );
}
// Juster med kantlinjen
WriteFile (hFile, Palett, (størrelse på (farge) * Bredde) % 4 , & RW, NULL );
}
CloseHandle(hFile) ;
}
farge - bildefarge. Verdien av denne variabelen må fylles ut i henhold til den første tabellen. Du kan se det resulterende bildet i ACDSee, for eksempel. Jeg prøvde nettopp å åpne den i Photoshop, men det viste seg at den ikke kan lese dem i dette formatet. Men du kan :).
Eksempel 2. Konvertering av et bilde fra 8-bits format (256 farger) til 24-bits.
BOOL Convert256To24 (char * fin, char * fout)
{
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
int Bredde, Høyde;
RGBQUAD-palett[ 256 ] ;
BYTE * inBuf;
RGBTRIPLE * utBuf;
HÅNDTER HIN, HØT;
DWORD RW;
DWORD OffBits;
int i, j;
HIn = CreateFile (fin, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL) ;
if (hIn == INVALID_HANDLE_VALUE)
return FALSE;
HOut = CreateFile(fout, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hOut == INVALID_HANDLE_VALUE)
{
Lukk Håndtak(hIn);
return FALSE;
}
// Les dataene
ReadFile (hIn, & bfh, sizeof (bfh) , & RW, NULL );
ReadFile (hIn, & bih, sizeof (bih) , & RW, NULL );
ReadFile (hIn, Palette, 256 * sizeof (RGBQUAD) , & RW, NULL );
// Sett pekeren til begynnelsen av rasteret
SetFilePointer (hIn, bfh.bfOffBits, NULL, FILE_BEGIN) ;
Width = bih.biWidth ;
Høyde = bih.biHøyde ;
OffBits = bfh.bfOffBits ;
// Tildel minne
inBuf = ny BYTE [Bredde];
outBuf = ny RGBTRIPLE [Bredde];
// Fyll inn overskriftene
bfh.bfOffBits = sizeof (bfh) + sizeof (bih) ; // La oss ikke skrive en palett
bih.biBitCount = 24 ;
bfh.bfSize = bfh.bfOffBits + 4 * Bredde * Høyde + Høyde * ( Bredde % 4 ) ; // Filstørrelse
// Og resten forblir uendret
// Skriv overskriftene
WriteFile (hOut, & bfh, sizeof (bfh) , & RW, NULL );
WriteFile (hOut, & bih, sizeof (bih) , & RW, NULL );
// La oss begynne å konvertere
for (i = 0 ; i<
Height;
i++
)
{
ReadFile(hIn, inBuf, Width, & RW, NULL);
for (j = 0 ; j<
Width;
j++
)
{
outBuf[ j].rgbtRed = Palett[ inBuf[ j] ] .rgbRed ;
outBuf[ j].rgbtGreen = Palett[ inBuf[ j] ] .rgbGreen ;
outBuf[ j].rgbtBlue = Palett[ inBuf[ j] ] .rgbBlue ;
}
WriteFile (hOut, outBuf, sizeof (RGBTRIPLE) * Width, & RW, NULL );
// Skriv søppel for justering
WriteFile (hOut, Palett, Width % 4 , & RW, NULL );
SetFilePointer(hIn, (3 * Bredde) % 4, NULL, FILE_CURRENT) ;
}
slett inBuf;
slette outBuf;
Lukk Håndtak(hIn);
Lukk Håndtak(hOut);
returner TRUE;
}
Navnene på kilde- og målfilene må sendes til funksjonen, henholdsvis.
Den vanligste årsaken til problemer med å åpne BMP-filen er ganske enkelt mangelen på passende applikasjoner installert på datamaskinen din. I dette tilfellet er det nok å finne, laste ned og installere et program som serverer filer i BMP-format - slike programmer er tilgjengelige nedenfor.
Søkesystem
Skriv inn filtypen
Hjelp
Clue
Vær oppmerksom på at noen kodede data fra filer som datamaskinen vår ikke leser, noen ganger kan vises i Notisblokk. På denne måten vil vi lese fragmenter av tekst eller tall - Det er verdt å sjekke om denne metoden også fungerer når det gjelder BMP-filer.
Hva skal jeg gjøre hvis applikasjonen fra listen allerede er installert?
Ofte skal en installert applikasjon automatisk koble til en BMP-fil. Hvis dette ikke skjer, kan BMP-filen assosieres manuelt med det nylig installerte programmet. Bare høyreklikk på BMP-filen, og velg deretter alternativet "Velg standardprogram" fra den tilgjengelige listen. Deretter må du velge "Vis"-alternativet og finne din favorittapplikasjon. De angitte endringene må godkjennes ved å bruke "OK".
Programmer som åpner filen BMP
Windows
Mac os
Hvorfor kan jeg ikke åpne en BMP-fil?
Problemer med BMP filer kan også ha andre årsaker. Noen ganger vil til og med å installere programvare på datamaskinen din som støtter BMP filer ikke løse problemet. Årsaken til manglende evne til å åpne og jobbe med BMP-filen kan også være:
Upassende BMP-filtilknytninger i registeroppføringer
- korrupsjon av BMP-filen vi åpner
- BMP-filinfeksjon (virus)
- for lite dataressurs
- utdaterte drivere
- fjerning av BMP-utvidelsen fra Windows-registeret
- ufullstendig installasjon av et program som støtter BMP-utvidelsen
Å fikse disse problemene bør resultere i fritt åpning og arbeid med BMP filer. I tilfelle datamaskinen din fortsatt har problemer med filer, må du ta hjelp av en ekspert som vil fastslå den eksakte årsaken.
Datamaskinen min viser ikke filtypene, hva skal jeg gjøre?
I standard Windows-systeminnstillinger ser ikke datamaskinbrukeren filtypen BMP. Dette kan endres i innstillingene. Bare gå til "Kontrollpanel" og velg "Vis og personalisering". Deretter må du gå til "Mappealternativer" og åpne "Vis". I "Vis"-fanen er det et alternativ "Skjul utvidelser av kjente filtyper" - du må velge dette alternativet og bekrefte operasjonen ved å klikke på "OK"-knappen. På dette tidspunktet skal utvidelsene til alle filer, inkludert BMP, vises sortert etter filnavn.
Kunngjøring
BMP Raster bildefilformat
BMP (bitmapfil, enhetsuavhengig bitmapfilformat) er punktgrafikkfiler som brukes til å lagre digitale punktgrafikkbilder separat fra visningsenheten. Denne filtypen ble tidligere brukt i Microsoft Windows og OS/2. Begrepet "raster" kommer fra programmerernes idé om en bitmap. BMP-bilder er vanligvis ukomprimerte eller tapsfritt komprimerte (for eksempel ved bruk av ZIP eller RAR - på grunn av tilstedeværelsen av overflødige data i filen). I dag er JPG det foretrukne bildeformatet – hovedsakelig på grunn av den store filstørrelsen til BMP, som kan forårsake problemer eller forsinkelser ved nedlasting, sending eller opplasting av filer.
Teknisk informasjon om BMP-filer
BMP-filer lagres som 2D-bilder av forskjellige størrelser, farger og fargedybder uten datakomprimering, fargeprofiler eller alfakanaler. BMP-bilder lagres i enhetsuavhengige bitmap-formater (DIB), noe som betyr at bildet har farger i stedet for systemspesifikasjoner. Dette forklarer hvorfor noen BMP-bilder ser annerledes ut på forskjellige datamaskiner. BMP-bilder kan sees på alle enheter, inkludert datamaskiner og TV-skjermer. Mangelen på patenter har gjort denne bildetypen til et populært format for et bredt spekter av enheter.
Ytterligere informasjon om BMP-formatet
Filutvidelse | .bmp |
Filkategori | |
Eksempelfil | (2,7 MiB) (487,85 KiB) |
Relaterte programmer | Adobe Photoshop MS Paint Microsoft Photo Editor Pensel |