|
Kiran Satish wrote: Any suggestions ??
Yes. Get it working just drawing right on the dialog.
I don't know that this control is (Disp = GetDlgItem(ID_PSF); )
that you're drawing to but it's adding unnecessary complexity.
The DIBSectionDC only needs to be created when you create the dibsection,
not every time you draw - we're trying to SAVE time here
Destroy it when you destroy the DIBSection - they go hand-in-hand.
But again, I recommend getting it working drawing right on the dialog.
That means your destination DC is the paintdc, that's fine as long as there's
no controls in the way. That way, you can see what's going on.
Also, go through the code line by line and make sure you understand it.
The same principles apply as you were doing before with setpixel.
the only difference is now you draw to an offscreen DC and then blt the final drawing
to the screen. You have a pointer to the offscreen bits so you can write pixel
values directly to memory and/or use gdi functions to draw offscreen (by
drawing to the DIBSectionDC)....that's the power.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
At last got it running , removed the text box from the window and bilted it directly onto the dialog box as follows.
void CPSFDlg::OnPaint() <br />
{<br />
CPaintDC dc(this);
HGDIOBJ holdbm;<br />
RECT rect;<br />
BYTE color;<br />
int align_top,align_left;<br />
this->GetClientRect(&rect);<br />
align_top = (rect.bottom - rect.top - row) / 2;<br />
align_left = (rect.right - rect.left - col) / 2;<br />
this->InvalidateRect(NULL,TRUE);<br />
RGBTRIPLE *pCurRowPixel = (RGBTRIPLE *)(pDIBSectionBits);<br />
for (int y = 0; y < col; ++y)<br />
{<br />
for (int x = 0; x < row; ++x)<br />
{<br />
color = (BYTE) data[x * col + (row - 1 - y)];<br />
pCurRowPixel[x].rgbtBlue = color;<br />
pCurRowPixel[x].rgbtGreen = color;<br />
pCurRowPixel[x].rgbtRed = color;<br />
}<br />
pCurRowPixel = (RGBTRIPLE *)((BYTE*)pCurRowPixel + Stride);<br />
} <br />
holdbm = memDC.SelectObject(hbm);<br />
dc.BitBlt(align_left, align_top, bmi.bmiHeader.biWidth, bmi.bmiHeader.biHeight,&memDC,0,0,SRCCOPY);<br />
memDC.SelectObject(holdbm);<br />
}
the problem is, the window keeps on refreshing all the time even though there is nothing happening on tht window and you can see the image flickering in it. How to get rid of it??
thanks,
PKNT
|
|
|
|
|
Never call InvalidateRect or InvalidateRgn from your WM_PAINT handler.
This causes endless WM_PAINT messages! Bad!
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Ooops.... I am just getting on track now... Actually I didnt have InvalidateRect in there at first, at that time, the window doesnt refresh at all. I started off with data filled with 255 and when I ran the program it showed me a nice whire box, but when I do some calculations and when the box is supposed to be changed it doesnt reflect the new data, it still stays white until I move another window over it or something like tht. This is why I added that in OnPaint function.
Anyway I got it now... replaced it into the calling function and tht did the trick. Now I can't wait to do the same for all other windows and see how the performance increases.
thanks,
PKNT
|
|
|
|
|
Whenever your data is updated, use InvalidateRect()/UpdateWindow() (or RedrawWindow()).
This will force an immediate WM_PAINT message to be sent to the window's window procedure.
Just don't do it from inside the WM_PAINT handler
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Did exactly the same.... now everything is fine... time to go home.. will modify other windows the same way tomm.
thanks for all your help and patience...
PKNT
|
|
|
|
|
Gr8, changing all the drawing to bitmaps improved the speed to ~11Hz. The main bottleneck as you thought before is from a very big matrix multiplication which is done in a for loop element by element. To sum up that multiplication, it includes 66x100x100 matrix (static) multiplied by a 1x66 matrix (variable). I changed this using matrix library from OptiVec and now the speed boosted to ~16Hz. I have to change another loop of the same kind but involves complex matricies of 66x64x64 and 1x66 sizes. That should improve speed close to ~20Hz. But for now ~16Hz is pretty impressive for our application.
Now I will start on developing a new application to display a TIFF image (greyscale images), zoom in and out able to select some points (mark them in red) on the image using mouse, delete any selected point or move any selected point in any mode (normal, zoom in/out) using mouse. Some basic IP functions like histogram equalization, brightness/contrast adjustment. I think single document interface is good enough for this. But whats the best way to draw image (our images may be very big anywhere from 512x512 to 2000x3000) ??
PKNT
|
|
|
|
|
Kiran Satish wrote: But whats the best way to draw image (our images may be very big anywhere from 512x512 to 2000x3000) ??
StretchBlt() takes a source rect and a destination rect so you can specify exactly
what you want drawn, where, and at what scale.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
So you have a 12x12 grid of cells and you're filling each cell with pixels right?
If so, I would...
Create a memory DC - this only needs to be done for the lifetime of the drawing,
not every time a redraw is done
Make one DIBSection, 24-bit RGB. the size of the 12 cells plus any
gaps/dividers/borders. This only needs to be (re)created if the dimensions
change.
Select the DIBSection into the memory DC.
Now you can use GDI APIs to draw any borders/dividers/etc. You may only have to
do this once as well if you're not overwriting them with data pixels.
Use the pointer to the DIBSection's pixel bits to directly write pixel values in your loops.
The "stride" (# of bytes per row) only needs to be calculated once, or whenever the
size of the DIBSection changes.
To calculate starting offset (rowpointer) in pixel data, use y*stride+x*3
Cast this pointer to an RGBTRIPLE*
For each row
Loop inserting row's pixel data (use rowpointer[x] to index)
Add stride to rowpointer
You'll find this MUCH faster than SetPixel()
After all the cells have been drawn offscreen, a single BitBlt (or StretchBlt)
call can copy the entire grid to the window.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Kiran Satish wrote: Hope this helps in understanding a lil better.
Yes! Thank you!
In that case the DIBSection can be 202x202.
The calculations I've explained previously will work.
The entire grid bitmap can then be blted to the window at whatever offset you want.
** I replied to your last message but the reply came back to me.<br />
I think we exceeded the maximum message hierarchy depth in Code Project
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I had problems with my previous project too. If it doesn't matter you, I think it will be better if you use a View/Doc app insteads of DialogBox app. The view has more functionality than a dialog box. When I changed it, it worked 2,3 times faster with my programm.
If you centralize all datas in the document, and use different views for showing whatever you need, I think it will be faster.
Greetings.
--------
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
|
|
|
|
|
I thought of implementing in Doc/View architecture, but I have soo many displays embedded into my main display, I am not sure how I can implement soo many views. Not to say the least, I am not that familiar with Doc/View implementation, any good resources on it which are simple and straight away rather than jumping from one part to another part??
thanks
|
|
|
|
|
About how to jump between the views, look for messages related that I wrote. I have asked about how to create different views with different menus more than once. The last, a few days ago.
But if you think is going to be difficult for you to go clear with the Doc/View... then u should try it as you think is better for you.
Greetings.
--------
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
|
|
|
|
|
Any time you select an object into a DC, you should save the
previously selected object. When you're done with the DC, select the original
object back into the DC.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I need some help/advice on modifying a part of my existing code. I have this application where I use the libraries provided by one of our hardware manufacturers through which we grab a frame from a monochrome camera into a memory (BYTE*) defined/assigned to that library and it displays the captured frame into the window handle that we assign to it. But for some more processing I would like to display the captured frame using my own dc object. But how can I display a 8 bit (monochrome) data into a dc ??
-thanks
PKNT
|
|
|
|
|
The easiest and most flexible way to do that is to create a DIBsection and copy your pixel bits
into it. That gives you an HBITMAP you can select into DCs, and also a pointer to the pixel
bits so you can directly manipulate them.
Here's an example of the basic stuff for creating an 8bpp grayscale DIBSection:
LONG lImageWidth = 640;
LONG lImageHeight = 480;
WORD wBitsPerPixel = 8;
LONG lStride = (((lImageWidth * (long)wBitsPerPixel + 31L) & (~31L)) / 8L);
BITMAPINFO *bm = (BITMAPINFO *)new BYTE[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)];
bm->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bm->bmiHeader.biWidth = lImageWidth;
bm->bmiHeader.biHeight = lImageHeight;
bm->bmiHeader.biPlanes = 1;
bm->bmiHeader.biBitCount = wBitsPerPixel;
bm->bmiHeader.biCompression = BI_RGB;
bm->bmiHeader.biSizeImage = 0;
bm->bmiHeader.biXPelsPerMeter = 0;
bm->bmiHeader.biYPelsPerMeter = 0;
bm->bmiHeader.biClrUsed = 0;
bm->bmiHeader.biClrImportant = 0;
for (int color_index = 0; color_index < 256; color_index++)
{
bm->bmiColors[color_index].rgbBlue = color_index;
bm->bmiColors[color_index].rgbGreen = color_index;
bm->bmiColors[color_index].rgbRed = color_index;
bm->bmiColors[color_index].rgbReserved = 0;
}
BYTE *pBitmapBits;
HBITMAP hBitmap = ::CreateDIBSection(NULL, bm, DIB_RGB_COLORS, (void**)&pBitmapBits, NULL, 0);
if (hBitmap)
{
::DeleteObject(hBitmap);
}
delete[] (BYTE *)bm; Copy your captured 8-bit pixel data to the array pointed to by pBitmapBits.
lStride is the length of each row in bytes - there may be extra bytes at the
end of each row so make sure you take that into account.
You can use hBitmap just like any DDB. You can select it into a memory DC and draw on it
with GDI functions, blt it to the screen, etc.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hello,
I'm rewriting my console application in MFC. The applications is a port scanner and it works very fine in as a console application. However, when writing it in MFC I get an unhandled exception where it isn't supposed to be.
<br />
void CNetScanMfcDlg::OnBnClickedButton1()<br />
{<br />
LPTSTR host = m_host.GetBuffer(255);
PortScanner portScanner((char*) host, m_startPort, m_endPort);<br />
}<br />
PortScanner::PortScanner(char* sHost, int startPort, int endPort) {<br />
address.sin_family = AF_INET;<br />
hostent* host = gethostbyname(sHost);<br />
address.sin_addr.s_addr = (unsigned long) atoi(host->h_addr_list[0]);
this->startPort = startPort;<br />
this->endPort = endPort;<br />
}<br />
gethostbyname() appears to return NULL, but it's not a problem with the host itself if I put gethostbyname("localhost") it works fine. I believe the string conversion causes this problem.
|
|
|
|
|
Since gethostbyname() expects a const char* , why are you using a char* instead? That in itself is not bad, but your use of GetBuffer() is unnecessary.
Mike Borozdin wrote: hostent* host = gethostbyname(sHost);
What is the value of sHost at this point? If gethostbyname() is returning NULL , are you calling WSAGetLastError() to find out why?
Mike Borozdin wrote: address.sin_addr.s_addr = (unsigned long) atoi(host->h_addr_list[0]); //this leads to an exception
Is host non-NULL at this point?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
The value of sHost is correct, that is if I enter "localhost" in the edit box it will be "localhost", but host is NULL , but if I put "localhost" instead of sHost it won't be NULL , so it makes me thing that there is something wrong in string conversion. Anyway I worked it out, I found a solution here. However, I'm still going to see what was wrong with my piece of code, probably I should have added a traling zero.
|
|
|
|
|
Mike Borozdin wrote: Anyway I worked it out, I found a solution here.
Resulting in what change?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
It made it work
|
|
|
|
|
Ok, so my question was a bit ambiguous. I meant, what change was required in your code?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
I replaced:
<br />
LPTSTR host = m_host.GetBuffer(255);
PortScanner portScanner((char*) host, m_startPort, m_endPort);<br />
with:
<br />
size_t CharactersConverted = 0;<br />
char host[100];<br />
wcstombs_s(&CharactersConverted, host, m_host.GetLength()+1, m_host, _TRUNCATE);<br />
PortScanner portScanner(host, m_startPort, m_endPort);<br />
|
|
|
|
|
This looks to be a Unicode vs. ANSI issue. Which are you using?
"A good athlete is the result of a good and worthy opponent." - David Crow
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
Sorry for a lame question, but how do I find out which one I'm using?
|
|
|
|