|
There are two formulas i've seen for calculating a grey value from an RGB :
1. byte grey = (R * 0.299) + (G * 0.587) + (B * 0.114);
2. byte grey = (R * 0.2126) + (G * 0.7152) + (B * 0.0722);
The first is what you will generally find documented. It is based on National Television Standard Committee (NTSC) findings from the 50's. It is based on how the human eye perceives light and tuned to how the color TV phosphour (50's) displays RGB colours.
Other sources say these values are no longer representative of current TV/monitor displays and state that the values in 2. should be used.
Regardless, for each pixel :
byte grey = <1 or 2>;
R = grey;
G = grey;
B = grey;
As you've found there are articles here on how to access/change the pixel values in a bitmap.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Thanks for the 2 formulas, highly appreciated! I will test them both. Just for fun
cmk wrote:
As you've found there are articles here on how to access/change the pixel values in a bitmap.
I did find a function on the net earlier today which transforms an icon into a gray scale icon. I used the function and instered the gray scale icon into an image list. Unfortunately, the image list just wouldn't accept the icon's mask! I used PJ Arend's excellent icon/bitmap/dc debugger, and found that the icon renders perfectly when using DrawIcon. Unfortunately, when using the image list (which I added using ImageList_AddIcon), the mask wasn't used, which resulted in blackness instead of transparency. I used ILD_TRANSPARENT when I drew the icon - which works perfectly for "unmodified" icons. The function which transformed the icon into a grayscale icon looked correct: it saved the mask, and modified each pixel using a formula similar to what you describe above. Then recreated the icon using the image bitmap and saved mask.
--
...Coca Cola, sometimes war...
|
|
|
|
|
Yes, i spent the last couple days fighting with the imagelist functions as well. I was modifying my toolbar code to accept a normal colour bitmap, apply appropriate filters, generate hot and disabled bitmaps and then generate/apply toolbar imagelists from each of the three bitmaps.
Originally i was using GDI+ Bitmap to manipulate the image (no problem) and then Bitmap::GetHBITMAP() to get a HBITMAP to pass to Imagelist_AddMasked() - no joy. The image would add but no mask would be created. No matter what i did the mask would not generate correctly.
The docs say Imagelist_AddMasked() will only work on 8bbp or less. Even when i created my own mask i couldn't get Imagelist_Add() to work. I even looked at the WINE implimentation.
I ended up writing my own code to access/manipulate the raw bitmap (24/32bbp) and pass that HBITMAP to Imagelist_AddMasked() which works. That's where i stopped. I didn't try Imagelist_AddIcon().
I found this to be infuriating !
Sorry.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
In case you ever need to draw desaturated image list images, here's a piece of code I found in WTL/atlctrlw.h:
void DrawBitmapDisabled(CDCHandle& dc, int nImage, POINT point,
HBRUSH hBrushBackground = ::GetSysColorBrush(COLOR_3DFACE),
HBRUSH hBrush3DEffect = ::GetSysColorBrush(COLOR_3DHILIGHT),
HBRUSH hBrushDisabledImage = ::GetSysColorBrush(COLOR_3DSHADOW))
{
#if (_WIN32_WINNT >= 0x0501) && (_WIN32_IE >= 0x0501)
if(m_bAlphaImages)
{
IMAGELISTDRAWPARAMS ildp = { 0 };
ildp.cbSize = sizeof(IMAGELISTDRAWPARAMS);
ildp.himl = m_hImageList;
ildp.i = nImage;
ildp.hdcDst = dc;
ildp.x = point.x;
ildp.y = point.y;
ildp.cx = 0;
ildp.cy = 0;
ildp.xBitmap = 0;
ildp.yBitmap = 0;
ildp.fStyle = ILD_TRANSPARENT;
ildp.fState = ILS_SATURATE;
ildp.Frame = (DWORD)-100;
::ImageList_DrawIndirect(&ildp);
}
[snip] It doesn't work on Win2k, but then again, old style graying looks ok anyway in that chunky old GUI.
--
...Coca Cola, sometimes war...
|
|
|
|
|
About icons manipulation, there's an interesting sample in MSDN: IconPro: Icon Manager Sample[^]
And yes, the easiest way to draw icons is IMHO using an ImageList, which accepts HICON entries. Working with a mask should probably help you to do what you want.
Собой остаться дольше...
|
|
|
|
|
I've made a CEdit-derived class called CLockEdit and added a Get- and SetEnabled() function that holds the member variable to see if it should process WM_CHAR messages or not(just so the controls don't look grayed-out when disabled). So I put a CLockEdit control on a dialog that only has that control and the ok and cancel buttons. I allow the user to resize the dialog, and in turn the edit box should also resize. But any CWnd-inherited function like MoveWindow() or GetWindowRect() crashes in wincore.cpp because the hWnd of the control is null. The Methods work like they're supposed to, but I can't resize the window because it crashes on ::IsWindow() in the wincore.cpp file. Any suggestions?
[insert witty comment here]
bdiamond
|
|
|
|
|
Perhaps is your object instantiated but then not created? Do you use CWnd::SubclassDlgItem in your dialog's OnInitDialog?
Собой остаться дольше...
|
|
|
|
|
No, I'm not really familiar with SubclassDlgItem. I placed an edit box on the dialog, and associated a CEdit variable with it. Then I went and changed the type to CLockEdit instead of CEdit. The other functions I made for the derived class work, but not anything that needs an hWnd. I've read what you said and looked it up, but I can't seem to get this to work. Can you elaborate further?
[insert witty comment here]
bdiamond
|
|
|
|
|
bdiamond wrote:
Can you elaborate further?
Yes
To use your own class, there are two ways, using DDX or subclass an existing window: Here will I try to explain the second method:
Let's suppose your control as for identifier ID_MY_CONTROL. You created an edit object with this identifier with the resource editor. Next, you need to add a CLockEdit member attribute to your dialog class, let's say CLockEdit m_MyEdit. Then you have to catch the WM_INITDIALOG message, and in the corresponding method, you have to associate the CLockEdit object with the identifier: that's the role of the method CWnd::SubclassDlgItem:
m_MyEdit.SubclassDlgItem(IDC_MY_CONTROL, this);
You will find useful informations about subclassing (and certainly better explained) in this article by The Master himself: Create your own controls - the art of subclassing[^]
HTH,
K.
Собой остаться дольше...
|
|
|
|
|
I tried that before looking at the article you pointed me to and I get an ASSERTION error in this code in wincore.cpp:
ASSERT(m_hWnd == NULL);
ASSERT(FromHandlePermanent(hWndNew) == NULL);<br />
I also tried using Attach() as I saw in one of my books, and it still didn't work.
[insert witty comment here]
bdiamond
|
|
|
|
|
If you use SubclassDlgItem, be sure not to use the DDX mechanism.
Also, use SubclassDlgItem after having called the base method CDialog::OnInitDialog.
I send you a small example (using VC6), check your mail.
HTH,
K.
Собой остаться дольше...
|
|
|
|
|
That's the same thing I was doing in mine!! However, I saw that in your class the macros IMPLEMENT_DYNAMIC and DECLARE_DYNAMIC weren't there, so I removed that from mine also. Then just to be safe, I deleted the edit box, made another one and started all over. Now it works!!! I thank you a million times.
[insert witty comment here]
bdiamond
|
|
|
|
|
i'm trying to just paint to a dialog using CreateCompatibleDC(), FillRect(), etc, but i cant find the right spot to paint at, i've tried all the OnInitDialog(), etc, doesnt work, only time it works is in OnPaint() then it paints it forever and ever, help me!
|
|
|
|
|
You need to put your painting in OnPaint.
OnPaint will be called whe region needs to get repainted ( when it is Invalidated ).
If your dialog stands on top, and nothing is happening, it should not repaint itself for nothing.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
|
evilslope wrote:
when do i paint?
This is dependant on you geographic location. Generally it is best to paint during the driest part of the year.
-- signature under construction -- -pete
|
|
|
|
|
Papa
while (TRUE)
Papa.WillLove ( Bebe ) ;
|
|
|
|
|
|
With Windows XP, the borders of many controls are now flat (blue with the default theme).
But for TreeCtrl, the borders stay edge.
With the DrawThemeBackground API, I can't found parameters to draw those borders.
Is anyone know how to retrieve informations about current border color ?
Thanks
|
|
|
|
|
Hi,
I found suddenly that in Windows CE .NET (Platform Builder)/eMbedded Visual C++ there is no bsearch function!!! which normally exist in VC++.
How I can get around that issue? Maybe I can get just code for that function which I can icorporate into my.
Thanks in advance.
Val
|
|
|
|
|
It's very easy to roll your own binary search function. With some knowledge of your data structure, someone here can surely be of help.
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|
|
|
hi!
i'm trying to write a custom writer sink using the IWMWriterSink but it doesn't work at all. can someone help me, best provide some simple example code? also, how to i then create my customer writer sink object so i can attach it to the writer using AddSink?
my current code looks like this:
--
class CMySink: public IWMWriterSink
{
public:
HRESULT STDMETHODCALLTYPE OnHeader(
/* [in] */ INSSBuffer *pHeader)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE IsRealTime(
/* [out] */ BOOL *pfRealTime)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE AllocateDataUnit(
/* [in] */ DWORD cbDataUnit,
/* [out] */ INSSBuffer **ppDataUnit)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnDataUnit(
/* [in] */ INSSBuffer *pDataUnit)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE OnEndWriting( void)
{
return S_OK;
}
// QueryInterface
STDMETHODIMP QueryInterface(REFIID refiid, void **ppv)
{
if(1 || refiid == IID_IUnknown)
{
*ppv = static_cast<iwmwritersink*>(this);
static_cast<iwmwritersink*>(this)->AddRef();
return S_OK;
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
// AddRef
STDMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement((PLONG)&refCount_);
}
// Release
STDMETHODIMP_(ULONG) Release()
{
ULONG ul = 0;
if((ul = InterlockedDecrement((PLONG)&refCount_)) == 0)
{
delete this;
}
return ul;
}
ULONG refCount_;
};
--
thanks for any help!!
|
|
|
|
|
I am writing a small project using ODBC which can add, delete and edit records in the database, I have accomplished it, but I don't know how to write the code which I can dump the whole database, I need some advices or sample code, Thanks in advance!
|
|
|
|
|
A simple way (if your database is fairly small) would be to just generate a load of insert statements for all the tables in your database. These could then be replayed in bulk to restore a database.
store your internet favourites online - www.my-faves.co.uk
|
|
|
|
|
Does it necessarily need to go to a text file? If not, I've used this code before to backup up a database:
CShellFileOp ShellFileOp;
CDatabase *pDatabase = GetDatabase();
CString strDBNameFrom,
strDBNameTo;
TCHAR szFilename[_MAX_FNAME],
szExt[_MAX_EXT];
BOOL bAPICalled;
ASSERT(! m_rOptionsInfo.m_strBackupFolder.IsEmpty());
strDBNameFrom = pDatabase->GetDatabaseName();
if (! strDBNameFrom.IsEmpty())
{
strDBNameFrom += _T(".mdb");
_splitpath(strDBNameFrom, NULL, NULL, szFilename, szExt);
strDBNameTo.Format(_T("%s\\Backup of %s%s"), m_rOptionsInfo.m_strBackupFolder, szFilename, szExt);
ShellFileOp.AddSourceFile(strDBNameFrom);
ShellFileOp.AddDestFile(strDBNameTo);
ShellFileOp.SetOperationFlags(FO_COPY, AfxGetMainWnd(), FOF_NOCONFIRMATION);
if (ShellFileOp.Go(&bAPICalled) != FALSE)
AfxMessageBox(IDS_MSG_BACKUPSUCCESS);
else
AfxMessageBox(IDS_MSG_BACKUPFAILED);
}
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|