Until our most fantastic demands are met, fantasy will always be at war with reality. Fino al nostro fantastico più richieste sono soddisfatte, la fantasia sarà semper in guerra con la realtà.
Reading and Writing BMP Files in C++La lettura e la scrittura dei file BMP in C + +
Published by: 0x0BADFOOD , on 2007-08-16 22:49:18 Pubblicato da: 0x0BADFOOD, su 2007-08-16 22:49:18
Reading and Writing BMP Files using C++La lettura e la scrittura dei file BMP utilizzando il C + +
Introduction Introduzione
This article is intended to be a primer for novices who wish to learn about bitmap file structure and to perform basic image processing. Questo articolo è destinato a essere un primer per novizi che desiderano saperne di più file bitmap e la struttura di base per eseguire l'elaborazione delle immagini.It is not a how-to article for graphics. Non si tratta di un how-to articolo per la grafica.The reason for this - C++ has no native graphics capabilities. La ragione di questo - C + + nativo non ha capacità grafiche.You either have to use GDI (under Windows), OpenGL, SDL, to name a few API's. Voi abbiano ciascuno di utilizzare GDI (sotto Windows), OpenGL, SDL, per citarne alcuni API.The code can be used as is anyway, so you can use it to solve some of the puzzles here. Il codice può essere utilizzato come è comunque, in modo da poter utilizzare per risolvere alcuni dei puzzle qui.
The bitmap class outlined in this article is complete enough to compile, and was adapted from my own class wrapper around OpenGL and SDL. La classe bitmap descritte in questo articolo è abbastanza completo compilare, ed è stato adattato dalla mia classe wrapper di OpenGL e SDL.The project got leggy, and code was executing very slow for what I wanted, so I scrapped the project and kept the classes for reuse. Il progetto ha ottenuto leggy, e l'esecuzione di codice è stato molto lento per quello che ho voluto, così ho demolito il progetto e mantenuto le classi per il riutilizzo.
Bitwise Color Operations Operazioni bit a bit di colore
In my previous article, I mentioned how color information can be stored in a long integer. Nel mio articolo precedente, ho citato come colore informazioni possono essere memorizzate in un lungo intero.This integer has a special name under Windows, called a COLORREF data type. Questo numero intero ha un nome speciale sotto Windows, COLORREF chiamato un tipo di dati.The color data is ordered into fields that look something like 0xAABBGGRR, with RR (red data) occupying the LSB side. Il colore dei dati è ordinata in campi che cercare qualcosa di simile 0xAABBGGRR, con RR (rosso dati) che occupa il lato LSB.Well, in order to go from discrete RGBA values to that format and back again, you will need to understand how bit masking and arithmetic shifts work. Ebbene, al fine di passare da valori discreti RGBA a tale formato e ritorno, sarà necessario capire in che modo po 'coprente e aritmetica turni di lavoro.Let's tackle these now. Supponiamo ora affrontare questi.
In digital logic, there are a handful of basic operations: Nella logica digitale, ci sono un pugno di operazioni di base:
These have "analogs" (har, har) in C++. Questi sono "analoghi" (HAR, HAR) in C + +.I strongly encourage you to go to the library and learn about these digital operations. I vivamente di andare in biblioteca e imparare su queste operazioni digitale.Studying boolean algebra can become very useful. Studiare l'algebra booleana può diventare molto utile.What you need to know for this article is that bits can be ANDded and ORed together to get at the data. Cosa dovete sapere per questo articolo è bit che possono essere ANDded e ORed insieme per ottenere i dati.In a nutshell, the AND operation yeilds a binary 1 only if both input bits are 1. In poche parole, l'operazione yeilds E un binario 1 solo se entrambi i bit di ingresso sono: 1.So we can use ANDing to get at the fields of interest in our long int. Quindi possiamo usare ANDing arrivare a campi di interesse a lungo nella nostra int.If you need to brush up on your hex, there are several articles that can help. Se avete bisogno di fino a pennello sul tuo esadecimale, ci sono vari articoli che possono aiutare.
Extracting Fields from a COLORREFEstrazione Campi da un COLORREF
CODE : CODICE:
int a = 0x0000ff00; // decimal 65,280int a = 0x0000ff00; / / decimale 65280 int b = 0x0000fa19; // decimal 64,025int b = 0x0000fa19; / / decimale 64025 int c = 0;int c = 0;
// suppose we are interested in in getting at the 'fa' part of b,/ / Supponiamo che siamo interessati ad ottenere in occasione della 'fa' parte di b, // we must use a bitwise and, which is a binary operator/ / Dobbiamo utilizzare un bit a bit e, che è un operatore binario
c = a & b; // a is the 'mask' being applied to bc = a & b / / a è la 'maschera' essere applicato a B
// c should now contain the hex value 0x0000fa00, so we need to shift/ / C dovrebbe ora contenere il valore esadecimale 0x0000fa00, così abbiamo bisogno di spostare // the bits eight bit positions to the right (LSB direction), and we/ / I bit bit otto posizioni a destra (direzione LSB), e noi // can combine these operations in one shot using parentheses/ / Possibile combinare queste operazioni in un solo colpo utilizzando parentesi
c = (a & b) >> 8; // c now has the value 0x000000fac = (A & B)>> 8; / / c ora ha il valore 0x000000fa
int r = 0x0000001aint r = 0x0000001a int g = 0x000000fcint g = 0x000000fc int b = 0x000000cdint b = 0x000000cd int a = 0x000000ffint a = 0x000000ff COLORREF c = 0;COLORREF c = 0;
// lets make a single COLORREF with these values/ / Consente di fare un unico COLORREF con questi valori c = r + (g << 8) + (b << 16) + (a << 24);c = r + (g <<8) + (b <<16) + (uno <<24);
// now c = 0xffcdfc1a...simple/ / Ora c = 0xffcdfc1a semplice ...
Bitmap Class Definition and Code Bitmap definizione della classe e il codice
I have included all the necessary files here for you to begin screwing around with bitmaps. Sono inclusi tutti i file necessari per voi qui per iniziare con avvitamento intorno bitmap.It can only open existing bitmaps and alter them, but you should be able to do that by examining the code and header structure. Si può solo aprire gli attuali bitmap e li modifica, ma si dovrebbe essere in grado di farlo esaminando il codice intestazione e struttura.I have included a stub (main.cpp) to outline how to use the class. Ho incluso uno stub (main.cpp) a delineare il modo di utilizzare classe.I strongly encourage you to read up on bitmap file structure, though a knowledge of it is not necessary to use my class. Sono fermamente invitiamo a leggere sul file bitmap struttura, anche se la conoscenza di esso non è necessario utilizzare la mia classe.
#include <stdlib.h># include <stdlib.h> #include <windows.h># include <windows.h> #include "udt.h"# include "udt.h" using namespace std;using namespace std;
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | cBitmap || CBitmap | +----------------------------------------------------------++------------------------------------------------- ---------+ | || | | Purpose: || Finalità: | | The cBitmap class makes it easy to load and use bitmaps.|| Il cBitmap classe lo rende facile caricare e utilizzare bitmap. | | || | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/
// arrays are dynamic, so we can't have any leaks/ / Array sono dinamici, in modo che non può avere alcuna perdita di ~cBitmap();~ cBitmap ();
// returns the width of the bitmap in pixels/ / Restituisce la larghezza della bitmap in pixel LONG GetWidth();LUNGO GetWidth ();
// returns the height of the bitmap in pixels/ / Restituisce l'altezza della bitmap in pixel LONG GetHeight();LUNGO GetHeight ();
// returns a long int with rgba data for point (x, y)/ / Restituisce un int a lungo con RGBA dati per il punto (x, y) COLORREF GetPixel(int x, int y);COLORREF GetPixel (int x, int y);
// paints a pixel in the bitmap/ / Vernici un pixel nella bitmap void PutPixel(int x, int y,void PutPixel (int x, int y, BYTE red, BYTE green, BYTE blue, BYTE alpha);BYTE rosso, verde BYTE, BYTE blu, BYTE alfa);
// saves a bitmap to the given file/ / Salva una bitmap di un determinato file void SaveBitmap(char * filename);void SaveBitmap (char * filename);
private:privato: // bitmap file header, standard Winblows format/ / File bitmap intestazione, il formato standard Winblows BITMAPFILEHEADER m_header;BITMAPFILEHEADER m_header;
// bitmap information, like height, width, and pixel format/ / Bitmap informazioni, come altezza, larghezza, e formato pixel BITMAPINFOHEADER m_info;BITMAPINFOHEADER m_info;
// used for transparency (m_rgba_data is OpenGL ready)/ / Usato per la trasparenza (m_rgba_data è pronto OpenGL) color_vector m_colorkey;color_vector m_colorkey; };);
#endif# endif
bitmap_class.cppbitmap_class.cpp
CODE : CODICE:
#include <iostream># include <iostream> #include <fstream># include <fstream> #include <windows.h># include <windows.h> #include "udt.h"# include "udt.h" #include "bitmap_class.h"# include "bitmap_class.h" using namespace std;using namespace std;
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | cBitmap || CBitmap | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/ cBitmap::cBitmap(char * filename,cBitmap:: cBitmap (char * filename, BYTE red_color_key,BYTE red_color_key, BYTE green_color_key,BYTE green_color_key, BYTE blue_color_key)BYTE blue_color_key) {( // need an input stream variable for file operations/ / Bisogno di un flusso variabile di input per le operazioni sui file ifstream fin;ifstream fin;
// it is impolite to dangle your pointers/ / È scortese a dondolare il tuo puntatori m_pixel_data = 0;m_pixel_data = 0; m_rgba_data = 0;m_rgba_data = 0;
// attempt to open the file using binary access/ / Tentativo di aprire il file utilizzando l'accesso binario fin.open(filename, ios::binary);fin.open (filename, ios:: binario);
if(fin.is_open())if (fin.is_open ()) {( // read in the file info/ / Leggiamo nel file info fin.read((char *)(&m_header), sizeof(BITMAPFILEHEADER));fin.read ((char *) & (m_header), sizeof (BITMAPFILEHEADER)); fin.read((char *)(&m_info), sizeof(BITMAPINFOHEADER));fin.read ((char *) & (m_info), sizeof (BITMAPINFOHEADER));
// create an array that can take the pixel data/ / Creare un array che può assumere dati pixel m_pixel_data = new BYTE[m_info.biSizeImage];m_pixel_data = new byte [m_info.biSizeImage];
// rgba format requires 32 bits, not 24 (hence the * 4 / 3)/ / RGBA formato richiede 32 bit, non 24 (e quindi la * 4 / 3) m_rgba_data = new BYTE[m_info.biSizeImage * 4 / 3];m_rgba_data = new byte [m_info.biSizeImage * 4 / 3];
// read the pixels/ / Leggere i pixel fin.read((char *)(m_pixel_data), m_info.biSizeImage);fin.read ((char *) (m_pixel_data), m_info.biSizeImage);
// close the file/ / Chiudere il file fin.close();fin.close ();
// now, the hard part - we need to get the BGR data to RGBA/ / Ora, la parte difficile - abbiamo bisogno per ottenere il BGR dati RGBA BYTE * src(m_pixel_data);BYTE * src (m_pixel_data); BYTE * dst(m_rgba_data);BYTE * dst (m_rgba_data);
// now we walk through the arrays and perform the operation/ / Ora a piedi attraverso l'array ed eseguire l'operazione for(unsigned int index(0); index < m_info.biSizeImage / 3;for (unsigned int index (0); index <m_info.biSizeImage / 3; index++)indice + +) {( // transform BGR to RGB (OpenGL uses this format -/ / BGR trasformare in RGB (OpenGL utilizza questo formato -- // you can thank me later...)/ / Si può ringraziare in seguito ...) *(dst) = *(src + 2);* (DST) = * (src + 2); *(dst + 1) = *(src + 1);* (dst + 1) = * (src + 1); *(dst + 2) = *(src);* (dst + 2) = * (src);
// now check the colorkey, and set colorkey/ / Ora verificare il colorkey, e impostare colorkey // pixels to alpha = 0/ / Pixel di alfa = 0 if((*(dst) == red_color_key) &&if ((* (DST) == red_color_key) & & (*(dst + 1) == green_color_key) &&(* (dst + 1) == green_color_key) & & (*(dst + 2) == blue_color_key))(* (dst + 2) == blue_color_key)) {( // colorkey matches, set to transparent/ / Colorkey partite, impostato su trasparente *(dst + 3) = 0x00;* (dst + 3) = 0x00; }) elsealtro {( // the pixel isn't a colorkey pixel, set to opaque/ / Pixel non è un colorkey pixel, insieme a opaco *(dst + 3) = 0xff;* (dst + 3) = 0xff; })
// increment the array pointers according/ / Incremento l'array di puntatori secondo src += 3;src + = 3; dst += 4;dst + = 4; }) }) elsealtro {( // post file not found message/ / Post Impossibile trovare il file di messaggio cout << "What is this " << filename << " you speak of?";cout << "Che cos'è questo" <<nomefile << "si parla di?"; }) })
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | ~cBitmap || ~ CBitmap | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/ cBitmap::~cBitmap()cBitmap:: ~ cBitmap () {( // deallocate arrays, if they were successfully allocated/ / Array deallocate, se essi sono stati assegnati if(m_pixel_data)if (m_pixel_data) {( delete [] m_pixel_data;eliminare [] m_pixel_data; }) if(m_rgba_data)if (m_rgba_data) {( delete [] m_rgba_data;eliminare [] m_rgba_data; }) })
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | GetPixel || GetPixel | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/ COLORREF cBitmap::GetPixel(int x, int y)COLORREF cBitmap:: GetPixel (int x, int y) {( // offset into the bitmap and place into a COLORREF variable/ / Compensare l'immagine bitmap in luogo e in una variabile COLORREF COLORREF temp_color(0);COLORREF temp_color (0); int temp_red(0), temp_green(0), temp_blue(0), temp_alpha(0);int temp_red (0), temp_green (0), temp_blue (0), temp_alpha (0); int temp_x(x), temp_y(m_info.biHeight - 1 - y);temp_x int (x), temp_y (m_info.biHeight - 1 - y);
// we can put the individual colors in the right format/ / Siamo in grado di mettere i singoli colori in formato temp_color += temp_alpha << 24;temp_color + = temp_alpha <<24; temp_color += temp_blue << 16;temp_color + = temp_blue <<16; temp_color += temp_green << 8;temp_color + = temp_green <<8; temp_color += temp_red;temp_color + = temp_red;
return temp_color;temp_color ritorno; })
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | PutPixel || PutPixel | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/ void cBitmap::PutPixel(int x, int y, BYTE red, BYTE green, BYTE blue, BYTE alpha)void cBitmap:: PutPixel (int x, int y, BYTE rosso, verde BYTE, BYTE blu, BYTE alfa) {( // offset into the bitmap and insert rgba vals/ / Offset nella bitmap e inserire RGBA Vals int temp_red(0), temp_green(0), temp_blue(0), temp_alpha(0);int temp_red (0), temp_green (0), temp_blue (0), temp_alpha (0); int temp_x(x), temp_y(m_info.biHeight - 1 - y);temp_x int (x), temp_y (m_info.biHeight - 1 - y);
/*+----------------------------------------------------------+/*+----------------------------------------------- -----------+ | SaveBitmap || SaveBitmap | +----------------------------------------------------------+*/+------------------------------------------------- ---------+*/ void cBitmap::SaveBitmap(char * filename)void cBitmap:: SaveBitmap (char * filename) {( // attempt to open the file specified/ / Tenta di aprire il file specificato ofstream fout;ofstream fout;
// attempt to open the file using binary access/ / Tentativo di aprire il file utilizzando l'accesso binario fout.open(filename, ios::binary);fout.open (filename, ios:: binario);
if(fout.is_open())if (fout.is_open ()) {( // same as before, only outputting now/ / Stessa di prima, solo ora l'output fout.write((char *)(&m_header), sizeof(BITMAPFILEHEADER));fout.write ((char *) & (m_header), sizeof (BITMAPFILEHEADER)); fout.write((char *)(&m_info), sizeof(BITMAPINFOHEADER));fout.write ((char *) & (m_info), sizeof (BITMAPINFOHEADER));
// read off the color data in the bass ackwards MS way/ / Leggere il colore dei dati in basso ackwards SM modo for(unsigned int index(0); index < number_of_bytes; index += 4)for (unsigned int index (0); index <number_of_bytes; indice + = 4) {( red = m_rgba_data[index];rosso = m_rgba_data [indice]; green = m_rgba_data[index + 1];verde = m_rgba_data [indice + 1]; blue = m_rgba_data[index + 2];blu = m_rgba_data [indice + 2];
// close the file/ / Chiudere il file fout.close();fout.close (); }) elsealtro {( // post file not found message/ / Post Impossibile trovare il file di messaggio cout << "What is this " << filename << " you speak of?";cout << "Che cos'è questo" <<nomefile << "si parla di?"; }) })
// this is a struct for handling color vectors/ / Questa è una struct per la gestione del colore vettori struct color_vectorstruct color_vector {( // rgb data/ / RGB dati BYTE r;BYTE r; BYTE g;BYTE g; BYTE b;BYTE b; };);
#endif# endif
main.cppmain.cpp
CODE : CODICE:
#include <iostream># include <iostream> #include <windows.h># include <windows.h> #include "bitmap_class.h"# include "bitmap_class.h" using namespace std;using namespace std;
// functions for the example/ / Funzioni per l'esempio BYTE Red(COLORREF color);BYTE Rosso (COLORREF colore); BYTE Green(COLORREF color);BYTE verde (COLORREF colore); BYTE Blue(COLORREF color);BYTE Blu (COLORREF colore);
int main(int argc, char * argv)int main (int argc, char * argv) {( // some variables/ / Alcune variabili int red(0), green(0), blue(0);int rosso (0), verde (0), blu (0); int x(0), y(0);int x (0), y (0); COLORREF color(0);COLORREF colore (0);
// open an existing bitmap (use your favorite here)/ / Apre una bitmap (usare il tuo preferito qui) cBitmap test("0x0badf00d.bmp", 0, 0, 0);cBitmap prova ( "0x0badf00d.bmp", 0, 0, 0);
// get a color in Windows format/ / Ottenere un colore in formato Windows color = test.GetPixel(0, 0);test.GetPixel color = (0, 0); cout << "Obtained a pixel value..."cout << "ha ottenuto un valore di pixel ..."<< endl;<<Endl;
// RGB data analysis/ / RGB analisi dei dati cout << "At the point (0, 0) the color is: ";cout << "Al punto (0, 0) è il colore:"; cout << "(" << int(Red(color)) << ", ";cout << "(" <<int (Rosso (colore)) << ","; cout << int(Green(color)) << ", " << int(Blue(color)) << ")" << endl;cout <<int (verde (a colori)) << "," <<int (blu (colore)) << ")" <<endl;
// change a color "magenta at (0, 0)"/ / Cambiare un colore "magenta a (0, 0)" test.PutPixel(0, 0, 255, 0, 255, 0);test.PutPixel (0, 0, 255, 0, 255, 0); cout << "Placed a new pixel color at (0, 0)."cout << "Posto un nuovo colore dei pixel a (0, 0)".<< endl;<<Endl;
// save the bitmap/ / Salvare l'immagine bitmap test.SaveBitmap("newfile.bmp");test.SaveBitmap ( "newfile.bmp"); cout << "Saved the file to this directory as newfile.bmp."cout << "salvate il file in questa directory come newfile.bmp".<< endl;<<Endl;
// destructor fired and deallocated memory/ / Destructor sparato e deallocated memoria cout << "Look in the top left corner of newfile.bmp!"cout << "Guarda in alto a sinistra della newfile.bmp!"<< endl;<<Endl; return 0;return 0; })
// function to obtain red data from a COLORREF value/ / Funzione per ottenere rosso i dati da un valore COLORREF BYTE Red(COLORREF color)BYTE Rosso (COLORREF colore) {( return (color & 0x000000ff);andata e ritorno (a colori e 0x000000ff); })
// and green/ / E verde BYTE Green(COLORREF color)BYTE verde (COLORREF colore) {( return (color & 0x0000ff00) << 8;andata e ritorno (a colori e 0x0000ff00) <<8; })
// and also blue/ / E anche blu BYTE Blue(COLORREF color)BYTE Blu (COLORREF colore) {( return (color & 0x00ff0000) << 16;andata e ritorno (a colori e 0x00ff0000) <<16; })
// and alpha if you're froggy/ / E alfa se stai froggy BYTE Alpha(COLORREF color)BYTE Alpha (COLORREF colore) {( return (color & 0xff000000) << 24;andata e ritorno (a colori e 0xff000000) <<24; })
Conclusion Conclusione
I have actually used this class to solve some of the challenges on this website. Ho effettivamente utilizzata questa classe per risolvere alcune delle sfide su questo sito.I encourage you to keep screwing around with stuff, because you learn more by doing for yourself than any book can teach you! Vi incoraggio a mantenere intorno con avvitamento roba, perché si impara di più da fare per te di qualsiasi libro si può insegnare!Always keep pushing the envelope. Semper mantenere spingere la busta.
- 195948557 - 195948557
PS: You will see me often say that you should go to the library.PS: Si vedrà spesso mi dicono che si dovrebbe andare alla biblioteca.I'm not trying to be condescending - this is the secret to knowledge and ability.Non sto cercando di essere condiscendente - questo è il segreto di conoscenze e capacità.Yes, they may be analog devices, but books are so very valuable.Sì, essi possono essere dispositivi analogici, ma i libri sono molto preziose.There is nothing wrong with educating yourself.Non c'è niente di sbagliato con te educare.Some of the greatest knowledge you could possibly obtain is that which no one else can teach you.Alcuni dei maggiori conoscenze che si potrebbe ottenere è quello che nessun altro si può insegnare.
Educate yourself.Educare te stesso. Become strong.Diventa forte. Guard your secrets.Difendi il tuo segreto.
<3<3<3<3 <3 <3
- 195948557- 195948557
Cast your vote on this article Cast il vostro voto su questo articolo *Note: the order of the votes has been reversed. * Nota: l'ordine delle votazioni è stato invertito.