void LoadRGBAImage(TEXTURE_RGBA& tex, string Filename, string MkFilename) { unsigned char col[3]; unsigned int ind = 0; TEXTURE_RGBA& bitmap = tex; //返回位图 bitmap.buffer = nullptr; bitmap.sizeX = bitmap.sizeY = 0; std::ifstream bmpfile(Filename, std::ios::binary | std::ios::in); //位图文件(二进制) std::ifstream maskfile(MkFilename, std::ios::binary | std::ios::in); //遮罩位图文件(二进制) if (!bmpfile.is_open()) { printf("[console][Warning] Cannot load %s\n", Filename.c_str()); return; } BITMAPFILEHEADER bfh; //各种关于文件的参数 BITMAPINFOHEADER bih; //各种关于位图的参数 //开始读取 maskfile.read((char*)&bfh, sizeof(BITMAPFILEHEADER)); //这两个是占位mask文件的 maskfile.read((char*)&bih, sizeof(BITMAPINFOHEADER)); //到了后面mask可以直接从颜色部分开始读取 bmpfile.read((char*)&bfh, sizeof(BITMAPFILEHEADER)); //真正的info以这个bmp文件为准 bmpfile.read((char*)&bih, sizeof(BITMAPINFOHEADER)); //它将覆盖之前从mask文件读出来的info数据 bitmap.sizeX = bih.biWidth; bitmap.sizeY = bih.biHeight; bitmap.buffer = unique_ptr<ubyte[]>(new unsigned char[bitmap.sizeX * bitmap.sizeY * 4]); bool noMaskFile = MkFilename == ""; for (unsigned int i = 0; i < bitmap.sizeX * bitmap.sizeY; i++) { //把BGR格式转换为RGB格式 bmpfile.read((char*)col, 3); bitmap.buffer[ind++] = col[2]; //R bitmap.buffer[ind++] = col[1]; //G bitmap.buffer[ind++] = col[0]; //B if (noMaskFile) { bitmap.buffer[ind++] = 255; } else { //将遮罩图的红色通道反相作为Alpha通道 maskfile.read((char*)col, 3); bitmap.buffer[ind++] = 255 - col[2]; //A } } bmpfile.close(); maskfile.close(); }
void SaveBMP ( const char * szFile, CRaster bmp, int temp_i ) { BITMAPFILEHEADER bmfh; bmfh.bfType='MB', //PALETTE bmfh.bfSize = ( sizeof(bmfh) + sizeof(BITMAPINFO) + 1024 + (bmp.Width*bmp.Height));//quizas -4 bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = 1078; BITMAPINFOHEADER bmih = bmp.pbmi->bmiHeader; // Open file. ofstream bmpfile (szFile , ios::out | ios::binary); if (! bmpfile.is_open()) cout << "ERROR SAVING FILE" << endl; // Error opening file //Save bitmap fileheader & infoheader bmpfile.write ((char*)&bmfh,sizeof (BITMAPFILEHEADER)); bmpfile.write ((char*)&bmih,sizeof (BITMAPINFOHEADER)); int i, j; for( i = 0; i < 256; i++ ){ bmpfile.write ((char*)&bmp.Palette[i], sizeof(char)*4); } //Save the data for( i = (bmp.Height-1); i >= 0; i-- ) for( j = 0; j < bmp.Width+temp_i; j++ ) { bmpfile.write ((char*)&bmp.Raster[i][j], sizeof(char)); } bmpfile.close(); }
/// /// LDR I/O, only available to LDR images void SaveBmp(const std::string& file_name) { BOOST_STATIC_ASSERT( (boost::is_same<T, UCHAR>::value) ); BOOST_STATIC_ASSERT( channel == 3 ); size_t pos = file_name.find_last_of("."); std::string file_type = file_name.substr(++pos, std::string::npos); boost::to_lower(file_type); assert(file_type == "bmp"); // create output file ofstream bmpfile(file_name.c_str(), ios::out | ios::binary); if(!bmpfile) { assert(0); return; } // save bitmap file header BITMAPFILEHEADER fileHeader; memset(&fileHeader, 0, sizeof(BITMAPFILEHEADER)); fileHeader.bfType = 0x4d42; fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); if(!bmpfile.write((char*)&fileHeader, sizeof(fileHeader))) { assert(0); bmpfile.close(); return; } // save bitmap info header BITMAPINFOHEADER infoHeader; memset(&infoHeader, 0, sizeof(BITMAPINFOHEADER)); infoHeader.biSize = sizeof(infoHeader); infoHeader.biWidth = GetWidth(); infoHeader.biHeight = GetHeight(); infoHeader.biPlanes = 1; infoHeader.biBitCount = sizeof(UCHAR)*GetChannel()*8; infoHeader.biCompression = BI_RGB; if(!bmpfile.write((char*)&infoHeader, sizeof(infoHeader))) { assert(0); bmpfile.close(); return; } UCHAR * swap_channel_data = new UCHAR[GetWidth() * GetHeight() * GetChannel()]; memcpy(swap_channel_data, GetData(), GetWidth() * GetHeight() * GetChannel()); for (UINT i = 0; i < GetWidth() * GetHeight() * GetChannel(); i += GetChannel()) swap(swap_channel_data[i], swap_channel_data[i + 2]); // save bitmap data if(!bmpfile.write((char*)swap_channel_data, GetWidth() * GetHeight() * GetChannel())) { assert(0); bmpfile.close(); return; } delete[] swap_channel_data; bmpfile.close(); }
// ********** // CRaster::LoadBMPFile (FileName); // - loads a BMP file into a CRaster object // * supports non-RLE-compressed files of 1, 2, 4, 8 & 24 bits-per-pixel void CRaster::LoadBMP (char * szFile) { BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; // Open file. ifstream bmpfile (szFile , ios::in | ios::binary); if (! bmpfile.is_open()) { cout << "ERROR OPENING FILE" << endl; // Error opening file system("PAUSE"); } // Load bitmap fileheader & infoheader bmpfile.read ((char*)&bmfh,sizeof (BITMAPFILEHEADER)); bmpfile.read ((char*)&bmih,sizeof (BITMAPINFOHEADER)); // Check filetype signature if (bmfh.bfType!='MB') { cout << "ERROR FILE IS NOT BMP" << endl; // File is not BMP system("PAUSE"); } // Assign some short variables: BPP=bmih.biBitCount; //bits per pixel if ( BPP != 8 ) { cout << "ERROR THE BMP FILE SHOULD BE 8 BPP" << endl; system("PAUSE"); } Width=bmih.biWidth; Height= (bmih.biHeight>0) ? bmih.biHeight : -bmih.biHeight; // absoulte value BytesPerRow = Width * BPP / 8; BytesPerRow += (4-BytesPerRow%4) % 4; // int alignment // If BPP aren't 24, load Palette: if (BPP==24) pbmi=(BITMAPINFO*)new char [sizeof(BITMAPINFO)]; else { pbmi=(BITMAPINFO*) new char[sizeof(BITMAPINFOHEADER)+(1<<BPP)*sizeof(RGBQUAD)]; Palette=(RGBQUAD*)((char*)pbmi+sizeof(BITMAPINFOHEADER)); bmpfile.read ((char*)Palette,sizeof (RGBQUAD) * (1<<BPP)); } pbmi->bmiHeader=bmih; // Load Raster bmpfile.seekg (bmfh.bfOffBits,ios::beg); // Raster= new char[BytesPerRow*Height]; //COMIENZO int i, bitwidth; bitwidth = ((BytesPerRow / sizeof(char))); if((BytesPerRow % sizeof(char) > 0 )) bitwidth++; // cout << bitwidth << endl; // system("PAUSE"); //start //se reserva memoria para las filas Raster = new char*[Height]; //se reserva memoria para las columnas for( i = 0; i <= Width; i++ ) Raster[i] = new char[Width]; //end FIN //El problema ESTA AQUI!!!! // (if height is positive the bmp is bottom-up, read it reversed) if (bmih.biHeight>0) //NO SE DE ESTAS LINEAS for (int n=Height-1; n>=0; n--) bmpfile.read (Raster[n],BytesPerRow); else //NO SE DE ESTAS LINEAS bmpfile.read (Raster,BytesPerRow*Height); //NO SE DE ESTAS LINEAS // so, we always have a up-bottom raster (that is negative height for windows): pbmi->bmiHeader.biHeight=-Height; bmpfile.close(); cout << "SIZE OF THE BMP ---> " << ( sizeof(bmfh) + sizeof(BITMAPINFO) + 1024 + (Width*Height)-4) << endl; // system("PAUSE"); }
/** * BMPImage::LoadBMPFile (FileName); * - loads a BMP file into a BMPImage object * - supports non-RLE-compressed files of 1, 2, 4, 8 & 24 bits-per-pixel * - requires power of two bitmap. yes really. otherwise wonky rendering! **/ int BMPImage::LoadBMP (const char* szFile) { #if defined(ARK2D_MACINTOSH) ErrorDialog::createAndShow(StringUtil::append("Loading bitmaps is broken on Mac: ", string(szFile))); exit(0); #endif ARK2D_BITMAPFILEHEADER bmfh; ARK2D_BITMAPINFOHEADER bmih; // Open file. ifstream bmpfile (szFile , ios::in | ios::binary); if (! bmpfile.is_open()) return 1; // Error opening file // Load bitmap fileheader & infoheader bmpfile.read ((char*)&bmfh, sizeof (ARK2D_BITMAPFILEHEADER)); bmpfile.read ((char*)&bmih, sizeof (ARK2D_BITMAPINFOHEADER)); // Check filetype signature //if (bmfh.bfType != 'MB') return 2; // File is not BMP char* first = (char*) &bmfh.bfType; if ((*first) != 'M') return 2; // File is not BMP if ((*first+1) != 'B') return 2; // File is not BMP // Assign some short variables: BPP = bmih.biBitCount; Width = bmih.biWidth; Height = (bmih.biHeight>0) ? bmih.biHeight : -bmih.biHeight; // absoulte value BytesPerRow = Width * BPP / 8; BytesPerRow += (4-BytesPerRow%4) % 4; // int alignment // If BPP aren't 24, load Palette: if (BPP==24) pbmi=(ARK2D_BITMAPINFO*)new char [sizeof(ARK2D_BITMAPINFO)]; else { pbmi=(ARK2D_BITMAPINFO*) new char[sizeof(ARK2D_BITMAPINFOHEADER)+(1<<BPP)*sizeof(ARK2D_RGBQUAD)]; Palette=(ARK2D_RGBQUAD*)((char*)pbmi+sizeof(ARK2D_BITMAPINFOHEADER)); bmpfile.read ((char*)Palette,sizeof (ARK2D_RGBQUAD) * (1<<BPP)); } pbmi->bmiHeader=bmih; // Load Raster bmpfile.seekg (bmfh.bfOffBits, ios::beg); Raster = new char[BytesPerRow*Height]; // (if height is positive the bmp is bottom-up, read it reversed) if (bmih.biHeight>0) for (int n=Height-1;n>=0;n--) bmpfile.read (Raster+BytesPerRow*n,BytesPerRow); else bmpfile.read (Raster,BytesPerRow*Height); // so, we always have a up-bottom raster (that is negative height for windows): pbmi->bmiHeader.biHeight=-Height; bmpfile.close(); return 0; }
// **************************************************************************** // * SaveBMP * // * Save the content of a C_Image object into a BMP file * // * (c) Sept2000, Juan Soulie <*****@*****.**> * // **************************************************************************** int C_Image::SaveBMP (char * szFileName) { int n; // Create file. ofstream bmpfile (szFileName , ios::out | ios::binary | ios::trunc); if (! bmpfile.is_open()) { ERRORMSG("Error creating file"); return 0;} // determine BPP for file: int SaveBPP; if (BPP == 1) SaveBPP=1; else if (BPP <= 4) SaveBPP=4; else if (BPP <= 8) SaveBPP=8; else SaveBPP=24; // *1* SAVE BITMAP FILE HEADER struct BITMAPFILEHEADER { unsigned short bfType; unsigned long bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; } bmfh; bmfh.bfType='MB'; bmfh.bfSize=0; // TO DO bmfh.bfReserved1 = bmfh.bfReserved2 = 0; bmfh.bfOffBits = 54 + ((SaveBPP==24) ? 0 : (1<<SaveBPP)*4); bmpfile.write ((char*)&bmfh,sizeof (bmfh)); // *2* SAVE BITMAP INFO HEADER struct BITMAPINFOHEADER { unsigned long biSize; long biWidth; long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } bmih; bmih.biSize=sizeof(bmih); bmih.biWidth=Width; bmih.biHeight=Height; // down-top bmih.biPlanes=1; bmih.biBitCount=SaveBPP; bmih.biCompression=0;// BI_RGB? bmih.biSizeImage =(Width*BPP)/8; bmih.biSizeImage += (4- (bmih.biSizeImage)%4)%4; bmih.biXPelsPerMeter=11811; bmih.biYPelsPerMeter=11811; bmih.biClrUsed=0; bmih.biClrImportant=0; bmpfile.write ((char*)&bmih,sizeof (bmih)); // *3* IF BPP AREN'T 24, SAVE PALETTE. if (BPP!=24) { for (n=0;n< 1<<BPP;n++) { bmpfile.put(Palette[n].b); bmpfile.put(Palette[n].g); bmpfile.put(Palette[n].r); bmpfile.put((char)0); } for (;n < 1<<SaveBPP; n++) // in case SaveBPP is higher than BPP bmpfile.write((char*)'\0\0\0\0',4); } // *4* SAVE RASTER DATA int PixelsPerByte = 8/SaveBPP; //used only if BPP are less than 8 int BitMask = (1<<SaveBPP)-1; //used only if BPP are less than 8 // Raster Data Rows are 32bit aligned in BMP files. int RowAlignmentInFile = ((4- ((Width*SaveBPP+7)/8)%4)%4); // (bytes) for (int row=0; row<Height; row++) { char * pPixel; // If height is positive the bmp is bottom-up, set adequate row info: pPixel= (char*) Raster + BytesPerRow * ( (bmih.biHeight>0)? Height-row-1 : row ); if (SaveBPP >= 8) // 8 or more BPP: Save as block. bmpfile.write (pPixel, Width*SaveBPP/8); else // Less than 8BPP: Save packing bytes. { unsigned char charToPut; for (int col=0; col < Width; col+=PixelsPerByte) { charToPut=0; for (int bit=8 ; bit >0 ; bit -= BPP) // high to low charToPut |= (*pPixel++ & BitMask) << (bit - BPP); bmpfile.put(charToPut); } } // Ignore aligment bytes of file: for (int m=0; m<RowAlignmentInFile; m++) bmpfile.put ((char)0); } bmpfile.close(); return 1; }
// **************************************************************************** // * LoadBMP * // * Load a BMP File into the C_Image object * // * (c) Sept2000, Juan Soulie <*****@*****.**> * // **************************************************************************** int C_Image::LoadBMP (char* szFileName) { int n; // Open file. ifstream bmpfile (szFileName , ios::in | ios::binary | ios::nocreate); if (! bmpfile.is_open()) { ERRORMSG("File not found"); return 0; } // *1* LOAD BITMAP FILE HEADER struct BITMAPFILEHEADER { unsigned short bfType; unsigned long bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; } bmfh; bmpfile.read ((char*)&bmfh,sizeof (bmfh)); // Check filetype signature if (bmfh.bfType!='MB') { ERRORMSG("Not a valid BMP File"); return 0; } // *2* LOAD BITMAP INFO HEADER struct BITMAPINFOHEADER { unsigned long biSize; long biWidth; long biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned long biCompression; unsigned long biSizeImage; long biXPelsPerMeter; long biYPelsPerMeter; unsigned long biClrUsed; unsigned long biClrImportant; } bmih; bmpfile.read ((char*)&bmih,sizeof (bmih)); // Check for supported Color depths if ((bmih.biBitCount!=1) && (bmih.biBitCount!=4) && (bmih.biBitCount!=8) && (bmih.biBitCount!=24)) { ERRORMSG("Color depth not supported"); return 0; } // Check if file is compressed if (bmih.biCompression!=0) { ERRORMSG("File uses unsupported compression"); return 0; } // Set: Allocate memory to contain Data Init (bmih.biWidth, (bmih.biHeight>0) ? bmih.biHeight: -bmih.biHeight, // abs bmih.biBitCount); // *3* IF BPP AREN'T 24, LOAD PALETTE. if (BPP!=24) { for (n=0;n< 1<<BPP;n++) { Palette[n].b=bmpfile.get(); Palette[n].g=bmpfile.get(); Palette[n].r=bmpfile.get(); bmpfile.get(); // 4th byte of RGBQUAD discarded } } // *4* LOAD RASTER DATA // Seek Raster Data in file bmpfile.seekg (bmfh.bfOffBits,ios::beg); int PixelsPerByte = 8/BPP; //used only if BPP are less than 8 int BitMask = (1<<BPP)-1; //used only if BPP are less than 8 // Raster Data Rows are 32bit aligned in BMP files. int RowAlignmentInFile = ((4- ((Width*BPP+7)/8)%4)%4); // (bytes) for (int row=0; row<Height; row++) { char * pPixel; // If height is positive the bmp is bottom-up, set adequate row info: pPixel= Raster + BytesPerRow * ( (bmih.biHeight>0)? Height-row-1 : row ); if (BPP >= 8) // 8 or more BPP: Read as block. bmpfile.read (pPixel, Width*BPP/8); else // Less than 8BPP: Read and store byte aligned. { int charGot; for (int col=0; col < Width; col+=PixelsPerByte) { charGot=bmpfile.get(); for (int bit=8 ; bit >0 ; bit -= BPP) // high to low *pPixel++ = (charGot>> (bit - BPP)) & BitMask; } } // Ignore aligment bytes of file: for (int m=0; m<RowAlignmentInFile; m++) bmpfile.get (); } bmpfile.close(); return 1; }