Lou*_*s93 7 c++ image bmp armadillo
我有一个文本文件由包含2D矩阵的矩阵库保存,如下所示:
1 0 0
6 0 4
0 1 1
Run Code Online (Sandbox Code Playgroud)
其中每个数字用彩色像素表示.我正在寻找一些关于我如何解决这个问题的见解.如果需要更多信息,请不要犹豫.
编辑:我尝试的另一种方法是:fwrite(&intmatrix, size,1, bmp_ptr);我传入矩阵指针,它似乎没有输出可读的BMP文件.的值size是rows*cols当然的,和矩阵的类型是arma::Mat<int>作为从犰狳线性代数库的矩阵.
编辑II:阅读这表明我的大小应该是行*cols*4给定行的大小如果我没有弄错,任何关于这一点的指导也会很好.
U00*_*07D 12
这是一个应用程序,它生成随机整数的文本文件,将它们读回,并将它们作为(大致正方形)每像素32位.BMP图像写入磁盘.
注意,我对原始文本文件的格式,数字范围等内容做了一些假设,但它们在代码中有记录.通过这个工作示例,您应该能够在必要时轻松调整它们.
// IntToBMP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <cstdint>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <random>
#include <ctime>
#include <memory>
#pragma pack( push, 1 )
struct BMP
{
BMP();
struct
{
uint16_t ID;
uint32_t fileSizeInBytes;
uint16_t reserved1;
uint16_t reserved2;
uint32_t pixelArrayOffsetInBytes;
} FileHeader;
enum class CompressionMethod : uint32_t { BI_RGB = 0x00,
BI_RLE8 = 0x01,
BI_RLE4 = 0x02,
BI_BITFIELDS = 0x03,
BI_JPEG = 0x04,
BI_PNG = 0x05,
BI_ALPHABITFIELDS = 0x06 };
struct
{
uint32_t headerSizeInBytes;
uint32_t bitmapWidthInPixels;
uint32_t bitmapHeightInPixels;
uint16_t colorPlaneCount;
uint16_t bitsPerPixel;
CompressionMethod compressionMethod;
uint32_t bitmapSizeInBytes;
int32_t horizontalResolutionInPixelsPerMeter;
int32_t verticalResolutionInPixelsPerMeter;
uint32_t paletteColorCount;
uint32_t importantColorCount;
} DIBHeader;
};
#pragma pack( pop )
BMP::BMP()
{
//Initialized fields
FileHeader.ID = 0x4d42; // == 'BM' (little-endian)
FileHeader.reserved1 = 0;
FileHeader.reserved2 = 0;
FileHeader.pixelArrayOffsetInBytes = sizeof( FileHeader ) + sizeof( DIBHeader );
DIBHeader.headerSizeInBytes = 40;
DIBHeader.colorPlaneCount = 1;
DIBHeader.bitsPerPixel = 32;
DIBHeader.compressionMethod = CompressionMethod::BI_RGB;
DIBHeader.horizontalResolutionInPixelsPerMeter = 2835; // == 72 ppi
DIBHeader.verticalResolutionInPixelsPerMeter = 2835; // == 72 ppi
DIBHeader.paletteColorCount = 0;
DIBHeader.importantColorCount = 0;
}
void Exit( void )
{
std::cout << "Press a key to exit...";
std::getchar();
exit( 0 );
}
void MakeIntegerFile( const std::string& integerFilename )
{
const uint32_t intCount = 1 << 20; //Generate 1M (2^20) integers
std::unique_ptr< int32_t[] > buffer( new int32_t[ intCount ] );
std::mt19937 rng;
uint32_t rngSeed = static_cast< uint32_t >( time( NULL ) );
rng.seed( rngSeed );
std::uniform_int_distribution< int32_t > dist( INT32_MIN, INT32_MAX );
for( size_t i = 0; i < intCount; ++i )
{
buffer[ i ] = dist( rng );
}
std::ofstream writeFile( integerFilename, std::ofstream::binary );
if( !writeFile )
{
std::cout << "Error writing " << integerFilename << ".\n";
Exit();
}
writeFile << buffer[ 0 ];
for( size_t i = 1; i < intCount; ++i )
{
writeFile << " " << buffer[ i ];
}
}
int _tmain(int argc, _TCHAR* argv[]) //Replace with int main( int argc, char* argv[] ) if you're not under Visual Studio
{
//Assumption: 32-bit signed integers
//Assumption: Distribution of values range from INT32_MIN through INT32_MAX, inclusive
//Assumption: number of integers contained in file are unknown
//Assumption: source file of integers is a series of space-delimitied strings representing integers
//Assumption: source file's contents are valid
//Assumption: non-rectangular numbers of integers yield non-rectangular bitmaps (final scanline may be short)
// This may cause some .bmp parsers to fail; others may pad with 0's. For simplicity, this implementation
// attempts to render square bitmaps.
const std::string integerFilename = "integers.txt";
const std::string bitmapFilename = "bitmap.bmp";
std::cout << "Creating file of random integers...\n";
MakeIntegerFile( integerFilename );
std::vector< int32_t >integers; //If quantity of integers being read is known, reserve or resize vector or use array
//Read integers from file
std::cout << "Reading integers from file...\n";
{ //Nested scope will release ifstream resource when no longer needed
std::ifstream readFile( integerFilename );
if( !readFile )
{
std::cout << "Error reading " << integerFilename << ".\n";
Exit();
}
std::string number;
while( readFile.good() )
{
std::getline( readFile, number, ' ' );
integers.push_back( std::stoi( number ) );
}
if( integers.size() == 0 )
{
std::cout << "No integers read from " << integerFilename << ".\n";
Exit();
}
}
//Construct .bmp
std::cout << "Constructing .BMP...\n";
BMP bmp;
size_t intCount = integers.size();
bmp.DIBHeader.bitmapSizeInBytes = intCount * sizeof( integers[ 0 ] );
bmp.FileHeader.fileSizeInBytes = bmp.FileHeader.pixelArrayOffsetInBytes + bmp.DIBHeader.bitmapSizeInBytes;
bmp.DIBHeader.bitmapWidthInPixels = static_cast< uint32_t >( ceil( sqrt( intCount ) ) );
bmp.DIBHeader.bitmapHeightInPixels = static_cast< uint32_t >( ceil( intCount / static_cast< float >( bmp.DIBHeader.bitmapWidthInPixels ) ) );
//Write integers to .bmp file
std::cout << "Writing .BMP...\n";
{
std::ofstream writeFile( bitmapFilename, std::ofstream::binary );
if( !writeFile )
{
std::cout << "Error writing " << bitmapFilename << ".\n";
Exit();
}
writeFile.write( reinterpret_cast< char * >( &bmp ), sizeof( bmp ) );
writeFile.write( reinterpret_cast< char * >( &integers[ 0 ] ), bmp.DIBHeader.bitmapSizeInBytes );
}
//Exit
Exit();
}
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助.
如果选择正确的图像格式,这很容易. PGM有一个ASCII变体,看起来几乎与你的矩阵一样,但有一个标题.
P2
3 3
6
1 0 0
6 0 4
0 1 1
Run Code Online (Sandbox Code Playgroud)
P2ASCII PGM的魔力在哪里,大小为3x3,6是maxval.我选择了6,因为这是你提出的最大值,这使得6白色(而0是黑色).在典型的255的PGM中,这与8位灰度图像一致.
PPM几乎一样简单,每个像素只有3个颜色分量而不是1个.
您可以使用任何需要PPM(netpbm,ImageMagick,GIMP等)的图像对这些图像进行操作.您可以将它们重新保存为二进制PPM,其大小与等效的BMP基本相同.
要输出可读的BMP文件,您需要先放置标题:
#include <WinGDI.h>
DWORD dwSizeInBytes = rows*cols*4; // when your matrix contains RGBX data)
// fill in the headers
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4D42; // 'BM'
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwSizeInBytes;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = cols;
bmih.biHeight = rows;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
Run Code Online (Sandbox Code Playgroud)
现在,在编写颜色信息之前,只需编写位图标题
fwrite(&bmfh, sizeof(bmfh),1, bmp_ptr);
fwrite(&bmih, sizeof(bmih),1, bmp_ptr);
Run Code Online (Sandbox Code Playgroud)
最后是颜色信息:
fwrite(&intmatrix, size, sizeof(int), bmp_ptr);
Run Code Online (Sandbox Code Playgroud)
请注意,块大小为sizeof(int),因为矩阵不包含单个字符,而是每个值的整数.根据矩阵的内容,将值转换为COLORREF值可能是一个好主意(检查RGB宏,也可以在WinGDI.h中找到)