Click to See Complete Forum and Search --> : help:How to Implement Shrinking a mem HBITMAP size??


Polytech
January 5th, 2007, 09:39 AM
Hello,everyone.I want to shrink a bitmap in memory.but it was not working as the code shown below,can somebody help me to find out the reason?Thanks indeed!

HBITMAP hBitmap = NULL;
if(OpenClipboard())
{
hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if(hBitmap)
{
CDC* pdc = GetDC();
CBitmap* pCBmp = new CBitmap;
pCBmp->Attach(hBitmap);
BITMAP bm;
pCBmp->GetBitmap(&bm);
CDC dcCompatible;
dcCompatible.CreateCompatibleDC(pdc);
dcCompatible.SelectObject(pCBmp);
hdcScaled = CreateCompatibleDC(pdc->GetSafeHdc());
StretchBlt(hdcScaled,
0, 0,
bm.bmWidth *0.1, bm.bmHeight * 0.2,
dcCompatible.GetSafeHdc(),
0, 0,
bm.bmWidth, bm.bmHeight,
SRCCOPY);

hBitmapNew = CreateCompatibleBitmap(hdcScaled, bm.bmWidth *0.1, bm.bmHeight * 0.2);
EmptyClipboard();
HANDLE hTemp = SetClipboardData(CF_BITMAP, hBitmapNew);

CloseClipboard();

}

}

CloseClipboard();

Zaccheus
January 6th, 2007, 10:50 AM
hBitmapNew = CreateCompatibleBitmap(hdcScaled, bm.bmWidth *0.1, bm.bmHeight * 0.2);
EmptyClipboard();
HANDLE hTemp = SetClipboardData(CF_BITMAP, hBitmapNew);
CloseClipboard();
It looks like you are creating a blank bitmap and putting it onto the clipboard. You have to blit the scaled bitmap onto hBitmapNew before calling SetClipboardData.

miteshpandey
January 6th, 2007, 11:24 AM
If Zaccheus's post is not clear; first you have to create the compatible bitmap. Then select this bitmap in the mem dc and StretchBlt using the created mem dc as the destination. Now the compatible bitmap that you created will contain the scaled image.

Polytech
January 6th, 2007, 10:14 PM
If Zaccheus's post is not clear; first you have to create the compatible bitmap. Then select this bitmap in the mem dc and StretchBlt using the created mem dc as the destination. Now the compatible bitmap that you created will contain the scaled image.



I did as you told me,but the image copied in the memory been to gray image,not colorful. I don't know why.
and I try to use another API CopyImage () ,it 's easy to use,but the result image distort very much--I printScreen,and let the size reduce to half,and then I can't distinguish the text printed in the screen!!

miteshpandey
January 7th, 2007, 03:28 AM
This might be your problem. When creating the compatible bitmap don't pass the mem dc as the parameter but use the dc got by calling GetDC();

Polytech
January 8th, 2007, 01:42 AM
This might be your problem. When creating the compatible bitmap don't pass the mem dc as the parameter but use the dc got by calling GetDC();

so,How can I modify the code and let it work correctly?can anyone show me the working code?

miteshpandey
January 8th, 2007, 03:45 AM
Here is the code: Haven't tired it but should work


.............................
.............................
hdcScaled = CreateCompatibleDC(pdc->GetSafeHdc());

hBitmapNew = CreateCompatibleBitmap(pdc) //note the use of "pdc"

hdcScaled.SelectObject(hBitmapNew);

StretchBlt(hdcScaled,
0, 0,
bm.bmWidth *0.1, bm.bmHeight * 0.2,
dcCompatible.GetSafeHdc(),
0, 0,
bm.bmWidth, bm.bmHeight,
SRCCOPY);



HANDLE hTemp = SetClipboardData(CF_BITMAP, hBitmapNew);

CloseClipboard();
.................
.................


I hope other things are correct like passing the correct parameters to the StretchBlt function.

Polytech
January 9th, 2007, 03:20 AM
It can't work,because CDC is different from HDC,and CBitmap is different from HBITMAP,so the code can't work.can you try to run it,and let it working.I use another API CopyImage to do such thing,but the result image is been distort very much so that the text printed on screen can be seen clearly



Here is the code: Haven't tired it but should work


.............................
.............................
hdcScaled = CreateCompatibleDC(pdc->GetSafeHdc());

hBitmapNew = CreateCompatibleBitmap(pdc) //note the use of "pdc"

hdcScaled.SelectObject(hBitmapNew);

StretchBlt(hdcScaled,
0, 0,
bm.bmWidth *0.1, bm.bmHeight * 0.2,
dcCompatible.GetSafeHdc(),
0, 0,
bm.bmWidth, bm.bmHeight,
SRCCOPY);



HANDLE hTemp = SetClipboardData(CF_BITMAP, hBitmapNew);

CloseClipboard();
.................
.................


I hope other things are correct like passing the correct parameters to the StretchBlt function.

miteshpandey
January 9th, 2007, 09:16 AM
Oops sorry, I am used to using MFC function hence the mix up.

However you should have guessed what's wrong.

So simply replace


hBitmapNew = CreateCompatibleBitmap(pdc) ;


with


hBitmapNew = CreateCompatibleBitmap(pdc->GetSafeHdc()) ;

Polytech
January 10th, 2007, 06:55 AM
Oops sorry, I am used to using MFC function hence the mix up.

However you should have guessed what's wrong.

So simply replace


hBitmapNew = CreateCompatibleBitmap(pdc) ;


with


hBitmapNew = CreateCompatibleBitmap(pdc->GetSafeHdc()) ;



I have changed the code and it is working,But,the result bitmap is only Black and White two tone,so How can I let the picture been to colorful?

miteshpandey
January 10th, 2007, 08:00 AM
Could you plz post your changed code once again. I mean the whole thing.

Polytech
January 11th, 2007, 04:50 AM
Could you plz post your changed code once again. I mean the whole thing.

the two tone of bitmap problem has been resolved,but another problem occured,I make this function to respond the hotkey in my program,but when I first time press the hotkey,the function works, and reduce the bitmap in clipboard to half size,and then I press the hot key again, the size of the bitmap in clipboard hasn't changed!!--but the stranger is that:when I make break point in VC IDE to trace the code,I see the bitmap size changed(I watch it by bm.bmwidth,bm.bmheight in my code shown above) -- I don't know what 's the bug in my function......


void CReduceMemBmpSizeDlg::OnOK()
{
// TODO: Add extra validation here
RegisterHotKey(GetSafeHwnd(),WM_SNAPHOTKEY,NULL, VK_F3);
OnHotKey(1125,7471104);
}

LRESULT CReduceMemBmpSizeDlg::OnHotKey(WPARAM wParam,LPARAM lParam)
{
HBITMAP hBitmap = NULL;
if(OpenClipboard())
{
hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if(hBitmap)
{
BITMAP bm;
GetObject(hBitmap, sizeof(BITMAP), &bm);
//trace code in here,bm changed
CDC* pdc = GetDC();
CBitmap cbmpSource;
cbmpSource.Attach(hBitmap);
CDC dcSource;
dcSource.CreateCompatibleDC(pdc);
dcSource.SelectObject(cbmpSource);
CDC dcNewDC;
dcNewDC.CreateCompatibleDC(pdc);
HBITMAP hBitmapNew = NULL;
hBitmapNew = CreateCompatibleBitmap(pdc->m_hDC,bm.bmWidth/2,bm.bmHeight/2);
//the return value of hBitmapNew return non zero,I think means successful
bm.bmWidth = 0; //here for test
GetObject(hBitmapNew, sizeof(HBITMAP),&bm); //this sentence has not work...why?
CBitmap cbmpNew;
cbmpNew.Attach(hBitmapNew);
dcNewDC.SelectObject(cbmpNew);
CBitmap* pBitmapOld;
pBitmapOld = dcNewDC.SelectObject(&cbmpNew);
dcNewDC.SetStretchBltMode(COLORONCOLOR);
dcNewDC.StretchBlt(0,0,bm.bmWidth/2,bm.bmHeight/2,&dcSource,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
dcNewDC.SelectObject(pBitmapOld);
dcNewDC.Detach();
HANDLE hSetCB_Result = NULL;
cbmpNew.Detach();
bm.bmWidth = 0; //here for test
GetObject(hBitmapNew, sizeof(HBITMAP),&bm); //this sentence has not work...why?
hSetCB_Result = SetClipboardData(CF_BITMAP, hBitmapNew);
if(!hSetCB_Result)
{
MessageBox("Set ClipboardData error!");
}
// CloseHandle(hSetCB_Result);
DeleteObject(hBitmapNew);
dcSource.Detach();
dcSource.DeleteDC();
dcNewDC.DeleteDC();
ReleaseDC(pdc);
}
CloseClipboard();
}
return 0;
}

miteshpandey
January 11th, 2007, 09:33 AM
I have modified the code highlighted in red and blue. I think the problem appears becuase you are using the same variable "bm" twice. Replace one with say "bm2".


LRESULT CReduceMemBmpSizeDlg::OnHotKey(WPARAM wParam,LPARAM lParam)
{
HBITMAP hBitmap = NULL;
if(OpenClipboard())
{
hBitmap = (HBITMAP)GetClipboardData(CF_BITMAP);
if(hBitmap)
{
BITMAP bm;
GetObject(hBitmap, sizeof(BITMAP), &bm);
//trace code in here,bm changed
CDC* pdc = GetDC();
CBitmap cbmpSource;
cbmpSource.Attach(hBitmap);
CDC dcSource;
dcSource.CreateCompatibleDC(pdc);
dcSource.SelectObject(cbmpSource);
CDC dcNewDC;
dcNewDC.CreateCompatibleDC(pdc);
HBITMAP hBitmapNew = NULL;
hBitmapNew = CreateCompatibleBitmap(pdc->m_hDC,bm.bmWidth/2,bm.bmHeight/2);
//the return value of hBitmapNew return non zero,I think means successful
BITMAP bm2;
GetObject(hBitmapNew, sizeof(HBITMAP),&bm2);
CBitmap cbmpNew;
cbmpNew.Attach(hBitmapNew);
dcNewDC.SelectObject(cbmpNew);
CBitmap* pBitmapOld;
pBitmapOld = dcNewDC.SelectObject(&cbmpNew);
dcNewDC.SetStretchBltMode(COLORONCOLOR);
dcNewDC.StretchBlt(0,0,bm2.bmWidth,bm2.bmHeight,&dcSource,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
dcNewDC.SelectObject(pBitmapOld);
dcNewDC.Detach();
HANDLE hSetCB_Result = NULL;
cbmpNew.Detach();
bm.bmWidth = 0; //here for test
GetObject(hBitmapNew, sizeof(HBITMAP),&bm); //this sentence has not work...why?
hSetCB_Result = SetClipboardData(CF_BITMAP, hBitmapNew);
if(!hSetCB_Result)
{
MessageBox("Set ClipboardData error!");
}
// CloseHandle(hSetCB_Result);
DeleteObject(hBitmapNew);
dcSource.Detach();
dcSource.DeleteDC();
dcNewDC.DeleteDC();
ReleaseDC(pdc);
}
CloseClipboard();
}
return 0;
}


If you want to use only one variable "bm". Then I think you can entirely remove the following line:


GetObject(hBitmapNew, sizeof(HBITMAP),&bm); //this sentence has not


with your original StretchBlt code intact:


dcNewDC.StretchBlt(0,0,bm.bmWidth/2,bm.bmHeight/2,&dcSource,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);


Hope it works:

Polytech
January 11th, 2007, 09:31 PM
If you want to use only one variable "bm". Then I think you can entirely remove the following line:


GetObject(hBitmapNew, sizeof(HBITMAP),&bm); //this sentence has not


with your original StretchBlt code intact:


dcNewDC.StretchBlt(0,0,bm.bmWidth/2,bm.bmHeight/2,&dcSource,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);


Hope it works:

I have made it as you said,but not work, I think to definite a new variable not not is not matter, if the API GetObject do something behind for the variable bm,It must have some API to reverse it,such as release resource.

p.s. I have paste almost entirely the code in my program.the other code is generated by VC IDE

miteshpandey
January 12th, 2007, 03:19 AM
Please correct the code that I have suggested:

I think now I know the reason why your code doesn't work.

1. You are registering your Hot Key on OnOk(). But after OnOk() your dialog will be dismissed i.e. there will be a no window for your dialog.

2. But now in your OnHotKey function you are calling all functions dependent on the window like GetDC. Your OnHotKey function will work the way you want only if your dialog has a valid Windows window. Otherwise it won't work.

3. So it is advisable to test the return values from functions.

Polytech
January 12th, 2007, 09:15 PM
Please correct the code that I have suggested:

I think now I know the reason why your code doesn't work.

1. You are registering your Hot Key on OnOk(). But after OnOk() your dialog will be dismissed i.e. there will be a no window for your dialog.

2. But now in your OnHotKey function you are calling all functions dependent on the window like GetDC. Your OnHotKey function will work the way you want only if your dialog has a valid Windows window. Otherwise it won't work.

3. So it is advisable to test the return values from functions.

1.what's the meaning of " dialog will be dismissed" ?I haven't called CDialog::OnOK() in my program;
2.I make a break point to trace my code:
CDC* pdc = NULL;
pdc = GetDC();
and found that Even the window is in background,when I press the hotkey,I saw the code shown above,pdc is not NULL,in other word,the GetDC() api is called successful........
how about your opinion?

miteshpandey
January 13th, 2007, 01:40 AM
I have suggested the previous thing based upon your following code:


void CReduceMemBmpSizeDlg::OnOK()
{
// TODO: Add extra validation here
RegisterHotKey(GetSafeHwnd(),WM_SNAPHOTKEY,NULL, VK_F3);
OnHotKey(1125,7471104);
}


The default behaviour of OnOK() is that the dialog window is closed (dismissed) probably if you have called CDialog::OnOK();

The next time you press your hot key there will be no dialog window present.

In fact the next time you press your hotkey there is no modal dialog, no OnOK button, so your OnHotKey function is never called.

So I don't understand your actual situation. If you can explain it would be better.

miteshpandey
January 13th, 2007, 01:52 AM
It would be a lot better if you can post your project here in zipped form.

Don't include "Release" and "Debug" folders. Also remove the unnecessary files like .ncb and .opt

Polytech
January 30th, 2007, 02:38 AM
Thank you very much for your kind help

Polytech
January 30th, 2007, 02:51 AM
It would be a lot better if you can post your project here in zipped form.

Don't include "Release" and "Debug" folders. Also remove the unnecessary files like .ncb and .opt

--------------------------------------------------------------------------------

Thank you very much for your kind help!! I have let it work,if there is still some problems I would ask for you.
thanks again