【问题标题】:Write RGB values to a BITMAP image file将 RGB 值写入 BITMAP 图像文件
【发布时间】:2015-10-12 21:35:54
【问题描述】:

我目前正在使用数组进行图像处理,以存储宽度为 120 像素、高度为 100 像素的 24 位 BITMAP 图像的 R、G、B 值。 正在使用 Visual Studio 2010。

我目前已从 24 位位图中将单个 R、G、B 值提取到三个单独的二维数组中(假设正确,因为正确的 R、G、B 值已写入具有正确像素数的文本文件以及)。

需要将这些单独的 R、G、B 值恢复回一个数组(一维或二维),然后将其写入图像文件。输出应与原始图像相同。

我尝试了以下方法,但当前输出不正确(宽度、高度和内存大小相同,但颜色不正确)。

感谢您的指导和反馈。

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

【问题讨论】:

    标签: c++ image bitmap rgb


    【解决方案1】:

    我没有自己测试,但在这一点上

    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的次数太多,可能会导致错误的结果。
    相反,试试这个:

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

    【讨论】:

    • 感谢您的建议。我现在检查并注意到正确的 R、G、B 值被写入 array_1D (而最初,它们不是)。我仍然需要以某种方式将其正确写入新的 BITMAP 文件。仍然没有给出正确的图像。
    猜你喜欢
    • 2017-06-26
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2013-08-15
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多