简体   繁体   English

将RGB值写入BITMAP图像文件

[英]Write RGB values to a BITMAP image file

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. 我目前正在使用数组存储来自宽度为120像素,高度为100像素的24位BITMAP图像的R,G,B值进行成像处理。 Visual Studio 2010 is being used. 正在使用Visual Studio 2010。

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). 我目前已从24位位图中将各个R,G,B值提取到三个单独的2D数组中(假定正确的R,G,B值也已被写入具有正确像素数的文本文件中,因此被认为是正确的) 。

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. 这些单独的R,G,B值需要还原回数组(1D或2D),然后将其写入图像文件。 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); 
    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 didn't test by myself, but at this point 我没有自己测试,但是在这一点上

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++];

}

You inclement counter too many times, and it may lead to incorrect result. 您增加counter次数过多,可能会导致错误的结果。
Instead, try this: 相反,请尝试以下操作:

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++;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM