Click here to Skip to main content
15,890,579 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello. I am currently trying to extract R, G, B values from a 256 colour bitmap image (using for testing purposes a fixed width of 152 and height 150). I have checked using BITMAPINFOHEADER and BITMAPFILEHEADER that the offset is 1078 and bytes per pixel is 1.

The image data is initially placed in a 2 dimensional array before being placed into a 1 dimensional array. Three 2 dimensional arrays were allocated to hold the R, G, B values from each pixel.

When I run the program, the following Debug Assertion Failed! message appears:
Expression: _BLOCK_TYPE_IS_VALID (pHead->nBlockUse)

Below is the code and I would value your expert feedback and how to fix this error.

C#
unsigned char** Allocate2DArray(unsigned char** buffer, int w, int h)
{
    buffer = new unsigned char*[h];
    if(buffer == NULL) return 0; // return if memory not allocated
    // For each of these pointers, allocate memory of size ‘w’
    for(int j=0; j<h; j++)
    {   buffer[j] = new unsigned char[w];
        if(buffer[j] == NULL) return 0;// return if not allocated
    }
    return buffer;
}

void DeAllocate2DArray(unsigned char** buffer, int h)
{
    // After complete usage, delete the memory dynamically allocated
    for(int j=h-1; j>= 0; j--)
        delete[] buffer[j]; //delete rows
    delete[] buffer; //delete the pointer to pointer
}



using namespace std;

int main()
{
    ifstream image;
    image.open("image.bmp",std::ios_base::binary);

    if (image.is_open())
    {
        cout<< "function success\n";
    }
    else
    {
        cout<< "unable to open file";
    }


    const int width = 152;
    const int height = 150;

    unsigned char m_cHeaderData[1078];
    unsigned char** m_cImageData = new unsigned char* [height];

    for( int i = 0; i <height; i++)
    {
        m_cImageData[i] = new unsigned char [width];
    }

    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), 1078); 
    //bitmap bits start at offset 1078

    for(int i = 0; i <height; i++)
    {
       m_pInFile->read(reinterpret_cast<char*>(m_cImageData[i]), width);
    }

    m_pInFile->close();


    // Declare a pointer of the type you want.
    // This will point to the 1D array
    unsigned char* array_1D;

    // Now allocate memory for array_1D
    array_1D = new unsigned char[height*width];
    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 * j;
        for(int i=0; i<width; 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(arrayR_2D, width, height);
    arrayG_2D = Allocate2DArray(arrayG_2D, width, height);
    arrayB_2D = Allocate2DArray(arrayB_2D, 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
    int offsetx = 0;
    int counter = 0;
    int bytesPerPixel = 1;

    for(int j=0; j<height; j++)  // traverse height (or rows)
    {
        offset = width * j;
        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];
        }
        counter = 0;
    }


    // After complete usage, delete the memory dynamically allocated
    DeAllocate2DArray(arrayR_2D, height);
    DeAllocate2DArray(arrayG_2D, height);
    DeAllocate2DArray(arrayB_2D, height);

    // After complete usage, delete the memory dynamically allocated
    delete[] array_1D; //delete the pointer to pointer

    //deallocate memory:
    delete m_pInFile;
    delete m_pOutFile;
    for(int i = 0; i <height; i++)
    {
        delete[] m_cImageData[i];
    }
    delete[] m_cImageData;


    system("pause");

    return 0;
}
Posted

1 solution

The error is here:
C++
//deallocate memory:
delete m_pInFile;
delete m_pOutFile;

m_pInFile and m_pInFile are streams and not memory pointers.

[EDIT]
The correct answer should be:
These objects have not been allocated on the heap using new but are located on the stack and can't be therefore destroyed using delete.
 
Share this answer
 
v2
Comments
binaryoffset 9-Oct-15 7:49am    
Thank you Jochen. I have taken that on board.
However, the program still crashes.

I believe the errors lies within the loop containing:

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];
Jochen Arndt 9-Oct-15 7:59am    
The loop assigning the RGB values looks wrong but I don't see an access violation at the moment.

The arrays are allocated as height * width. But you are using count as width index which is only running up to three.

Getting the value from the 1d array would fail if you would use a non-zero offsetx value.

Don't forget that your bitmap has only 256 colours so that each pixel uses 1 byte. The correct RGB decoding must use the colour table (behind the headers) to lookup the 32-bit (24-bit plus alpha) colour values.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900