How to load Windows DIB in Magick++? [SOLVED]
-
- Posts: 36
- Joined: 2010-02-21T18:02:40-07:00
- Authentication code: 8675308
How to load Windows DIB in Magick++? [SOLVED]
Hi,
I am new to Windows programming and was given a HANDLE to a Windows DIB image and a BITMAPINFOHEADER structure.
How can I load this DIB image into an ImageMagick image using Magick++ on Visual C++ 2008 in Windows Vista (using less memory if possible)?
Thanks in advance!
I am new to Windows programming and was given a HANDLE to a Windows DIB image and a BITMAPINFOHEADER structure.
How can I load this DIB image into an ImageMagick image using Magick++ on Visual C++ 2008 in Windows Vista (using less memory if possible)?
Thanks in advance!
Last edited by anotherprogrammer123 on 2010-08-20T13:35:37-07:00, edited 1 time in total.
-
- Posts: 36
- Joined: 2010-02-21T18:02:40-07:00
- Authentication code: 8675308
Re: How to load Windows DIB?
*bump*
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: How to load Windows DIB?
looks like none of the users know about this. so try posting to the developers forum
Re: How to load Windows DIB?
I am fairly sure the dib and bmp image format are the same thing. VS recognizes bmp format. Not sure on dib. Try changing the type to bmp and load it into paint to be sure.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: How to load Windows DIB?
yes, they can be the same. see http://en.wikipedia.org/wiki/BMP_file_format
so just load it with .bmp into IM just like any other image format.
I am not a Windows or API programmer (I script command line IM on Mac), so I cannot help further.
so just load it with .bmp into IM just like any other image format.
I am not a Windows or API programmer (I script command line IM on Mac), so I cannot help further.
-
- Posts: 36
- Joined: 2010-02-21T18:02:40-07:00
- Authentication code: 8675308
Re: How to load Windows DIB?
Thanks for the responses, but ImageMagick gives me a "resource limit" error when I try to load the handle into a BLOB.
My machine had 2GB of RAM so something is wrong. If no one knows, I can try posting in the developer's forum.
My machine had 2GB of RAM so something is wrong. If no one knows, I can try posting in the developer's forum.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: How to load Windows DIB?
try loading a known good image and see if you are using the right API calls. perhaps it is not the image, but your code.
-
- Posts: 36
- Joined: 2010-02-21T18:02:40-07:00
- Authentication code: 8675308
Re: How to load Windows DIB?
Hi guys,
I am still totally confused on this.
First, I define this function:
Next, I run this code:
Which gives me access violation errors while img.read() is being run.
So, I think that the BITMAPINFOHEADER and pixels need to be contiguous and loaded together, so I do this:
This time, no errors happen, but twain.bmp is an empty file!
Can anybody help me out?
Thank you in advance!
I am still totally confused on this.
First, I define this function:
Code: Select all
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; //our file pointer
BITMAPFILEHEADER bitmapFileHeader; //our bitmap file header
unsigned char *bitmapImage; //store image data
int imageIdx=0; //image index counter
unsigned char tempRGB; //our swap variable
//open filename in read binary mode
filePtr = fopen(filename,"rb");
if (filePtr == NULL)
return NULL;
//read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER),1,filePtr);
//verify that this is a bmp file by check bitmap id
if (bitmapFileHeader.bfType !=0x4D42)
{
fclose(filePtr);
return NULL;
}
//read the bitmap info header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER),1,filePtr);
//move file point to the begging of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
//allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
//verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
//read in the bitmap image data
fread(bitmapImage,bitmapInfoHeader->biSizeImage,1,filePtr);
//make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
//swap the r and b values to get RGB (bitmap is BGR)
for (imageIdx = 0;imageIdx < bitmapInfoHeader->biSizeImage;imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
//close file and return bitmap image data
fclose(filePtr);
return bitmapImage;
}
Next, I run this code:
Code: Select all
BITMAPINFOHEADER* header = new BITMAPINFOHEADER;
unsigned char* pixels = LoadBitmapFile("D:/img.bmp", header);
Magick::Image img;
img.read(Magick::Blob(pixels, header->biSizeImage));
img.write("D:/twain.bmp");
So, I think that the BITMAPINFOHEADER and pixels need to be contiguous and loaded together, so I do this:
Code: Select all
unsigned char* fullImg = (unsigned char*)malloc(sizeof(BITMAPINFOHEADER) + header->biSizeImage);
memcpy((void*)fullImg, (void*)header, sizeof(BITMAPINFOHEADER));
memcpy((void*)(fullImg + sizeof(BITMAPINFOHEADER)), pixels, header->biSizeImage);
unsigned char* pixelscpy = fullImg + sizeof(BITMAPINFOHEADER);
;copy to imagemagick
Magick::Image img;
img.read(Magick::Blob(fullImg, sizeof(BITMAPINFOHEADER) + header->biSizeImage));
img.write("D:/twain.bmp");
Can anybody help me out?
Thank you in advance!
-
- Posts: 1015
- Joined: 2005-03-21T21:16:57-07:00
Re: How to load Windows DIB?
This is an edited version of a C function I wrote to save a screen capture image (which is received as a handle to a bitmap).
Perhaps you can massage this to do what you need.
Pete
Perhaps you can massage this to do what you need.
Pete
Code: Select all
#include <windows.h>
#include <wand/magick_wand.h>
void SaveBitmap(char *filename,HBITMAP hBitmap)
{
HDC hdc=NULL;
unsigned char *pBuf=NULL;
BITMAPINFO bmp_inf;
do {
hdc = GetDC(NULL);
ZeroMemory(&bmp_inf,sizeof(BITMAPINFO));
bmp_inf.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
// Passing a NULL gets just the header info containing
// the width and height which are used to compute the
// size required for a malloc
GetDIBits(hdc,hBitmap,0,0,NULL,&bmp_inf,DIB_RGB_COLORS);
if(bmp_inf.bmiHeader.biSizeImage <= 0)
bmp_inf.bmiHeader.biSizeImage=bmp_inf.bmiHeader.biWidth*abs(bmp_inf.bmiHeader.biHeight)*(bmp_inf.bmiHeader.biBitCount+7)/8;
if((pBuf = malloc(bmp_inf.bmiHeader.biSizeImage+sizeof(BITMAPINFOHEADER))) == NULL)
{
MessageBox( NULL, "Unable to Allocate Bitmap Memory", "Error", MB_OK|MB_ICONERROR);
break;
}
bmp_inf.bmiHeader.biCompression=BI_RGB;
// Now get the whole image
GetDIBits(hdc,hBitmap,0,bmp_inf.bmiHeader.biHeight,pBuf+sizeof(BITMAPINFOHEADER), &bmp_inf, DIB_RGB_COLORS);
{
int i;
unsigned char *p,*q;
MagickWand *wand;
// Copy the separate bmp_inf into the DIB info header which is
// now contiguous with the image data in pBuf
p = (unsigned char *)&bmp_inf;
q = pBuf;
for(i=0;i<sizeof(BITMAPINFOHEADER);i++)*q++ = *p++;
MagickWandGenesis();
wand = NewMagickWand();
MagickReadImageBlob(wand,pBuf,bmp_inf.bmiHeader.biSizeImage+sizeof(BITMAPINFOHEADER));
// Force it OFF - shouldn't need this but IM's DIB coder
// forces matte on if the bit depth is 32 (which it is with a screencap).
MagickSetImageMatte(wand,MagickFalse);
// Write the file
MagickWriteImage(wand,filename);
wand = DestroyMagickWand(wand);
MagickWandTerminus();
}
} while(0);
if(hdc) ReleaseDC(NULL,hdc);
if(pBuf) free(pBuf);
}
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
See my message in this topic for a link to a zip of all the files.
-
- Posts: 36
- Joined: 2010-02-21T18:02:40-07:00
- Authentication code: 8675308
Re: How to load Windows DIB?
Thanks so much guys.
I figured out the problem! I think I did pointer arithmetic wrong. I was also not taking into account the RGBQUAD structures.
Here is the new function. Hope it helps future searches out:
It is working now!
Lesson: don't forget about the 2^biBitCount RGBQUAD structures.
Thanks again everyone.
I figured out the problem! I think I did pointer arithmetic wrong. I was also not taking into account the RGBQUAD structures.
Here is the new function. Hope it helps future searches out:
Code: Select all
int handleToImage(HANDLE bitmap, MYIMAGE &image) const
{
//Get the header of the bitmap (stored at the start of the handle's address)
BITMAPINFOHEADER* header = (BITMAPINFOHEADER*)GlobalLock(bitmap);
//We will store the bitmap into a magick++ image and transfer this to the image
Magick::Image magickImg;
//calculates the total number of bytes stored in 'header' (the structure is: BITMAPINFOHEADER, one RGBQUAD structure for each possible color, pixel data)
int length = header->biSize + (00000001 << header->biBitCount)*sizeof(RGBQUAD) + header->biSizeImage; //note that if we are working with uncompressed bitmaps (32 bits), header->biSizeImage might be 0
//read the bitmap into a magick++ using a BLOB
try { magickImg.read(Magick::Blob(header, length)); }
catch (...) { return 1; }
//Load the magick++ object into the image
if (image.load(magickImg) != 0)
{
return 1; //failed reading
}
//Free the bitmap handle now that it is loaded into the image
GlobalUnlock(bitmap); GlobalFree(bitmap);
return 0;
}
Lesson: don't forget about the 2^biBitCount RGBQUAD structures.
Thanks again everyone.