|
hey there!
I have a problem dealing with this bitmap. using MFC, i must create a function that return the values of bitmap frequency vs. its pixel value when I load it in the window. This is somewhat like a histogram.
Can somebody share me some hints or ideas about this?
Thanks!
|
|
|
|
|
Would you care to explain a little more about what exactly you are trying to do? What is "bitmap frequency" and "pixel value", how do you intend to calculate these values and how are you going to represent your found data?
Waldermort
|
|
|
|
|
You loop over the pixel and make a map<int, int=""> with the color_number as key and the number of pixel with this color_number as value.
typedef std::map<int, int> HistoMapT;
HistoMapT theMap; For every color-number you encounter, you add one to the value under the key "color-number"
E.g. The first pixel has value 30:
You check if this number is already in the map. When it is, you increment its value. When its not, you insert it with a value of 1:
HistoMapT::iterator theIterator = theMap.find(color_number);
int value = 1;
if (theIterator != theMap.end() ) {
value += theIterator.second;
}
theMap.insert(MAKEPAIR(color_number, value));
You see, std::map is quite helpful here, providing you with elegant and easy to read code.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words{
|
|
|
|
|
jhwurmbach wrote: You see, std::map is quite helpful here, providing you with elegant and easy to read code.
maybe, but it will be very very slow, compared to:
int * histogram = new int[256 * 256 * 256];
memset(histogram, 0, 256 * 256 * 256 * sizeof(int));
for (int x=0;x< w;x++)
for (int y=0;y< h;y++)
{
histogram[(int)RGB(pixel.Red, pixel.Green, pixel.Blue)]++;
pixel++;
}
|
|
|
|
|
Chris Losinger wrote: maybe, but it will be very very slow
May or may not. That probably depends on the pattern of usage and the picture.
You are newing 28MB in one piece here.
AND you are still limited to 8-bit per color.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
jhwurmbach wrote: May or may not.
you're calling how many functions per pixel?
vs. my single macro (which is a couple of bit shifts and logical ORs) and an array index.
jhwurmbach wrote: You are newing 28MB in one piece here
64MB. but that's really not a big deal. your map will potentially require many times more than that.
you're right that your map will require less memory (though more memory allocations) in cases where images have few colors.
jhwurmbach wrote: AND you are still limited to 8-bit per color.
true. it's an easy enough problem to fix. and your map will potentially suffer the same memory bloat.
-- modified at 10:34 Tuesday 9th October, 2007
ok... i'm bored, so i did some testing:
typedef std::map< int, int> HistoMapT ;
const int w = 1000;
const int h = 1000;
BYTE *p = = new BYTE[w * h * 3];
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
p[x * 3 + y * w * 3 + 0] = x % 256;
p[x * 3 + y * w * 3 + 1] = y % 256;
p[x * 3 + y * w * 3 + 2] = (x + y) % 256;
}
}
{
CTimer c("Map");
BYTE * pix = p;
HistoMapT theMap;
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
int color_number = RGB(pix[0], pix[1], pix[2]);
HistoMapT::iterator theIterator = theMap.find(color_number);
int value = 1;
if (theIterator != theMap.end() )
{
value += (*theIterator).second;
}
theMap.insert(std::pair< int, int>(color_number, value));
pix+=3;
}
}
}
{
CTimer c("C");
BYTE * pix = p;
int *histo = new int[256 * 256 * 256];
memset(histo, 0, 256 * 256 * 256 * 4);
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
histo[RGB(pix[0], pix[1], pix[2])]++;
pix+=3;
}
}
delete [] histo;
}
delete [] p;
here are the results:
// source image init'd to gradients
Map 2.01s
C 0.16s
// source image init'd to all zero
Map 0.30s
C 0.08s
// changing the source init to
p[x * 3 + y * w * 3 + 0] = x % 256;
p[x * 3 + y * w * 3 + 1] = y % 256;
p[x * 3 + y * w * 3 + 2] = x / 256;
Map 11.25s
C 0.08s
-- modified at 10:42 Tuesday 9th October, 2007
-- modified at 10:54 Tuesday 9th October, 2007
|
|
|
|
|
[memory block size]
Chris Losinger wrote: 64MB. [...]Your map will potentially require many times more than that.
Yes. Potentially. Very probably much less, by leaving out the unused color values.
But that sure depends on the picture you process.
[limit to 8bpp]
Chris Losinger wrote: true. it's an easy enough problem to fix.
Sure. At the expense of much more obligate alocated memory in one piece.
And no, the map will behave much more conservative, as the saved memory by not storing the unused pixel values will be more prominent.
But you are right in that the access is slower. This might or might not be an issue.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
i ran the timing tests (see the update above). the C version absolutely kills the map version. more than 3x faster for solid 0s, two orders of magnitude faster for one of the gradients.
-- modified at 10:55 Tuesday 9th October, 2007
-- modified at 10:58 Tuesday 9th October, 2007
|
|
|
|
|
Chris Losinger wrote: i ran the timing tests
Me too.
From your test-code I got 56msec vs. 85 msec for the map. Thats factor 1.5
I'm still unimpressed.
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
jhwurmbach wrote: From your test-code I got 56msec vs. 85 msec for the map.
debug or release ?
jhwurmbach wrote: Thats factor 1.5
I'm still unimpressed.
if only my customers were so ambivalent about performance!
|
|
|
|
|
Chris Losinger wrote: debug or release
VC++ 7.1. Release mode.
There is so much security built in in Debug, that there is no point comparing with raw C.
Chris Losinger wrote: if only my customers were so ambivalent about performance!
They are for me. At least for the sub-second delays we are talking about here.
I have added the stdext::hash_map and now I get
map: 57 msec
hash_map: 24 msec
C-Array: 85 msec
Here is my code:
#include "stdafx.h"
#include "Windows.h"
#include "MMSystem.h"
#pragma comment( lib, "winmm")
#include <tchar.h>
#include <iostream>
#include <map>
#include <hash_map>
#undef max
#undef min
static const int TARGET_RESOLUTION = 1;
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::map<int, int> HistoMapT ;
typedef stdext::hash_map< int, int> HashHistoMapT;
typedef std::pair<int, int> Int_PairT;
const int w = 1000;
const int h = 1000;
TIMECAPS tc = {0};
UINT wTimerRes = 5;
if( ::timeGetDevCaps( &tc, sizeof(TIMECAPS)) != TIMERR_NOERROR)
{
std::cout << "Timer Error";
return system("pause");
}
wTimerRes = std::min( std::max( tc.wPeriodMin, (UINT)TARGET_RESOLUTION), tc.wPeriodMax);
::timeBeginPeriod( wTimerRes);
BYTE *p = new BYTE[w * h * 3];
for (int x=0; x< w;x++)
{
for (int y=0;y< h;y++)
{
p[x * 3 + y * w * 3 + 0] = w % 256;
p[x * 3 + y * w * 3 + 1] = h % 256;
p[x * 3 + y * w * 3 + 2] = (w + h) % 256;
}
}
const UINT before1 = ::timeGetTime();
{
BYTE * pix = p;
HistoMapT theMap;
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
const int color_number = RGB(pix[0], pix[1], pix[2]);
HistoMapT::iterator theIterator = theMap.find(color_number);
int value = 1;
if (theIterator != theMap.end() )
{
value += (*theIterator).second;
}
theMap.insert(Int_PairT(color_number, value));
pix+=3;
}
}
}
const UINT after1 = ::timeGetTime();
const UINT before2 = ::timeGetTime();
{
BYTE * pix = p;
HashHistoMapT theMap;
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
const int color_number = RGB(pix[0], pix[1], pix[2]);
HashHistoMapT::iterator theIterator = theMap.find(color_number);
int value = 1;
if (theIterator != theMap.end() )
{
value += (*theIterator).second;
}
theMap.insert(Int_PairT(color_number, value));
pix+=3;
}
}
}
const UINT after2 = ::timeGetTime();
const UINT before3 = ::timeGetTime();
{
BYTE * pix = p;
int *histo = new int[256 * 256 * 256];
memset(histo, 0, 256 * 256 * 256 * sizeof(histo[0]));
for (int x=0;x< w;x++)
{
for (int y=0;y< h;y++)
{
histo[RGB(pix[0], pix[1], pix[2])]++;
pix+=3;
}
}
delete [] histo;
}
const UINT after3 = ::timeGetTime();
delete [] p;
::timeEndPeriod( wTimerRes);
std::cout << "Elapsed timing map: " << (after1 - before1) << " msec." << std::endl;
std::cout << "Elapsed timing hash_map: " << (after2 - before2) << " msec." << std::endl;
std::cout << "Elapsed timing C-Code: " << (after3 - before3) << " msec." << std::endl;
return system("pause");
}
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
there was a bug in my original test code.
you need to change this:
p[x * 3 + y * w * 3 + 0] = w % 256;
p[x * 3 + y * w * 3 + 1] = h % 256;
p[x * 3 + y * w * 3 + 2] = (w + h) % 256;
(w and h are constant so the image is a solid color)
to this:
p[x * 3 + y * w * 3 + 0] = x % 256;
p[x * 3 + y * w * 3 + 1] = y % 256;
p[x * 3 + y * w * 3 + 2] = (x + y) % 256;
Elapsed timing map: 1002 msec.
Elapsed timing hash_map: 1887 msec.
Elapsed timing C-Code: 120 msec.
Press any key to continue . . .
|
|
|
|
|
Chris Losinger wrote: Elapsed timing map: 1002 msec.
Elapsed timing hash_map: 1887 msec.
Elapsed timing C-Code: 120 msec.
Press any key to continue . . .
Here, its
Elapsed timing map: 455 msec.
Elapsed timing hash_map: 247 msec
Elapsed timing C-Code: 185 msec.
Are you still in Debug?
Though I speak with the tongues of men and of angels, and have not money, I am become as a sounding brass, or a tinkling cymbal. George Orwell, "Keep the Aspidistra Flying", Opening words
|
|
|
|
|
jhwurmbach wrote: Are you still in Debug?
nope.
VS05, Release. optimized for "Maximize Speed"
|
|
|
|
|
Hi
When I right click on a folder , I need to disable any of the Menu Option.
Any Suggestions would be helpful.
Thanks
Today is a gift, that's why it is called the present.
|
|
|
|
|
even iam eager to find answer for this.
thanks to the poster and the answerer.
|
|
|
|
|
When you use the CMenu class, you can disable menu options as follows:
CMenu * Menu = GetMenu (); // Gets the window's menu (if any)
if (Menu != (CMenu *)NULL) // make sure there is a menu
{
CMenu * SubMenu = Menu->GetSubMenu (nItem); // Gets the submenu at nItem (starts at 0)
if (SubMenu != (CMenu *)NULL) // make sure there is a submenu
{
SubMenu->EnableMenuItem (nMenuItemID, MF_GRAYED|MF_BYCOMMAND); // disables the menuitem
}
}
The itemID can be either the command id or the position in the menu. This is indicated by the MF_BYCOMMAND, which can be replaced by MF_BYPOSITION to use a sequence number rather that the command ID.
In stead of MF_GRAYED (which disables the command and grayes it), you can also use MF_DISABLED (which disables the command but does not gray it) and of course MF_ENABLED, which enables the command.
Goof luck
William
|
|
|
|
|
Thanks william.
What I did is, Iam getting the Handle of Windows Media Player Application.
and from it a pointer to the menu bar.Now I want to disable the File->Open menu Item . How Should I do it?
Iam doing as below...
CWnd *pWnd = CWnd::FindWindow(_T("WMPlayerApp"),NULL);
CMenu *pMenu = pWnd->GetMenu();
if (pMenu != NULL && pMenu->GetMenuItemCount() > 0)
{
CMenu * pSubMenu = pMenu->GetSubMenu (0);
if (pSubMenu != (CMenu *)NULL)
{
pSubMenu->EnableMenuItem (nMenuItemID, MF_GRAYED|MF_BYCOMMAND);
}
}
What is that I should specify in place of nMenuItemID?
How do I know the Id of a sub menu in another Appln?
Thanks
Today is a gift, that's why it is called the present.
|
|
|
|
|
I got it...
pSubMenu->EnableMenuItem (pSubMenu->GetMenuItemID(0), MF_GRAYED|MF_BYCOMMAND); // disables the menuitem
Thanks.
Today is a gift, that's why it is called the present.
|
|
|
|
|
Hello again,
Now, I have problem upon building an MFC project.
Error is: "unexpected end of file while looking for precompiled header directive"
This is due to insertion of an API. I added these files and when I build the project the error appears. Does someone knew of the cause of this problem?
Do I need to change the build properties?
Hope somebody can comment.
Thanks.
|
|
|
|
|
Either you have to include the stdafx.h in the newly added file or you can change the setting so that, the file is not using the precompiled hearder file. for this follows the below step.
project setting->c++->In the categaory combo select "precompiled header". select your file in the left tree view and change the settings to "Not using precompiled headers".
|
|
|
|
|
Thank you very much nave for your time.
I have also figured it out.
Till next post. God Bless.
|
|
|
|
|
For example, Inside a Dialog i have 3 edit controls. If i want to update all 3 controls, i will call UpdateData(True). If, i want to update only a particular contol value(i.e. i don't want to update remaining 2 controls value). how is it possible?
Sethuraman.K
|
|
|
|
|
|
Sethuraman.K wrote: For example, Inside a Dialog i have 3 edit controls. If i want to update all 3 controls, i will call UpdateData(True). If, i want to update only a particular contol value(i.e. i don't want to update remaining 2 controls value). how is it possible?
Sethuraman.K
Use Control's SetWindowText api!
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|
|