There's several problem in the code that I can see immediately. The most striking comes from within the innermost for loop:
sum=0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ];
*Image = sum/4;
Here, you have simply added the same value to sum
four times over, and then divided by four. This makes these six lines equivalent to
*Image = PaintBox1->Canvas->Pixels[ i ][ j ];
Clearly, you actually wanted to average each channel. If your RGB image were implemented as a three-dimensional array, this would probably look something like:
sum = 0;
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 0 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 1 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 2 ];
sum += PaintBox1->Canvas->Pixels[ i ][ j ][ 3 ];
*Image = sum/4;
However, from your code example, it looks like your RGB image is actually implemented as a two-dimensional array of (un)signed integers. In that case, the following code should suffice (provided integers are four bytes on your machine):
sum = 0;
unsigned int pixel = PaintBox1->Canvas->Pixels[ i ][ j ];
for(int k = 0; k < 4; ++k)
{
sum += pixel & 0xFF;
pixel >>= 1;
}
*Image = sum/4;
The other major problem I see is that you do not keep a pointer to the beginning of your grayscale array. You initialize it as
Image = new unsigned char[ 160 * 120 * 1 ];
which is good. But then each time through the loop, you've written
Image++;
Rather, you should keep a pointer to the beginning of the array, and have a temporary pointer which acts as an iterator:
// before the for loops
Image = new unsigned char[ 160 * 120 * 1 ];
unsigned char * temp = Image;
// at the end of the inner for loop:
temp++;
So you only move around the temp
pointer, while Image
stays fixed.