|
Hi,
Each pixel value is in the form of 32 bit. I understand the last 24 bits represent RGB values(8bits each) and the rest 8 bits are unused (value=0).
I am not sure how I can create a proper pixel palette to convert this image to bitamp and display it.
|
|
|
|
|
do you know the dimensions of the image?
i mean, pixels along x and pixels along y.
--------------------------------------------
Suggestion to the members:
Please prefix your main thread subject with [SOLVED] if it is solved.
thanks.
chandu.
|
|
|
|
|
Hi yes i know the dimensions of the image ..Its 1004*1002
|
|
|
|
|
I supose you do know the dimensions of your image (width and height) so when you create a DIB in memory of that size, as the documentation states, you get a pointer to the first pixel and can start copying your pixel data performing conversion if needed.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
Hi..
i know the dimensions of the image data. its 1004*1002. I created a DIB with CreateDIBSection. But the color information looks very different from the image which i obtained from the camera using its software. Right now my data is 32 bit (24bit RGB + 8bits unused). could u please advice me on how to convert the bit depth from 32bit to 8bit?
|
|
|
|
|
Why do you want to convert it to 8 bit? You can create 24 and 32 bit DIBs.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
The color imformation looks very different in the DIB which i have generated. I am not sure if i should use some color palette. Please find below the code which i used
HDC dc= CreateCompatibleDC(NULL);
BITMAPINFO info;
ZeroMemory( &info.bmiHeader, sizeof (BITMAPINFOHEADER) );
info.bmiHeader.biHeight = 1002;
info.bmiHeader.biWidth = 1004;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 24;
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
info.bmiHeader.biClrUsed= 0;
info.bmiHeader.biClrImportant= 0;
long* pixels;
int Buffersize = 1004*1002;
HBITMAP hbmp= CreateDIBSection( dc,
&info,
DIB_RGB_COLORS,
(void**)&pixels,
NULL,
0 );
pixels = (long*) malloc(Buffersize*sizeof(long));
for(int j=0; j < Buffersize; j++)
{
pixels[j] = arr[j];
}
int nFile = _open ("c:\\Image.bmp", _O_CREAT | _O_TRUNC | _O_BINARY | _O_WRONLY, _S_IWRITE);
int nBitmapDataSize = (width * height * 3);
int nFileSize = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER) + nBitmapDataSize;
int nOffset = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER);
BITMAPFILEHEADER bmfh;
bmfh.bfType = ((WORD) ('M' << 8) | 'B');
bmfh.bfSize = nFileSize;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = nOffset;
BITMAPINFOHEADER bmih;
memset (&bmih, 0, sizeof (BITMAPINFOHEADER));
bmih.biSize = sizeof (BITMAPINFOHEADER);
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biWidth = width;
bmih.biHeight = height;
_write (nFile, &bmfh, sizeof (BITMAPFILEHEADER));
_write (nFile, &bmih, sizeof (BITMAPINFOHEADER));
_write (nFile, pixels, nBitmapDataSize);
_close (nFile);
|
|
|
|
|
What are you trying to achieve here? If you wish to save your image you don't need a DIB section, i thought you wanted to display the image on some window for example, for that you could use the DIB, to save a bitmap to a file you can simply write the headers and the pixel data as you did without any device contexts or HBITMAPs. So let's forget the DIB and consider you just want to save the data to a bmp file. Explain what you mean by "looks very different". You should know that in a bitmap each scanline's bytecount has to be dividable by 4 otherwise your image will look disorted. To explain what i mean: you say your image's width is 1002 pixels. If you want a 24 bits per pixel bitmap, then every pixel is 3 bytes, right? So 1002 pixels is 1002 * 3 = 3006 bytes. 3006 / 4 = 751.5, so your scanlines do not occupy a multitple of 4 bytes. You need padding to overcome this, you have to add zeros to the end of each scanline till your scanline's bytecount can be divided by 4. So after you write 3006 bytes into the file for the RGB data you also need to write 2 additional bytes of 0, this way your scanlines will have 3008 bytes, which can be divided by 4 (752). You have to do this for each scanline. You should read about the bitmap file format here[^] or just google[^] a bit around.
Imho, you are better of trying to save a 32 bpp bitmap, since 32 bits are 4 bytes, your 1002 pixels on a scanline will occuppy 4008 bytes which is -obviously- dividable by 4.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
hii.
I am trying to display the image onto a window. But i'm not sure how to do it with DIB. So i just thought of saving it onto disk. Can u advice me on how to use DIB for displaying?
Actually the width of my image is 1004 and the height is 1002. So the width will be divisible by 4.
|
|
|
|
|
Well, you were on the right track there with creating the DIB section as you have shwon in your code but you don't need a DC, just feed it NULL there. Once you copied the pixel data into your DIB you can blit it onto a window like any other bitmap. So something like this for example:
void CMyWindow::OnPaint()
{
CPaintDC dc(this);
CDC MemDC;
MemDC.CreateCompatibleDC(dc);
HBITMAP original_bitmap = (HBITMAP)::SelectObject(MemDC, my_dib_handle);
dc.BitBlt(0, 0, 1004, 1002, &MemDC, 0, 0, SRCCOPY);
::SelectObject(MemDC, original_bitmap);
}
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
hi there.
I tried using the onpaint function in my program. But it does not seem to recognise the function. It throws error like
1. CMywindow: is not a class or namespace name
2. CPaintDC : undeclared identifier
I think i'm making a big mistake somewhere.
Could you please help me on where i should use this function in my above code? Or is it to be done in MFC's?
Thanks very much
|
|
|
|
|
I believe your biggest mistake is that you are trying to literally integrate the example i gave you into your program word by word... that code snipplet was just an example. Do you have a window in your application you wish to show the image on? You should do that when that window gets the WM_PAINT message. If you don't know what i am talking about then you should read some windows programming books or google around for tutorials and such. Good luck.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
Ya. I have been doing some learning to get this working. Can u pls let me know how to use OnPaint function? Does it work with MFC's?
I am getting confused with them.
|
|
|
|
|
Well, as said, google is your friend, you can find all that info, however, add this to the message map of your window: ON_WM_PAINT()
It would look something like this, please don't copy paste this into your code and try to compile, it is just an example so you know how it should look...so about...
BEGIN_MESSAGE_MAP(CMyWindow, CMyWindowsSuperClass)
...
ON_WM_PAINT()
...
END_MESSAGE_MAP()
Let's assume you named the class for your window CMyWindow, so in the header file, declare the OnPaint method similarry to this:
class CMyWindow: public CMyWindowsSuperClass
{
...
void OnPaint();
...
};
and then implement this method in the cpp file that contains your window class' implementation, similar to this:
void CMyWindow::OnPaint()
{
CPaintDC dc(this);
}
I hope this helps...
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
Hi there,
The image data that i have got represent intensity of light falling on the sensor(whcih is 32 bits per pixel) . Can u pls suggest me how i can use palette files when displaying images to visualise contrast in intensities?
Many Thanks
|
|
|
|
|
Never worked with palettes so i can't, sorry...
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
> Life: great graphics, but the gameplay sux. <
|
|
|
|
|
Currently your data is in long integer right.
So now just ur data is actualy a pixel data. which contains the pixel intensity for Monochrome and RGB for color.
So use GDI+
You want pixel data as long pointer array to bitmap from which it will be easy to create a image.
Bitmap * BitMapHandler::PixelInfo2BitMap(int width, int height,
int *pixData )
{
// Fistly create a temp Bmp with the height and width of the image.
Bitmap bit(width, height, PixelFormat32bppARGB );
// Create clone as as to return as output.
Bitmap *bmp = bit.Clone(0, 0, bit.GetWidth(), bit.GetHeight(),
PixelFormat32bppARGB);
BitmapData bmData;
Rect rect(0, 0, bmp->GetWidth(), bmp->GetHeight());
bmp->LockBits(rect,
ImageLockModeRead | ImageLockModeWrite,
PixelFormat32bppARGB,
&bmData);
int stride = bmData.Stride;
BYTE *pArr = (BYTE *)((void *)bmData.Scan0);
int nOffset = stride - width*4;
int pixel;
for(int y=0; y < height;y++) {
for(int x=0; x < width; ++x ) {
// GDI lies about RGB - internally it's BGR
pixel = pixData[y*width+x];
pArr[3] = (BYTE) ((pixel >> 24) & 0xff); // alpha
pArr[2] = (BYTE) ((pixel >> 16) & 0xff); // pixel red
pArr[1] = (BYTE) ((pixel >> 8 ) & 0xff); // pixel green
pArr[0] = (BYTE) ((pixel ) & 0xff); // pixel blue
pArr += 4;
}
pArr += nOffset;
}
bmp->UnlockBits(&bmData);
return (bmp);
}
Hope it is enough
|
|
|
|
|
Hi ARJ,
Thnaks for your code.Actually,the code throws an exception at
Bitmap *bmp = bit.Clone(0, 0, bit.GetWidth(), bit.GetHeight(),PixelFormat32bppARGB);
in getting the values of widht and height in GdiPlusBitmap.h
The exception is
Unhandled exception at 0x00411bc1 in test.exe: 0xC0000005: Access violation reading location 0x00000004.
I am not sure why it occurs. Could you please advice me on this?
|
|
|
|
|
Hello,
I am trying to capture a window from an external App Example Calculator.
I am able to get the handle of the window. If the user opens a second instance, I am able to get that handle too using EnumWindows.
Which means I have 2 handles for the 2 calculators. Short of using the Handle is there anything else that I could use to differenciate the 2 windows. I can't use the window title since they are both the same.
Reason for asking:
I know the handle gets reused, but is it possible for the handle to change after the window has been created or does it stay the same after creation? Yes, if I close the window, I know I will not get the same handle.
Is it possible that If the user minimizes the window and activates it again, we get a new handle?
If the handle changes during the lifetime of the window whats the best way of keeping track of that window?
I have created a thread and am using the same function to handle capturing data from the 2 windows by passing the handle as a parameter. However, I can only get the data from one of the windows, or am I better off creating multiple threads which is what I was avoiding?
Could someone please help.
|
|
|
|
|
FISH786 wrote: but is it possible for the handle to change after the window has been created or does it stay the same after creation
AFAIK, a window handle doesn't change over the lifetime of a window.
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Thanks again.
which is what I thought but wanted to be sure.
I guess back to debugging and find out why I can't get the data from the second window.
However, I should be able to use the same thread and pass the handle as a parameter? or am I better off creating multiple threads and dedicate each thread to a window for the lifetime of that particular window?
|
|
|
|
|
What is the reason of error message:
error C2036: 'void *' : unknown size
This was a result of compilation of such a code snippet:
void ** c=malloc(20);
int i=1;
c[i] = c[i-1]+1;
(Forget uninitialized block of memory c )
I'd expect that size of any pointer is known.
|
|
|
|
|
The pointer points to something which is not known (otherwise, you would have used int* for instance). Thus, when you are accessing it as an array, the compiler doesn't know how much offset he has to apply to the address to access the following element (because he doesn't know the size of an element). If you want to manipulate bytes, I suggest that you use an array of unsigned char instead.
|
|
|
|
|
I dont think it is a good practice to allocate a viod pointer. Void pointer is not introduded so as to allocate and use, rather its use is in holding data. Since Void can hold any type of data. You cannot able to allocate the exact length. Thats why complier doesnot allow you to do so.
So it better to allocate for some data types.
|
|
|
|
|
c[i-1] is a void *
c[i-1] + 1 you're trying to increment to the next "void" object, but void has no size
change the line of code
void** c = malloc(20)
to
int** c = malloc(20)
and you'll see that it compiles.
|
|
|
|