MagickWand writes a bitmap incompatible with Win32 LoadImage
Posted: 2013-02-03T01:09:17-07:00
I'm back with another question and some hard to understand (to me) behavior of the ImageMagick API ...
I'm using some code from Microsoft's online tutorials (referenced and copied below) to load a bitmap file and then subsequently display it in a win32 GUI program with BitBlt(). It works perfectly with bitmap files from any source, except those written by MagickWand.
Test program and output is below. Image files follow that. This is what I did:
1) Using MS Paint, I made a simple 100x50 image with a squiggly line.
2) Saved it as a 24-bit bitmap, named bitmap_made_by_ms_paint.bmp
3) Then saved the same image as a jpeg, named jpeg_made_by_ms_paint.jpg
4) Run test program.
4a) The program first tests the MS-provided LoadImage() routine to load bitmap_made_by_ms_paint.bmp - success.
4b) The program then uses MagickWand to read jpeg_made_by_ms_paint.jpg and immediately writes the image to bitmap_made_by_magick_wand.bmp - success.
4c) The program then tests the MS-provided LoadImage() routine to load bitmap_made_by_magick_wand.bmp - fails.
5) Swear at computer.
Other image editing programs (Paint, Gimp, Windows Explorer, Firefox, IE) can open all three image files. They look identical.
Where's the problem? Does MagickWand write a bitmap in some non-standard format? Is Microsoft's LoadImage (and their example wrapper LoadBitmapFromBMPFile) buggy? Am I doing something else wrong?
Thank you.
Below are the actual image files made by MS Paint and MagickWand:
bitmap_made_by_ms_paint.bmp
jpeg_made_by_ms_paint.jpg
bitmap_made_by_magick_wand.bmp
Thank you.
I'm using some code from Microsoft's online tutorials (referenced and copied below) to load a bitmap file and then subsequently display it in a win32 GUI program with BitBlt(). It works perfectly with bitmap files from any source, except those written by MagickWand.
Test program and output is below. Image files follow that. This is what I did:
1) Using MS Paint, I made a simple 100x50 image with a squiggly line.
2) Saved it as a 24-bit bitmap, named bitmap_made_by_ms_paint.bmp
3) Then saved the same image as a jpeg, named jpeg_made_by_ms_paint.jpg
4) Run test program.
4a) The program first tests the MS-provided LoadImage() routine to load bitmap_made_by_ms_paint.bmp - success.
4b) The program then uses MagickWand to read jpeg_made_by_ms_paint.jpg and immediately writes the image to bitmap_made_by_magick_wand.bmp - success.
4c) The program then tests the MS-provided LoadImage() routine to load bitmap_made_by_magick_wand.bmp - fails.
5) Swear at computer.
Other image editing programs (Paint, Gimp, Windows Explorer, Firefox, IE) can open all three image files. They look identical.
Where's the problem? Does MagickWand write a bitmap in some non-standard format? Is Microsoft's LoadImage (and their example wrapper LoadBitmapFromBMPFile) buggy? Am I doing something else wrong?
Thank you.
Code: Select all
pgg@g550 ~/test
$ ls -l
total 80
-rwxr-xr-x 1 pgg None 15054 Feb 3 12:05 bitmap_made_by_ms_paint.bmp
drwxr-xr-x+ 1 pgg None 0 Jan 30 22:41 include
-rwxr-xr-x 1 pgg None 2653 Feb 3 12:05 jpeg_made_by_ms_paint.jpg
-rwxr-xr-x 1 pgg None 3419 Feb 3 12:16 test.c
-rwxr-xr-x 1 pgg None 57120 Feb 3 12:16 test.exe
pgg@g550 ~/test
$ cat test.c
#include <windows.h>
#include <wchar.h>
#include <stdio.h>
#include <string.h>
#include <wand/magick_wand.h>
// From MS Support Article 158898 http://support.microsoft.com/kb/158898
BOOL LoadBitmapFromBMPFile (LPTSTR szFileName, HBITMAP *phBitmap, HPALETTE *phPalette )
{
BITMAP bm;
*phBitmap = NULL;
*phPalette = NULL;
// Load image into a DIBSection
*phBitmap = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
if( *phBitmap == NULL ) {
fprintf( stderr, "LoadImage() failed to load image file.\n" );
return FALSE;
}
// Get color depth of the DIBSection
GetObject( *phBitmap, sizeof(BITMAP), &bm );
// If the DIBSection is 256 color or less, it has a color table
if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 )
{
HDC hMemDC;
HBITMAP hOldBitmap;
RGBQUAD rgb[256];
LPLOGPALETTE pLogPal;
WORD i;
// Create a memory DC and select the DIBSection into it
hMemDC = CreateCompatibleDC( NULL );
hOldBitmap = (HBITMAP)SelectObject( hMemDC, *phBitmap );
// Get the DIBSection's color table
GetDIBColorTable( hMemDC, 0, 256, rgb );
// Create a palette from the color table
pLogPal = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + (256*sizeof(PALETTEENTRY)) );
pLogPal->palVersion = 0x300;
pLogPal->palNumEntries = 256;
for( i = 0; i < 256; i++ ) {
pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
pLogPal->palPalEntry[i].peFlags = 0;
}
*phPalette = CreatePalette( pLogPal );
// Clean up
free( pLogPal );
SelectObject( hMemDC, hOldBitmap );
DeleteDC( hMemDC );
} else { // it has no color table, so use a halftone palette
HDC hRefDC;
hRefDC = GetDC( NULL );
*phPalette = CreateHalftonePalette( hRefDC );
ReleaseDC( NULL, hRefDC );
}
return TRUE;
}
int main() {
MagickWand *mw = NULL;
HBITMAP hBitmap;
HPALETTE hPalette;
fprintf( stderr, "** Checking LoadImage() with bitmap made with MS paint **\n" );
if( LoadBitmapFromBMPFile( "bitmap_made_by_ms_paint.bmp", &hBitmap, &hPalette ) )
fprintf( stderr, "LoadBitMapFromBMPFile successfully loaded 'bitmap_made_by_ms_paint.bmp'\n" );
else
fprintf( stderr, "LoadBitMapFromBMPFile failed to load 'bitmap_made_by_ms_paint.bmp'\n" );
fprintf( stderr, "\n\n** Using MagickWand to convert bitmap to jpeg **\n" );
MagickWandGenesis();
mw = NewMagickWand();
MagickReadImage( mw, "jpeg_made_by_ms_paint.jpg" );
MagickWriteImage( mw, "bitmap_made_by_magick_wand.bmp" );
DestroyMagickWand(mw);
MagickWandTerminus();
fprintf( stderr, "\n\n** Checking LoadImage() with bitmap made with Magick Wand**\n" );
if( LoadBitmapFromBMPFile( "bitmap_made_by_magick_wand.bmp", &hBitmap, &hPalette ) )
fprintf( stderr, "LoadBitMapFromBMPFile successfully loaded 'bitmap_made_by_magick_wand.bmp'\n" );
else
fprintf( stderr, "LoadBitMapFromBMPFile failed to load 'bitmap_made_by_magick_wand.bmp'\n" );
return 0;
}
/*
gcc test.c -o test -lMagickWand-Q16 -lgdi32 -L/home/pgg/ImageMagick-6.8.1/lib -I/home/pgg/ImageMagick-6.8.1/include/ImageMagick -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
*/
pgg@g550 ~/test
$ gcc test.c -o test -lMagickWand-Q16 -lgdi32 -L/home/pgg/ImageMagick-6.8.1/lib -I/home/pgg/ImageMagick-6.8.1/include/ImageMagick -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
pgg@g550 ~/test
$ ./test.exe
** Checking LoadImage() with bitmap made with MS paint **
LoadBitMapFromBMPFile successfully loaded 'bitmap_made_by_ms_paint.bmp'
** Using MagickWand to convert bitmap to jpeg **
** Checking LoadImage() with bitmap made with Magick Wand**
LoadImage() failed to load image file.
LoadBitMapFromBMPFile failed to load 'bitmap_made_by_magick_wand.bmp'
pgg@g550 ~/test
$ ls -l
total 96
-rw-r--r-- 1 pgg None 15138 Feb 3 12:17 bitmap_made_by_magick_wand.bmp
-rwxr-xr-x 1 pgg None 15054 Feb 3 12:05 bitmap_made_by_ms_paint.bmp
drwxr-xr-x+ 1 pgg None 0 Jan 30 22:41 include
-rwxr-xr-x 1 pgg None 2653 Feb 3 12:05 jpeg_made_by_ms_paint.jpg
-rwxr-xr-x 1 pgg None 3419 Feb 3 12:16 test.c
-rwxr-xr-x 1 pgg None 57120 Feb 3 12:17 test.exe
bitmap_made_by_ms_paint.bmp
jpeg_made_by_ms_paint.jpg
bitmap_made_by_magick_wand.bmp
Thank you.