|
//PIXEL INFORMARTION
unsigned char * t=AreaBIR.GetItemData();
m_winImage.SetPixelsFromData(200, 152, t, false);
m_winImage.IntervalEqualize(0,240,0,255,0,255);
::InvalidateRect(NULL,NULL,FALSE);//Show image on screen
BITMAPINFOHEADER BMIH;
BMIH.biSize = 40;
BMIH.biBitCount = 8;
BMIH.biPlanes = 1;
BMIH.biCompression = 0;
BMIH.biWidth = 152;
BMIH.biHeight = 200;
BMIH.biSizeImage = 30400;
HDC pDC = ::GetDC(0);
HBITMAP hbitmap = CreateDIBSection(pDC->GetSafeHdc(), (CONST BITMAPINFO*)&BMIH, DIB_RGB_COLORS,
(void**)t, NULL, 0);
//Here write the bitmap to a .bmp file (This function works fine)
WriteBMPFile(hbitmap, "C:\\temp.bmp",pDC);
}
The variable "t" contains the pixels information of a fingerprint. I use "t" to display a fingerprint image in a window and works fine, however when I use "t" to create a HBITMAP object, and I pass the HBITMAP object to the WriteBMPFile function, a BLACK image is generated. I believe that my problem is in the creation of the HBITMAP object. Any help will be aprreciated
BTW I found the implementation of WriteBMPFile in http://www.saturnsoftmills.com/Articles/A6.pdf
Thanks
Miguel
|
|
|
|
|
A few things...
Each row of your pixel data needs to be aligned to a DWORD (4-byte) boundary.
You are fine here with a width of 152.
You are using t in CreateDIBSection incorrectly. CreateDIBSection returns a
pointer to its pixel bits - it doesn't take a pointer. Whenever you use a cast like that,
ask yourself if it's correct. You should never have to explicitly cast a pointer to a void
pointer.
Since your pixel data is 8 bits-per-pixel, you need to have a color table.
Instead of a BITMAPINFOHEADER struct, you can use a BITMAPINFO struct,
constructed with the color table...
BITMAPINFO *pbmi = (BITMAPINFO*)new BYTE[sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255];
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = 152;
pbmi->bmiHeader.biHeight = 200;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biBitCount = 8;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiHeader.biSizeImage = 30400;
pbmi->bmiHeader.biXPelsPerMeter = 0;
pbmi->bmiHeader.biYPelsPerMeter = 0;
pbmi->bmiHeader.biClrUsed = 0;
pbmi->bmiHeader.biClrImportant = 0;
for (int i = 0; i < 256; ++i)
{
pbmi->bmiColors[i].rgbRed = <font color="Red">?</font>;
pbmi->bmiColors[i].rgbGreen = <font color="Red">?</font>;
pbmi->bmiColors[i].rgbBlue = <font color="Red">?</font>;
pbmi->bmiColors[i].rgbReserved = 0;
}
<font color="Red">
</font>HDC hdc = ::GetDC(0);
BYTE *pDibBits;
HBITMAP hbitmap = ::CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, &pDibBits, NULL, 0);
<font color="Red">
memcpy(pDibBits, t, 30400);
::ReleaseDC(0, hdc);
delete[] (BYTE*)pbmi;
... use the DIBsection ...
::DeleteObject(hbitmap); Each value in the color table should be the RGB value you want to see for a given pixel data byte.
If you want to write a BMP file yourself:
A "packed" BMP file consists of these, in order:
a BITMAPFILEHEADER struct
a BITMAPINFO or BITMAPCOREINFO struct
a color table for bitmap types that require it (yours does)
the pixel bits (rows DWORD aligned)
Mark
Last modified: 11mins after originally posted --
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Thank you very much for your help! That was exactly what I was looking for. Everything worked… but I need one more thing… do you know how to write the hbitmap object to a bmp file??? I tried using the “WriteBMPFile” method described previously but it did not work because it is creating a distorted image. Do you have any ideas on how to correct that?
Thanks again for your help,
Miguel
|
|
|
|
|
Hi, first of all, sorry for the extension. Im pasting a piece of a tutorial I have. It is explained how to load a bitmap from a file. I think you can inverse the process to save it there.
::::::::::::::::::::::::::::::::::::::::::::::::
Loading DIB through Serialization
Since we are going to store data read from the file in globally allocated memory, first we must add an
HGLOBAL type varible (along with a member function) to class CGDIDoc. Because DIB data will be changed
to DDB data before drawing, a CBitmap type variable and its associated funciton are also declared in class
CGDIDoc:
class CGDIDoc : public CDocument
{
protected:
CBitmap m_bmpDraw;
……
HGLOBAL m_hDIB;
……
public:
CBitmap *GetBitmap(){return &m_bmpDraw;}
……
HGLOBAL GetHDib(){return m_hDIB;}
……
}
Variable m_hDIB is initialized in the constructor:
CGDIDoc::CGDIDoc()
{
m_hDIB=NULL;
}
We will allocate global memory each time a new bitmap file is opened. So when the application exits,
we need to check variable m_hDIB to see if the memory has been allocated. If so, we need to release it:
CGDIDoc::~CGDIDoc()
{
if(m_hDIB != NULL)
{
::GlobalFree(m_hDIB);
m_hDIB=NULL;
}
}
We need to modify function CGDIDoc::Serialize(…) to load data from DIB file. First, when a file is
being opened, variable m_hDIB may be currently in use. In this case, we need to release the global memory:
void CGDIDoc::Serialize(CArchive& ar)
{
if(ar.IsStoring())
{}
else
{
BITMAPFILEHEADER bf;
DWORD dwSize;
LPSTR lpDIB;
if(m_hDIB != NULL)
{
::GlobalFree(m_hDIB);
m_hDIB=NULL;
}
……
Reading data from a DIB file needs the following steps:
1) Read bitmap file header.
2) Verify that the the file format is correct.
3) From the bitmap file header, calculate the total memory needed, then allocate enough buffers.
4) Read the DIB data into the allocated buffers.
We can call CArchive::Read(…) to read bytes from the file into the memory. In the sample, first
bitmap file header (data contained in structure BITMAPFILEHEADER) is read:
……
if
(
ar.Read
(
(LPSTR)&bf,
sizeof(BITMAPFILEHEADER)
) != sizeof(BITMAPFILEHEADER)
)return;
……
Then the file type is checked. If it is DIB format, global memory is allocated, which will be used to
store DIB data:
……
if(bf.bfType != 'MB')return;
dwSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
m_hDIB=::GlobalAlloc(GHND, dwSize);
ASSERT(m_hDIB);
lpDIB=(LPSTR)::GlobalLock(m_hDIB);
ASSERT(lpDIB);
……
Next, the DIB data is read into the global memory:
……
if(ar.Read(lpDIB, dwSize) != dwSize)
{
::GlobalUnlock(m_hDIB);
::GlobalFree(m_hDIB);
m_hDIB=NULL;
}
else ::GlobalUnlock(m_hDIB);
}
}
This completes reading the bitmap file. The DIB data is stored in m_hDIB now.
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
BTW it should be some articles here in codeproject talking about.
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
|
|
|
|
|
Miguel Resto wrote: do you know how to write the hbitmap object to a bmp file???
Yes. You have almost everything you need except a BITMAPFILEHEADER...
BITMAPFILEHEADER FileHdr;
FileHdr.bfType = 'MB';
FileHdr.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255) + 30400;
FileHdr.bfReserved1 = 0;
FileHdr.bfReserved2 = 0;
FileHdr.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255);
Now, before you delete pbmi or t...
Open/truncate a file for writing
Write from &FilHdr (sizeof(BITMAPFILEHEADER) bytes)
Write from pbmi (sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255) bytes)
Write from t (30400 bytes)
Close the file
That's it
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
My Probelm:
I have the following file:
tmath.h: contains some definition of functions imax() and multi()
complex.h: contains the interface of class complex
complex.cpp: contains the implementation of class complex. In this file, complex.h and tmath.h are included.
cmatrix.h: defines some functions on class complex.h. In this file, tmath.h and complex.h are included.
test.cpp: my testing program.
The problem: when I building the .exe file, the compiler (VC 6.0) cannot linking to complex.cpp, says
the functions imax() and multi() are already defined in the test.object.
Can anyboday help me to figure it out? Thanks.
|
|
|
|
|
|
Since tmath.h , complex.h , and cmatrix.h are included multiples times, do you have safeguards in place to prevent multiple inclusions? Check out the #pragma once directive.
"Normal is getting dressed in clothes that you buy for work and driving through traffic in a car that you are still paying for, in order to get to the job you need to pay for the clothes and the car and the house you leave vacant all day so you can afford to live in it." - Ellen Goodman
"To have a respect for ourselves guides our morals; to have deference for others governs our manners." - Laurence Sterne
|
|
|
|
|
1hr 23mins ago
1hr 22mins ago
|
|
|
|
|
Another solution could be to make a new header file (i.e. Headers.h) or use the stdafx.h if you have it, to put all the #includes there.
By the way... #pragma once is the best option
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
|
|
|
|
|
Hi
I need the source code of naive bayes classifier in C++ and I want to run it in VC++ in windows. Please help me.
thanks in advance
|
|
|
|
|
|
Read the post at the top of the forum titled "How to get an answer to your question". Pay attention to #2
|
|
|
|
|
i have a computer that used by several people and i don't want anybody else to change the date and time of the computer, how can i do this through VC++?
thx.
|
|
|
|
|
I dont know, but I can imagine it with a hook, detecting when the Dialog to change date and time of the computer is being called and closing it.
Or saving the actual date and time in this moment and starting a time count somewhere. When that dialog is closed, asking for a password to save the changes, if password correct save changes, if not... restore the previously saved values + time offset.
It is just an idea that came when i read you. Most probably there are much better ways to do it.
Let us see what the masters say.
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
|
|
|
|
|
Make a User account for each person and restrict their privileges.
This is not a C++ answer, was it a C++ question? If not you are in the wrong forum
|
|
|
|
|
hi all,
we are planning to change the look and feel of out product which is developed MFC classes with the help of our own classes as wrapers to MFC control classes to made the control look like flat control..
but on client requests we need to make controls look even more ritch like XP control.. with minimal changes
for that iwas looking at comancontrol6.0.. but comancontrol6.0 works only on windows XP.. but our product is well established on win2k server
please some one help me in finding out what the best solution for my problem mentioned abow
and also let me know how abt GDI+ , please let me know wether GDI+ works on win2k r no
am eagerly waiting for the suggessions from u
i hope u all will help me finding out the best solution for me
thank you
|
|
|
|
|
Well first of all GDI+ is part of the .Net framework 2.0. And indeed it works on Win2K, although since you cannot use XP's visual styles you will not be able to use them.
There is nothing stopping you from creating your own controls derived from the .Net controls and change their draw methods.
Dewm Solo - Managed C++ Developer
|
|
|
|
|
sarat12in wrote: please let me know wether GDI+ works on win2k r no
They hide that information in the documentation[^]
|
|
|
|
|
|
The size of your message pieces depends on your communication medium. You need to experiment and find the balance between transmission time and the overhead to prepare a message segment. Also, you'll need to implement some kind of handshake to handle corrupt message pieces.
If you're that concerned about corruption, do some investigating about Error Correcting Codes.
Judy
|
|
|
|
|
What protocol are you using?
If it's TCP, you don't need to worry about CRC.
You probably won't be able to send that much data in one
send() call though
Are you encrypting the data or just worried about successful delivery?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|
Russell' wrote: I'm using socket with TCP protocol.
I don't need to encript the data, my only problem is the success of this trasmission.
Why worry about this then?
Yes, the TCP protocol will split your data into "frames". The network may further split those
frames. The protocol will also check for successful transmission, resend when necessary, etc. until all
data sent transmits successfully.
I'm not sure what you hope to gain by splitting into smaller units yourself.
I would let TCP do its thing. It's a very reliable protocol.
As for the send() function (and recv() as well), how much you can do at one time
depends on the socket's buffer size and how much room is left in that buffer.
Nothing changes at the application layer of the protocol stack however - you should always be
calling send() and recv() enough times until all data is sent or received.
When sending, for example (receiving is very similar)...
char *pNextByteToSend = ;
int nBytesToSend = ;
while (nBytesToSend > 0)
{
int nBytesSent = ::send(socket, pNextByteToSend, nBytesToSend, 0);
if (SOCKET_ERROR == nBytesSent)
{
int sockerr = ::WSAGetLastError();
if (sockerr != WSAEWOULDBLOCK)
{
break;
}
}
pNextByteToSend += nBytesSent;
nBytesToSend -= nBytesSent;
}
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
|