CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Oct 2015
    Posts
    18

    Restore RGB values back into BITMAP image file

    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).

    The task is to take these individual R,G,B values and restore them 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.

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

  2. #2
    2kaud's Avatar
    2kaud is online now Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: Restore RGB values back into BITMAP image file

    Code:
    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++];
    This is incrementing counter 3 times - once after each statement. Consider
    Code:
    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++];
    to match the reading.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Jun 2002
    Location
    Stockholm, Sweden
    Posts
    1,641

    Re: Restore RGB values back into BITMAP image file

    Code:
    	for(int i = 0; i <height; i++)
    	{
    		m_pOutFileRGB->write(reinterpret_cast<char*>(array_1D), width*bytesPerPixel); 
    		
    	}
    Also, this looks fishy. You are writing the same data to file many times.
    Nobody cares how it works as long as it works

  4. #4
    Join Date
    Oct 2015
    Posts
    18

    Re: Restore RGB values back into BITMAP image file

    Quote Originally Posted by 2kaud View Post
    Code:
    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++];
    This is incrementing counter 3 times - once after each statement. Consider
    Code:
    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++];
    to match the reading.
    Thanks. I tried this but the RGB values (when reading from the array_1D) are incorrect and the image output consequently is still incorrect.

  5. #5
    Join Date
    Aug 2000
    Location
    New York, NY, USA
    Posts
    5,656

    Re: Restore RGB values back into BITMAP image file

    Could you load that new image into your program and dump it to another text file? Then see where your RGB values differ.
    Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
    Convenience and productivity tools for Microsoft Visual Studio:
    FeinWindows - replacement windows manager for Visual Studio, and more...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured