 |
|
 |
Hi there! First of all thx for that great function. I just needed something like that, searched here on my favourite place for codes and found your cool function ASAP! I have re-written it a bit so the cleanup-procedures should be better (i.e. you return NULL if you fail to create a compatible DC but you don't release the DC) Now it looks like that: HICON CreateGrayscaleIcon(HICON hIcon) { ICONINFO csII; if (!::GetIconInfo(hIcon, &csII)) return NULL; HICON hGrayIcon = NULL; HDC hMainDC = ::GetDC(NULL); if(hMainDC != NULL) { HDC hMemDC1 = ::CreateCompatibleDC(hMainDC); if(hMemDC1 != NULL) { HDC hMemDC2 = ::CreateCompatibleDC(hMainDC); if(hMemDC2 != NULL) { BITMAP bmp; if (::GetObject(csII.hbmColor, sizeof(BITMAP), &bmp)) { DWORD dwWidth = csII.xHotspot*2; DWORD dwHeight = csII.yHotspot*2; ICONINFO csGrayII; csGrayII.hbmColor = ::CreateBitmap(dwWidth, dwHeight, bmp.bmPlanes, bmp.bmBitsPixel, NULL); if (csGrayII.hbmColor) { HBITMAP hOldBmp1 = (HBITMAP)::SelectObject(hMemDC1, csII.hbmColor); HBITMAP hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, csGrayII.hbmColor); //fill with black - needed for strange GFX cards ::BitBlt(hMemDC2, 0, 0, dwWidth, dwHeight, hMemDC1, 0, 0, SRCCOPY); DWORD dwLoopY = 0, dwLoopX = 0; COLORREF crPixel = 0; BYTE byNewPixel = 0; for (dwLoopY = 0; dwLoopY < dwHeight; dwLoopY++) { for (dwLoopX = 0; dwLoopX < dwWidth; dwLoopX++) { crPixel = ::GetPixel(hMemDC1, dwLoopX, dwLoopY); byNewPixel = (BYTE)((GetRValue(crPixel) * 0.299) + (GetGValue(crPixel) * 0.587) + (GetBValue(crPixel) * 0.114)); if (crPixel) ::SetPixel(hMemDC2, dwLoopX, dwLoopY, RGB(byNewPixel, byNewPixel, byNewPixel)); } // for } // for ::SelectObject(hMemDC1, hOldBmp1); ::SelectObject(hMemDC2, hOldBmp2); csGrayII.hbmMask = csII.hbmMask; csGrayII.fIcon = TRUE; hGrayIcon = ::CreateIconIndirect(&csGrayII); } // if ::DeleteObject(csGrayII.hbmColor); //::DeleteObject(csGrayII.hbmMask); } // if ::GetObject(...) } // if ::CreateCompatibleDC(...) ::DeleteDC(hMemDC2); } // if ::CreateCompatibleDC(...) ::DeleteDC(hMemDC1); } // if ::GetDC(...) //::DeleteObject(csII.hbmColor); //::DeleteObject(csII.hbmMask); ::ReleaseDC(NULL, hMainDC); return hGrayIcon; } // End of CreateGrayscaleIcon
Again, thx for your work, GreetZ, WiZaRd
|
|
|
|
 |
|
 |
fail to get grayscale icon with true color icon(32Bits)
Sample code:
HICON hIcon=(HICON)(::LoadImage(NULL,szTemp,IMAGE_ICON,iSize,iSize,LR_LOADFROMFILE));
HICON hGrayIcon=::CreateGrayscaleIcon(hIcon);
hGrayIcon is black icon now!
|
|
|
|
 |
|
 |
this is a usefull function, i just wanted to know
where did you get the "magical numbers" 0.299,0.587,0.114 ??
|
|
|
|
 |
|
 |
Well, honestly I don't remember!
I think I've searched on google for a similar alghorithm...
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
The code assumes that bitmaps created by CreateBitmap contain only black pixels. That's true on my system, but CreateBitmap does not ensure that this is always the case. If you use a different graphic card or a different driver, it may contain random pixels. Look at this screenshot: http://www.thescarms.com/vbasic/ClearBitmap.asp
To fix this, reactivate the commented out BitBlt.
(You may also remove the "if (crPixel)" before SetPixel, but that will be much slower.)
|
|
|
|
 |
|
 |
Iy's just fit me. thanks a lot.
|
|
|
|
 |
|
 |
hay doud
h r u
this is very nice article and help me to understand the grayscale icon creation
dear i have a problem and i hope u will help me and advise me to solve the problem
my problem is i m creating a visiual editor for displaying a business model now what i m doing i m creating window by using CWnd class and sending messages By SENDMessage function in which i pass SS_BITMAP for bitmaps to dispaly then i store these windows in a Array collection Class
and for tracking i use CRectTracker
now the problem is i want to give each bitmap a name or caption under it at run time by double clicking it probelm is how i get the rigth propety box for selected bitmap and how i can rename or attach text to bitmap runtime
i hope you will help me out meet my deadlines
God is great
Jawad
Analyst Programer
Elite STC
jawadayubbaig@hotmail.com
|
|
|
|
 |
|
|
 |
|
 |
Does anybody know the algirthm for changing from a color to a grayscale bitmap in gradule steps, similar to when you close XP?
Normski. - Professional Windows Programmer
|
|
|
|
 |
|
 |
Yes, it's called fade-in (or fade-out) and it is used in most intros (for those who now what is the demo-scene ). You should check on some demo-scene related site to find such algorithm (much probably written in assembler), there is www.hornet.org if I remember right.
Cheers,
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
for n to maxstep do for each pixel of the image do r' = r_orig + (target_r - r_orig) * n / maxstep g' = g_orig + (target_g - g_orig) * n / maxstep b' = b_orig + (target_b - b_orig) * n / maxstep end for end for Of course, this is the principle (the best optimisation you can do should be to precompute a LUT before running through the image and use this lut instead of a mul and a div by pixel) Yours, Emmanuel Deloget i-magus S.A.
|
|
|
|
 |
|
 |
This is a handle little function; two suggestions might be to use CreateCompatibleBitmap() instead of CreateBitmap(), and to not bother with the BitBlt() call since you're already looping pixel-by-pixel and could just as well retrieve the source pixel from the original bitmap.
--------
And we die young.
Faster we run. Alice in Chains, We Die Young
|
|
|
|
 |
|
 |
I agree on avoiding the BitBlt. This would increase the performances of the function. I'm not sure on using CreateCompatibleBitmap() because this creates a bitmap compatible to a given DC (if I remember right), but *theorically* you could use this function to convert an icon *not* compatible with your window DC. What do you think about this?
Cheers,
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
Why, are you focusing only m_hWnd ?
To be honest, it's my fault I didn't tested the function in a real Win32 application, but only assumed it should run only looking at the source code.
BTW, there are no posts commenting the whole function
Is it usefull, or not?
Is it optimized, or not?
Can it be enhanced?
Cheers,
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
Instead of:
hMainDC = ::GetDC(m_hWnd);
hMemDC1 = ::CreateCompatibleDC(hMainDC);
hMemDC2 = ::CreateCompatibleDC(hMainDC);
if (hMainDC == NULL || hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
you could do:
hMainDC = ::GetDC(m_hWnd);
if (hMainDC == NULL) return NULL;
hMemDC1 = ::CreateCompatibleDC(hMainDC);
hMemDC2 = ::CreateCompatibleDC(hMainDC);
if (hMemDC1 == NULL || hMemDC2 == NULL) return NULL;
Since your concern seems to be not failure to obtain hMainDC, it would be more efficient to bail out as soon as you know it failed instead of waiting until after you try to create the two compatible DCs using a null value.
Ed
|
|
|
|
 |
|
 |
I think that the probabilities that ::GetDC() fails are very, very low....
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
Also, just my personal preference, but you are calculating csII.xHotspot*2 in two different places. I use the rule of two: If I need a calculated value in two or more places in code, I assign the value to a variable and then use the variable wherever needed. Ed
|
|
|
|
 |
|
 |
Yes, I agree with you.
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
When I saw your code, I decide immediately to integrate it in my soft because it is really usefull. And it works !
Thanks a lot.
|
|
|
|
 |
|
 |
You're welcome, thank you too!
SoftechSoftware
Davide Calabro'
davide_calabro@yahoo.com
http://www.softechsoftware.it
|
|
|
|
 |
|
 |
You can replace m_hWnd by ::GetDesktopWindow()
|
|
|
|
 |
|
 |
I think you shouldn't use ::GetDesktopWindow - HWND should be passed as argument.
|
|
|
|
 |
|
 |
Sorry - I was wrong - it can be ::GetDesktopWindow
|
|
|
|
 |
|
 |
Robert W. wrote:
Sorry - I was wrong - it can be ::GetDesktopWindow
You are taking about GetDC(m_hWnd)?
If so, you could simply pass NULL. The documentation to GetDC() says:
hWnd Handle to the window whose DC is to be retrieved. If this value is NULL, GetDC retrieves the DC for the entire screen.
Max
"You can always improve your chances of writing
bug-free code by writing code that doesn't do anything"
Rob Macdonald, Serious ADO
|
|
|
|
 |