将RGB值结构回BITMAP图像文件 [英] Structure RGB values back into BITMAP image file

查看:90
本文介绍了将RGB值结构回BITMAP图像文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好。



我目前正在使用数组进行成像处理,以存储宽度为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆