将RGB值结构回BITMAP图像文件 [英] Structure RGB values back into BITMAP image file
问题描述
大家好。
我目前正在使用数组进行成像处理,以存储宽度为120和高度的24位BITMAP图像的R,G,B值100像素。
正在使用Visual Studio 2010。
我目前从24位位图中将各个R,G,B值提取到三个独立的二维数组中(假设正确的R,G,B)值已被写入具有正确像素数的文本文件中。
这些单独的R,G,B值需要恢复为数组( 1D或2D),然后写入图像文件。输出应该与原始图像相同。
我尝试了以下但输出当前不正确(相同的宽度,高度和内存大小但着色不正确) 。
感谢您的指导和反馈。
#include < iostream >
#include < fstream >
#include < windows.h >
#include < WinGDI.h >
unsigned < span class =code-keyword> char ** Allocate2DArray( int w, int h)
{
unsigned char ** buffer = new unsigned char * [h]; // 分配行
unsigned char * memory_pool = new unsigned char [w * h]; // 分配内存池
( int i = 0 ; i< h; ++ i)
{
buffer [i] = memory_pool; // 点行指针
memory_pool + = w; // 转到内存池的下一行
}
return buffer;
}
void DeAllocate2DArray( unsigned char ** buffer)
{
delete [] buffer [ 0 跨度>]; // 删除内存池
delete []缓冲区; // 删除行指针
}
使用 命名空间标准;
int main()
{
const int width = 120 ;
const int height = 100 ;
int bytesPerPixel = 3 ;
unsigned char m_cHeaderData [ 54 ];
unsigned char ** m_cImageData = new unsigned char * [height];
for ( int i = 0 ; i< height; i ++)
{
m_cImageData [i] = new unsigned char [width * bytesPerPixel];
}
ifstream * m_pInFile;
m_pInFile = 新 ifstream;
m_pInFile-> open( image.bmp,ios :: in | ios :: binary);
m_pInFile-> seekg( 0 ,ios :: beg);
m_pInFile-> read(reinterpret_cast< char *>(m_cHeaderData), 54 );
for ( int i = 0 ; i< height; i ++)
{
m_pInFile-> read(reinterpret_cast< char *>(m_cImageData [i]),width * bytesPerPixel);
}
m_pInFile-> close();
// 声明所需类型的指针。
// 这将指向1D数组
< span class =code-keyword> unsigned char * array_1D;
array_1D = new unsigned char [高度*宽* bytesPerPixel];
if (array_1D == NULL) return 0 跨度>; // 如果未分配内存则返回
// 从现有2D数组复制内容
int 偏移量= 0 ;
for ( int j = 0 ; j< height; j ++) // 遍历高度(或行)
{
offset = width * bytesPerPixel * j;
for ( int i = 0 ; i< width * bytesPerPixel; i ++) // 遍历宽度
{
array_1D [offset + i] = m_cImageData [j] [i];
// 当前(i,j)的更新值
}
}
// 声明三个2D数组到存储图像的R,G和B平面。
unsigned char ** arrayR_2D,** arrayG_2D,** arrayB_2D;
arrayR_2D = Allocate2DArray(width,height);
arrayG_2D = Allocate2DArray(宽度,高度);
arrayB_2D = Allocate2DArray(width,height);
// 如果未分配内存则返回
if (arrayR_2D == NULL || arrayG_2D == NULL || arrayB_2D == NULL) return 0 跨度>;
// 从现有复合材料1D中提取R,G,B平面数组
ofstream RGBdata2D;
RGBdata2D.open( RGBdata2D.txt);
int pixelCount = 0 ;
int offsetx = 0 ;
int counter = 0 ;
for ( int j = 0 ; j< height; j ++) // 遍历高度(或行)
{
offsetx = width * j * bytesPerPixel;
for ( int i = 0 ; i< width * bytesPerPixel; i + = bytesPerPixel) // width
{
arrayB_2D [j] [counter] = array_1D [offsetx + i + 0];
arrayG_2D [j] [counter] = array_1D [offsetx + i + 1];
arrayR_2D [j] [counter] = array_1D [offsetx + i + 2];
RGBdata2D<< B:<< ( int )arrayB_2D [j] [counter]<< G:<< ( int )arrayG_2D [j] [counter]<< R:<< ( int )arrayR_2D [j] [counter]<< ENDL;
pixelCount ++;
++ counter;
}
counter = 0 ;
}
RGBdata2D<< 像素数:<< pixelCount<< ENDL;
RGBdata2D.close();
// 将RGB数组内容中的RGB放回1D数组
offset = 0 ;
counter = 0 ;
for ( int j = 0 ; j< height; j ++) // 遍历高度(或行)
{
offset = width * bytesPerPixel * j;
for ( int i = 0 ; i< width * bytesPerPixel; i + = bytesPerPixel) // width
{
array_1D [offset + i + 0] = arrayB_2D [j] [counter ++];
array_1D [offset + i + 1] = arrayG_2D [j] [counter ++];
array_1D [offset + i + 2] = arrayR_2D [j] [counter ++];
}
counter = 0 ;
}
ofstream * m_pOutFileRGB;
m_pOutFileRGB = new ofstream;
m_pOutFileRGB-> open( imageCopyRGB.bmp,ios :: out | ios :: trunc | ios :: binary);
m_pOutFileRGB-> write(reinterpret_cast< char *>(m_cHeaderData), 54 ); // 位图位从偏移量1078开始
for ( int i = 0 ; i< height; i ++)
{
m_pOutFileRGB-> write(reinterpret_cast< char *>(array_1D),width * bytesPerPixel);
}
m_pOutFileRGB-> close();
// 完成使用后,动态删除内存已分配
DeAllocate2DArray(arrayR_2D);
DeAllocate2DArray(arrayG_2D);
DeAllocate2DArray(arrayB_2D);
// 完成使用后,删除动态分配的内存
delete [] array_1D; // 删除指针指针
for ( int i = 0 ; i< height ; i ++)
{
delete [] m_cImageData [i];
}
delete [] m_cImageData;
system( pause);
return 0 ;
}
我不知道这是否能解决你所有的问题但是,请尝试更换它:
array_1D [offset + i + 0] = arrayB_2D [j] [counter ++];
array_1D [offset + i + 1] = arrayG_2D [j] [counter ++];
array_1D [offset + i + 2] = arrayR_2D [j] [counter ++];
...这个......
array_1D [offset + i + 0] = arrayB_2D [j] [counter];
array_1D [offset + i + 1] = arrayG_2D [j] [counter];
array_1D [offset + i + 2] = arrayR_2D [j] [counter];
counter ++;
一些额外的建议:
1. don不要无偿地使用指针和新的指针。它经常导致内存泄漏。例如:
ifstream * m_pInFile;
m_pInFile = 新 ifstream;
m_pInFile-> open( image.bmp,ios :: in | ios :: binary);
m_pInFile-> seekg( 0 ,ios :: beg);
m_pInFile-> read(reinterpret_cast< char *>(m_cHeaderData), 54 );
for ( int i = 0 ; i< height; i ++)
{
m_pInFile-> read(reinterpret_cast< char *>(m_cImageData [i]),width * bytesPerPixel);
}
m_pInFile-> close();
这可以写成:
< pre lang =c ++> ifstream m_pInFile;
m_pInFile.open( image.bmp,ios :: in | ios :: binary);
m_pInFile.seekg( 0 ,ios :: beg);
m_pInFile.read(reinterpret_cast< char *>(m_cHeaderData), 54 );
for ( int i = 0 ; i< height; i ++)
{
m_pInFile.read(reinterpret_cast< char *>(m_cImageData [i]),width * bytesPerPixel);
}
m_pInFile.close();
后一种形式不会泄漏内存。
对于您的数组 - 使用std :: vector。
Hello all.
I am currently working on imaging processing using arrays to store R,G,B values from a 24 bit BITMAP image of width 120 and height 100 pixels.
Visual Studio 2010 is being used.
I have currently extracted the individual R,G,B values into three separate2D arrays from the 24 bit bitmap (it is assumed correct as the correct R,G,B values have been written to a text file with the right pixel count as well).
These individual R,G,B values need to be restored back into an array (either 1D or 2D), which is then written to an image file. The output should be identical to the original image.
I have tried the following but the output is currently incorrect (same width, height and memory size but colouring is incorrect).
Appreciate your guidance and feedback.
#include <iostream>
#include <fstream>
#include <windows.h>
#include <WinGDI.h>
unsigned char** Allocate2DArray(int w, int h)
{
unsigned char ** buffer = new unsigned char * [h]; // allocate the rows
unsigned char * memory_pool = new unsigned char [w*h]; // allocate memory pool
for (int i = 0; i < h; ++i)
{
buffer[i] = memory_pool; // point row pointer
memory_pool += w; // go to next row in memory pool
}
return buffer;
}
void DeAllocate2DArray(unsigned char** buffer)
{
delete [] buffer[0]; // delete the memory pool
delete [] buffer; // delete the row pointers
}
using namespace std;
int main()
{
const int width = 120;
const int height = 100;
int bytesPerPixel = 3;
unsigned char m_cHeaderData[54];
unsigned char** m_cImageData = new unsigned char* [height];
for( int i = 0; i <height; i++)
{
m_cImageData[i] = new unsigned char [width*bytesPerPixel];
}
ifstream* m_pInFile;
m_pInFile = new ifstream;
m_pInFile->open("image.bmp", ios::in | ios::binary);
m_pInFile->seekg(0, ios::beg);
m_pInFile->read(reinterpret_cast<char*>(m_cHeaderData), 54);
for(int i = 0; i <height; i++)
{
m_pInFile->read(reinterpret_cast<char*>(m_cImageData[i]), width*bytesPerPixel);
}
m_pInFile->close();
// Declare a pointer of the type you want.
// This will point to the 1D array
unsigned char* array_1D;
array_1D = new unsigned char[height*width*bytesPerPixel];
if(array_1D == NULL) return 0; // return if memory not allocated
// Copy contents from the existing 2D array
int offset = 0;
for(int j=0; j<height; j++) // traverse height (or rows)
{
offset = width * bytesPerPixel* j;
for(int i=0; i<width*bytesPerPixel; i++) // traverse width
{
array_1D[offset + i] = m_cImageData[j][i];
// update value at current (i, j)
}
}
// Declare three 2D arrays to store R,G, and B planes of image.
unsigned char**arrayR_2D, **arrayG_2D, **arrayB_2D;
arrayR_2D = Allocate2DArray(width, height);
arrayG_2D = Allocate2DArray(width, height);
arrayB_2D = Allocate2DArray(width, height);
// return if memory not allocated
if(arrayR_2D == NULL || arrayG_2D == NULL || arrayB_2D == NULL) return 0;
// Extract R,G,B planes from the existing composite 1D array
ofstream RGBdata2D;
RGBdata2D.open("RGBdata2D.txt");
int pixelCount = 0;
int offsetx = 0;
int counter = 0;
for(int j=0; j<height; j++) // traverse height (or rows)
{
offsetx = width * j * bytesPerPixel;
for(int i=0; i<width*bytesPerPixel; i+=bytesPerPixel) // width
{
arrayB_2D[j][counter] = array_1D[offsetx + i+0];
arrayG_2D[j][counter] = array_1D[offsetx + i+1];
arrayR_2D[j][counter] = array_1D[offsetx + i+2];
RGBdata2D<<"B: "<< (int)arrayB_2D[j][counter] << " G: " << (int)arrayG_2D[j][counter] << " R: " << (int)arrayR_2D[j][counter]<< endl;
pixelCount++;
++counter;
}
counter = 0;
}
RGBdata2D<<"count of pixels: "<< pixelCount << endl;
RGBdata2D.close();
//put RGB from 2D array contents back into a 1D array
offset = 0;
counter = 0;
for(int j=0; j<height; j++) // traverse height (or rows)
{
offset = width * bytesPerPixel * j;
for(int i=0; i<width*bytesPerPixel; i+=bytesPerPixel) // width
{
array_1D[offset + i+0] = arrayB_2D[j][counter++];
array_1D[offset + i+1] = arrayG_2D[j][counter++];
array_1D[offset + i+2] = arrayR_2D[j][counter++];
}
counter = 0;
}
ofstream* m_pOutFileRGB;
m_pOutFileRGB = new ofstream;
m_pOutFileRGB->open("imageCopyRGB.bmp", ios::out | ios::trunc | ios::binary);
m_pOutFileRGB->write(reinterpret_cast<char*>(m_cHeaderData), 54); //bitmap bits start at offset 1078
for(int i = 0; i <height; i++)
{
m_pOutFileRGB->write(reinterpret_cast<char*>(array_1D), width*bytesPerPixel);
}
m_pOutFileRGB->close();
// After complete usage, delete the memory dynamically allocated
DeAllocate2DArray(arrayR_2D);
DeAllocate2DArray(arrayG_2D);
DeAllocate2DArray(arrayB_2D);
// After complete usage, delete the memory dynamically allocated
delete[] array_1D; //delete the pointer to pointer
for(int i = 0; i <height; i++)
{
delete[] m_cImageData[i];
}
delete[] m_cImageData;
system("pause");
return 0;
}
I do not know if this will fix all your problems but, try replacing this:
array_1D[offset + i+0] = arrayB_2D[j][counter++]; array_1D[offset + i+1] = arrayG_2D[j][counter++]; array_1D[offset + i+2] = arrayR_2D[j][counter++];
... with this ...
array_1D[offset + i+0] = arrayB_2D[j][counter]; array_1D[offset + i+1] = arrayG_2D[j][counter]; array_1D[offset + i+2] = arrayR_2D[j][counter]; counter++;
Some additional suggestions:
1. don't make gratuitous use of pointer and new. It often leads to memory leaks. Example:
ifstream* m_pInFile; m_pInFile = new ifstream; m_pInFile->open("image.bmp", ios::in | ios::binary); m_pInFile->seekg(0, ios::beg); m_pInFile->read(reinterpret_cast<char*>(m_cHeaderData), 54); for(int i = 0; i <height; i++) { m_pInFile->read(reinterpret_cast<char*>(m_cImageData[i]), width*bytesPerPixel); } m_pInFile->close();
This could be written as:
ifstream m_pInFile; m_pInFile.open("image.bmp", ios::in | ios::binary); m_pInFile.seekg(0, ios::beg); m_pInFile.read(reinterpret_cast<char*>(m_cHeaderData), 54); for(int i = 0; i <height; i++) { m_pInFile.read(reinterpret_cast<char*>(m_cImageData[i]), width*bytesPerPixel); } m_pInFile.close();
The latter form does not leak memory.
For your arrays - use std::vector.
这篇关于将RGB值结构回BITMAP图像文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!