Picture resize in borland builder 5

Hey fellow programmers,
This is my first post here so I am sorry for anything that might go wrong at first hand. I am supposed to resize a bitmap picture from any resolution bigger than 480x272 to 480x272 then I am supposed to save this in to a bitmap file again. I wrote a code which pretty much works, it downsizes any picture to 480x272 however the picture itself seems to be corrupted. Colors are all mixed up and has no similarities to the original picture. Below is my code for resize,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
void TForm1::resize(AnsiString fileName, int width, int height, bool scaling)
{
        Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
        pBitmap->LoadFromFile(fileName);
        pBitmap->PixelFormat = pf24bit;
	int image_width = pBitmap->Width;
        int image_height = pBitmap->Height;
        int x= 0, y = 0;

        TRGBTriple data[480*272];
        TRGBTriple* itsRows[272];

        memset( &data, 0, sizeof(data) );

        for( int i=0; i<272; i++ )
               itsRows[i] = &data[i*480];

        if( (width < image_width || height < image_height ) && scaling )
        {
                TRGBTriple *src_row, *dest_row;
	        TRGBTriple *src_pixel, *dest_pixel;

                double width_step = 1;
        	double height_step = 1;

        	if( width < image_width )
	        	width_step = (double)(image_width)/(double)width;

        	if( height < image_height )
	        	height_step = (double)(image_height)/(double)height;

        	for( int i=0; i<height; i++ )
        	{
	        	if( height < image_height )
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[(int)((i*height_step))];
	        	else
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[i];

                        dest_row = itsRows[i];
	        	dest_pixel = dest_row;
                        src_pixel = src_row;
		        for( int j=0; j<width; j++, dest_pixel++ )
		        {
			        if( width < image_width )
				        src_pixel = &src_row[(int)((j*width_step))];
			        else
				        src_pixel = &src_row[j];
                                dest_pixel->rgbtRed = src_pixel->rgbtRed;
                                dest_pixel->rgbtGreen = src_pixel->rgbtGreen;
                                dest_pixel->rgbtBlue = src_pixel->rgbtBlue;
                        }

                }
        }

 SaveBmp("test.bmp", data);
}


and SaveBmp is as follows,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
void TForm1::SaveBmp( char *file, TRGBTriple *trgb)
{
	BmpMagic magic;
	BmpHeader header;
	BmpInfo info;

	memset( &magic, 0, BMP_MAGIC_SIZE);
	memset( &header, 0, BMP_HEADER_SIZE );
	memset( &info, 0, BMP_INFO_SIZE );

        TRGBTriple* itsRows[272];
        for( int i=0; i<272; i++ )
               itsRows[i] = &trgb[i*480];


	FILE *pFile = fopen( file, "w+" );
	if( !pFile )
	{
		printf("GrContext::SaveBmp error open file %s\n", file );
		return;
	}

	magic.magic[0] = 'B';
	magic.magic[1] = 'M';


	int width = 480*3;
	if( width%4 )
		width += 4-width%4;

	int size = width*272;
	unsigned char data[480*3*272];
	int index = 0;

	TRGBTriple *row;
	for( int i=0; i<272; i++ )
	{
		index = (272-i-1)*width;
		row = itsRows[i];
		for( int j=0; j<480; j++, row++ )
		{
			data[index++] = row->rgbtBlue;
			data[index++] = row->rgbtGreen;
			data[index++] = row->rgbtRed;
                                if(i == 200)
                                        i = 200;
		}
	}

	header.size = BMP_MAGIC_SIZE+BMP_HEADER_SIZE+BMP_INFO_SIZE+size;
	header.offset = BMP_MAGIC_SIZE+BMP_HEADER_SIZE+BMP_INFO_SIZE;

	info.size = BMP_INFO_SIZE;
	info.bits_per_pixel = 24;
	info.height = 272;
	info.image_size = size;
	info.width = 480;
	info.xresolution = 480;
	info.yresolution = 272;
	info.planes = 1;

	fwrite( &magic, 1, BMP_MAGIC_SIZE, pFile );
	fwrite( &header, 1, BMP_HEADER_SIZE, pFile );
	fwrite( &info, 1, BMP_INFO_SIZE, pFile );
	int x = fwrite( data, 1, size, pFile );
	fflush( pFile );
	fclose( pFile );
}


So when i call, say resize("test.bmp", 480, 272, true); it should downsize the picture and save it as a bitmap file. However there is a problem with the colors itself. What might be the problem? How can it be solved? I am pretty much clueless right now.

Just to add, I know some people will suggest using already written libraries for this kind of stuff such as OpenCV, however I use a very old compiler, Borland Builder 5 and after 2 days of trying I am pretty much sure OpenCV cannot be used with BCB5.

thanks in advance,
neb
Could you post an example bitmap and the function's result?

EDIT:
I use a very old compiler, Borland Builder 5
I take switching compilers is not an option?
Last edited on
here is an example. Both original picture and resized picture.

http://i.imgur.com/LV2yz.jpg

And sadly no, I am working in a company as an intern and they don't let me use other compilers.
Last edited on
An update! I checked my resize code and it works just fine. It resized the picture to the desired resolution. My mistake is somewhere inside the SaveBmp. Here is the code i used to check the resize just to help you guys out aswell,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

void __fastcall TForm1::Button1Click(TObject *Sender)
{
        resize("lion.bmp", 480, 272, true);
}

void TForm1::resize(AnsiString fileName, int width, int height, bool scaling)
{
        Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
        pBitmap->LoadFromFile(fileName);
        pBitmap->PixelFormat = pf24bit;
	int image_width = pBitmap->Width;
        int image_height = pBitmap->Height;
        int x= 0, y = 0;

        TRGBTriple src_data[480*272];
        TRGBTriple* itsRows[272];

        memset( &src_data, 0, sizeof(src_data) );

        for( int i=0; i<272; i++ )
               itsRows[i] = &src_data[i*480];

        if( (width < image_width || height < image_height ) && scaling )
        {
                TRGBTriple *src_row, *dest_row;
	        TRGBTriple *src_pixel, *dest_pixel;

                double width_step = 1;
        	double height_step = 1;

        	if( width < image_width )
	        	width_step = (double)(image_width)/(double)width;

        	if( height < image_height )
	        	height_step = (double)(image_height)/(double)height;

        	for( int i=0; i<height; i++ )
        	{
	        	if( height < image_height )
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[(int)((i*height_step))];
	        	else
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[i];

                        dest_row = itsRows[i];
	        	dest_pixel = dest_row;
                        src_pixel = src_row;
		        for( int j=0; j<width; j++, dest_pixel++ )
		        {
		     	        if( width < image_width )
		      		        src_pixel = &src_row[(int)((j*width_step))];
			        else
				        src_pixel = &src_row[j];
                                dest_pixel->rgbtRed = src_pixel->rgbtRed;
                                dest_pixel->rgbtGreen = src_pixel->rgbtGreen;
                                dest_pixel->rgbtBlue = src_pixel->rgbtBlue;
                        }

                }
        }

                TRGBTriple *src_row, *dest_row;
	        TRGBTriple *src_pixel, *dest_pixel;
        	for( int i=0; i<height; i++ )
        	{
                src_row = (TRGBTriple*)pBitmap->ScanLine[i];

                        dest_row = itsRows[i];
	        	dest_pixel = dest_row;
                        src_pixel = src_row;
		        for( int j=0; j<width; j++, dest_pixel++ )
		        {
				        src_pixel = &src_row[j];
                                src_pixel->rgbtRed= dest_pixel->rgbtRed;
                                src_pixel->rgbtGreen = dest_pixel->rgbtGreen;
                                src_pixel->rgbtBlue = dest_pixel->rgbtBlue;
                        }

                }
        Canvas->Draw(0,0,pBitmap);


SaveBmp("test.bmp", src_data);
}


So if you open up a VCL form in BCB5 but a button somewhere on the form and just run the program. It puts the original picture on the screen and then puts the resized picture inside the original picture and show it. Thus I think my resize works just as fine. Porblem has to be something about SaveBmp function.
I have solved the problem after 4 hours of work! However this solution is not a general one it is pretty much specific to BCB5. So hopefully when a fellow student like me needs to work on a compiler as old as earth itself he will stumble upon this thread and find his solution. What I did was pretty much simple. I just painted the resized picture on the original picture on a form using canvas. Then I rearranged the size of bitmap object thus it cropped the picture deleting the parts that belong the original picture thus left me with the resized picture inside a TImage. Then I simply saved whatever is inside the TImage (resized image in this case) in to a test file and voila! I have the resized picture. Here is my code,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
void TForm8::resize(AnsiString fileName, int width, int height, bool scaling)
{
        Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
        pBitmap->LoadFromFile(fileName);
        pBitmap->PixelFormat = pf24bit;
	int image_width = pBitmap->Width;
        int image_height = pBitmap->Height;
        int x= 0, y = 0;

        TRGBTriple src_data[480*272];
        TRGBTriple* itsRows[272];

        memset( &src_data, 0, sizeof(src_data) );

        for( int i=0; i<272; i++ )
               itsRows[i] = &src_data[i*480];

        if( (width < image_width || height < image_height ) && scaling )
        {
                TRGBTriple *src_row, *dest_row;
	        TRGBTriple *src_pixel, *dest_pixel;

                double width_step = 1;
        	double height_step = 1;

        	if( width < image_width )
	        	width_step = (double)(image_width)/(double)width;

        	if( height < image_height )
	        	height_step = (double)(image_height)/(double)height;

        	for( int i=0; i<height; i++ )
        	{
	        	if( height < image_height )
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[(int)((i*height_step))];
	        	else
		        	src_row = (TRGBTriple*)pBitmap->ScanLine[i];

                        dest_row = itsRows[i];
	        	dest_pixel = dest_row;
                        src_pixel = src_row;
		        for( int j=0; j<width; j++, dest_pixel++ )
		        {
		     	        if( width < image_width )
		      		        src_pixel = &src_row[(int)((j*width_step))];
			        else
				        src_pixel = &src_row[j];
                                dest_pixel->rgbtRed = src_pixel->rgbtRed;
                                dest_pixel->rgbtGreen = src_pixel->rgbtGreen;
                                dest_pixel->rgbtBlue = src_pixel->rgbtBlue;
                        }

                }
        }

        TRGBTriple *src_row, *dest_row;
        TRGBTriple *src_pixel, *dest_pixel;
        for( int i=0; i<height; i++ )
        {
                src_row = (TRGBTriple*)pBitmap->ScanLine[i];

                dest_row = itsRows[i];
        	dest_pixel = dest_row;
                src_pixel = src_row;
                for( int j=0; j<width; j++, dest_pixel++ )
                {
                        src_pixel = &src_row[j];
                        src_pixel->rgbtRed= dest_pixel->rgbtRed;
                        src_pixel->rgbtGreen = dest_pixel->rgbtGreen;
                        src_pixel->rgbtBlue = dest_pixel->rgbtBlue;
                }

        }
        Canvas->Draw(0,0,pBitmap);
        pBitmap->Height = 272;
        pBitmap->Width = 480;
        pBitmap->SaveToFile("C:\\PICTURES\\"+fileName+".bmp");
}


It was a very tiring coding marathon for past 6 days for me. Hopefully this will help people in future since there are NO image resizing programs, libraries, codes written for compile time process on old compilers. I would still love it if anyone solves whatever is wrong with the SaveBmp method for a general solution.

Neb, out.
Last edited on
I haven't looked at your code, but it would seem your problem was that you were ignoring padding. BMP rows are padded with bytes to the next multiple of 4, so for example a row of 2 pixels in a 24 bbp image actually uses 8 bytes, not 6. If you don't account for padding, your channels get shifted (reds become blues or greens, and so on) and the colors get all screwed up like in that example. Also, each new row adds one or more pixels of error, which causes the overall picture to look slanted like that.
Topic archived. No new replies allowed.