Discussion:
I need to adjust the size of a bitmap in a buffer - code included
(too old to reply)
soxmax
2006-08-04 20:37:21 UTC
Permalink
I am creating some image analysis software. My software is developed
specifically for bitmap images size 1280X1024 pixels. Now my boss wants
to be able to load images of any size into the software. I am looking
for a function that I can use when I load my image buffer that will
adjust the incoming image to the size I need (specifically 1280X1024).
I am using MS Visual Studio and MFC libraries. I don't know if I am
posting this in the correct place or not. I also posted to the C++
post. I'm a VHDL and Verilog guy and we don't have nearly the number of
newsgroups as you programmer guys (and gals). Please point me to the
correct newsgroup if this post doesn't belong here. Here is my code:

loadBuffer(int whichBuffer, TCHAR* importFileName)
{


BITMAPINFO bmp;
HANDLE hFile;
DWORD numBytesWrite;
DWORD pictBytes;
BITMAPFILEHEADER bmfInfo;


if( whichBuffer < 0 || whichBuffer >= numImageBuffers )
{
return false;
}


// Create the .BMP file.
hFile = CreateFileA((LPSTR)importFileName, GENERIC_READ,
(DWORD) 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);


if( hFile == INVALID_HANDLE_VALUE )
return false;


pictBytes=bitmapHeight*bytesPerPixel*bitmapWidth;//1024X3X1280


ReadFile(hFile, &bmfInfo, sizeof(BITMAPFILEHEADER),
&numBytesWrite, NULL);
if( sizeof(BITMAPFILEHEADER) == numBytesWrite )
{
ReadFile(hFile, &bmp.bmiHeader, sizeof(BITMAPINFOHEADER),
&numBytesWrite, NULL);
if( sizeof(BITMAPINFOHEADER) == numBytesWrite )
{


/* Here is where I need to stretch the image (I think) */
/* imageBuffer[whichBuffer] is 1024 X 3 X 1280 bytes */
/* I need to stretch or compress the image (importFileName) */
/* to fit in the imageBuffer[whichBuffer] */


ReadFile(hFile, imageBuffers[whichBuffer], pictBytes,
&numBytesWrite, NULL);
if( pictBytes == numBytesWrite )
{
CloseHandle(hFile);
return true;
}
}
}
CloseHandle(hFile);
return false;



}


Best Regards,
Derek
Bertel Brander
2006-08-04 23:25:08 UTC
Permalink
Post by soxmax
I am creating some image analysis software. My software is developed
specifically for bitmap images size 1280X1024 pixels. Now my boss wants
to be able to load images of any size into the software. I am looking
for a function that I can use when I load my image buffer that will
adjust the incoming image to the size I need (specifically 1280X1024).
It should be fairly easy to do. But I have a couple of questioins first.

What type stretch or compress do you want? Is a simple mean value
good enough, or...

Is the .bmp you read always 24 bits?
Post by soxmax
I am using MS Visual Studio and MFC libraries.
I don't think that matters here.

I don't know if I am
Post by soxmax
posting this in the correct place or not. I also posted to the C++
post. I'm a VHDL and Verilog guy and we don't have nearly the number of
newsgroups as you programmer guys (and gals). Please point me to the
correct newsgroup if this post doesn't belong here.
I think the question is fine here.
--
Absolutely not the best homepage on the net:
http://home20.inet.tele.dk/midgaard
But it's mine - Bertel
soxmax
2006-08-04 23:32:54 UTC
Permalink
Post by Bertel Brander
What type stretch or compress do you want? Is a simple mean value
good enough, or...
I am using a function called "StretchDIBits" for displaying the bitmap
after the analysis. I would like to use somthing like that. I guess
what I want is somthing exactly like that but I don't want to have to
display the bitmap in order to stretch/compress it. The flow would be
somthing like this: load image --> stretch/compress image to math
software constraints --> analyze image --> display image using
StretchDIBits.
Post by Bertel Brander
Is the .bmp you read always 24 bits?
Yes.

Thanks for your help,
Derek
Bertel Brander
2006-08-04 23:52:10 UTC
Permalink
Post by soxmax
Post by Bertel Brander
What type stretch or compress do you want? Is a simple mean value
good enough, or...
I am using a function called "StretchDIBits" for displaying the bitmap
after the analysis. I would like to use somthing like that. I guess
what I want is somthing exactly like that but I don't want to have to
display the bitmap in order to stretch/compress it. The flow would be
somthing like this: load image --> stretch/compress image to math
software constraints --> analyze image --> display image using
StretchDIBits.
I think it should be possible to load the image, put it into
a memory DC, use StretchBlt to resize and then get the bits
back, without putting it onto the screen.

A memory DC is create with CreateCompatibleBitmap
Use GetDIBits to get the bits back.

I think I can create an example...
--
Absolutely not the best homepage on the net:
http://home20.inet.tele.dk/midgaard
But it's mine - Bertel
Bertel Brander
2006-08-05 00:19:46 UTC
Permalink
Post by Bertel Brander
I think I can create an example...
Here we go:

#include <windows.h>
#include <iostream>
#include <fstream>

BITMAPINFOHEADER WriteHeader(std::ostream &os, int aWidth, int aHeight,
WORD aBitPixel)
{
BITMAPFILEHEADER BitmapFileHeader;
BITMAPINFOHEADER BitmapInfoHeader;
unsigned int WordsPerLine = (aWidth*aBitPixel + 31)/32;
BitmapFileHeader.bfType = (('M' << 8) | 'B');
BitmapFileHeader.bfSize = sizeof(BitmapFileHeader) +
sizeof(BitmapInfoHeader) + 4*WordsPerLine*aHeight;
BitmapFileHeader.bfReserved1 = 0;
BitmapFileHeader.bfReserved2 = 0;
BitmapFileHeader.bfOffBits = 0x36 + 8;

BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfoHeader.biWidth = aWidth;
BitmapInfoHeader.biHeight = aHeight;
BitmapInfoHeader.biPlanes = 1;
BitmapInfoHeader.biBitCount = aBitPixel;
BitmapInfoHeader.biCompression = BI_RGB;
BitmapInfoHeader.biSizeImage = 0;
BitmapInfoHeader.biXPelsPerMeter = 0;
BitmapInfoHeader.biYPelsPerMeter = 0;
BitmapInfoHeader.biClrUsed = 0;
BitmapInfoHeader.biClrImportant = 0;
os.write((char *)&BitmapFileHeader, sizeof(BitmapFileHeader));
os.write((char *)&BitmapInfoHeader, sizeof(BitmapInfoHeader));
return BitmapInfoHeader;
}


HBITMAP LoadBMP(const char *aFileName, UINT& aWidth, UINT& aHeight)
{
HBITMAP BitMap = (HBITMAP )LoadImage(0, aFileName, IMAGE_BITMAP, 0,
0, LR_LOADFROMFILE);
if(!BitMap)
{
std::cerr << "Failed to load image: " << aFileName << std::endl;
}
else
{
BITMAP BitmapInfo;
GetObject(BitMap, sizeof(BITMAP), &BitmapInfo);
aWidth = BitmapInfo.bmWidth;
aHeight = BitmapInfo.bmHeight;
}
return BitMap;
}

BOOL ResizeImage(const char* aInFileName, const char* aOutFileName)
{
UINT W, H;
HBITMAP BitMap1;
if((BitMap1 = LoadBMP(aInFileName, W, H)) == 0)
{
return FALSE;
}
HDC MemDc1 = CreateCompatibleDC(GetDC(0));
HDC MemDc2 = CreateCompatibleDC(GetDC(0));
HBITMAP BitMap2 = CreateCompatibleBitmap(GetDC(0), 1280, 1024);
SelectObject(MemDc1, BitMap1);
SelectObject(MemDc2, BitMap2);
StretchBlt(MemDc2, 0, 0, 1280, 1024, MemDc1, 0, 0, W, H, SRCCOPY);

std::ofstream File(aOutFileName, std::ios::binary);
if(!File)
{
std::cerr << "Failed to open: " << aOutFileName << std::endl;
return 0;
}
BITMAP Bm;
GetObject(BitMap2, sizeof(Bm), &Bm);
BITMAPINFOHEADER Header = WriteHeader(File, 1280, 1024, Bm.bmBitsPixel);
char *Buffer = new char [1280*1024*Bm.bmBitsPixel/8];
GetDIBits(MemDc2, BitMap2, 0, 1024, Buffer, (BITMAPINFO *)&Header,
DIB_RGB_COLORS);
File.write(Buffer, 1280*1024*Bm.bmBitsPixel/8);

delete [] Buffer;
DeleteDC(MemDc1);
DeleteDC(MemDc2);
DeleteObject(BitMap1);
DeleteObject(BitMap2);

return TRUE;
}

int main(int argc, char *argv[])
{
if(argc != 3)
{
std::cerr << "Usage: " << argv[0] << " infile outfile" << std::endl;
return 1;
}
if(!ResizeImage(argv[1], argv[2]))
{
std::cerr << "Failed to resize" << std::endl;
return 2;
}
std::cout << "Success!" << std::endl;
}

The program reads a .bmp file, resize it to 1280*1024
and writes the resized image to another file.

Buffer in ResizeImage(...) contains the data for the
resized image.
--
Absolutely not the best homepage on the net:
http://home20.inet.tele.dk/midgaard
But it's mine - Bertel
Bertel Brander
2006-08-05 00:37:07 UTC
Permalink
Post by Bertel Brander
Post by Bertel Brander
I think I can create an example...
[Snip]
Post by Bertel Brander
SelectObject(MemDc2, BitMap2);
You might get a better result if you add the call:
SetStretchBltMode(MemDc2, HALFTONE);
Post by Bertel Brander
StretchBlt(MemDc2, 0, 0, 1280, 1024, MemDc1, 0, 0, W, H, SRCCOPY);
--
Absolutely not the best homepage on the net:
http://home20.inet.tele.dk/midgaard
But it's mine - Bertel
soxmax
2006-08-07 15:32:04 UTC
Permalink
Thanks for your help Bertel.

I'll give this a shot and let you know how it works.

Adieu,
Derek

soxmax
2006-08-04 23:55:53 UTC
Permalink
Here is my updated Code:


loadBuffer(int whichBuffer, TCHAR* importFileName)
{


BITMAPINFO bmp;
HANDLE hFile;
DWORD numBytesWrite;
DWORD pictBytes;
BITMAPFILEHEADER bmfInfo;
int tempWidth;
int tempHeight;


if( whichBuffer < 0 || whichBuffer >= numImageBuffers )
{
return false;
}


// Create the .BMP file.
hFile = CreateFileA((LPSTR)importFileName, GENERIC_READ,
(DWORD) 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);


if( hFile == INVALID_HANDLE_VALUE )
return false;


pictBytes=bitmapHeight*bytesPerPixel*bitmapWidth;//1024X3X1280


ReadFile(hFile, &bmfInfo, sizeof(BITMAPFILEHEADER),
&numBytesWrite, NULL);
if( sizeof(BITMAPFILEHEADER) == numBytesWrite )
{
ReadFile(hFile, &bmp.bmiHeader, sizeof(BITMAPINFOHEADER),
&numBytesWrite, NULL);

/******************new code starts here*********************/

tempWidth = bmp.bmiHeader.biWidth;
tempHeight = bmp.bmiHeader.biHeight;

if(tempWidth * tempHeight != analysisSize_pixels)
{
//we need to put the bitmap info in a temporary buffer and
//then stretch or compress it to fit in imageBuf.

BYTE* tempBuf;

pictBytes = height * bytesPerPixel * width;

tempBuf = (BYTE* )LocalAlloc(LPTR, pictBytes*sizeof(BYTE));

ReadFile(hFile, tempBuf, pictBytes, &numBytesWrite, NULL);

/**********************************************************************/
/* I need to figure out how to stretch the bitmap data */
/* in tempBuf and then load it into imageBuffers[whichBuffer] */

/*********************************************************************/


LocalFree(tempBuf);
}

else
{

ReadFile(hFile, imageBuffers[whichBuffer], pictBytes,
&numBytesWrite, NULL);

if( pictBytes == numBytesWrite )
{
CloseHandle(hFile);
return true;
}
}
}

CloseHandle(hFile);
return false;



}
Loading...