News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

png to bitmap

Started by donkey, January 04, 2009, 08:37:10 AM

Previous topic - Next topic

donkey

After reading the first 50 or so pages of the libpng manual I gave up. I simply need to convert a png image to a bitmap image, I am not interested in learning to use libpng which comes with the most rambling, long winded documentation I have ever had the misfortune to encounter. Does anyone know of a library or routine that will convert a png image in memory to a bitmap ?
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

rags

God made Man, but the monkey applied the glue -DEVO

MichaelW

I think GDI+ might be able to do that, depending on what you mean by a png image in memory.
eschew obfuscation

drhowarddrfine


donkey

Hi Rags,

I should have checked Thomas' site, thanks.

Hi Michael,

I will have a look at the GDI+ flat API, the PNG is embedded in a file, I have to extract it to a buffer then display it.

Hi Doc,

Thanks, I will look at the C source code. Problem is that GoAsm, though it supports libs does not support lib chains where one library calls a function in another library. I can usually find a way around it but it's a chore that I hoped to avoid.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Vortex

Hi donkey,

The attached example converts a PNG in memory to bitmap with GDI+

The steps of the process :

- The PNG in memory is written to a stream
- The image in the stream is read by GDI+ and saved to another stream as BMP.
- The stream is written to disc.

A similar example is available from here

[attachment deleted by admin]

donkey

Hi Vortex,

Thanks, I already have my solution, simple and direct...

PNG2HBMP FRAME pMemory,dwSize
LOCAL pStream :D
LOCAL pGlobal :D
LOCAL pBitmap :D
LOCAL hBitmap :D

mov D[pStream],NULL

invoke CoTaskMemAlloc, [dwSize]
mov [pGlobal],eax
invoke MemCopy,[pMemory],[pGlobal],[dwSize]

invoke CreateStreamOnHGlobal, [pGlobal], TRUE, ADDR pStream
test eax,eax
jz >
; no interface
invoke GlobalFree,[pGlobal]
xor eax,eax
ret
:
invoke gdiplus.dll:GdipCreateBitmapFromStream,[pStream],offset pBitmap

invoke gdiplus.dll:GdipCreateHBITMAPFromBitmap,[pBitmap],offset hBitmap,0FFFFFFFFh

CoInvoke(pStream,IPicture.IUnknown.Release)
invoke GlobalFree,[pGlobal]
mov eax,[hBitmap]

RET
ENDF


Just have to do a bitof research on how to release the gdiplus bitmap object, I assume its GdipDisposeImage
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

donkey

Actually it works amazingly well, I had conversion routines for a bunch of different image types that can all be replaced by the one call now. I have yet to find one that it doesn't load and convert to a bitmap handle. BTW, I think

invoke gdiplus.dll:GdipDisposeImage,[pBitmap]

Releases the bitmap object.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Vortex

Hi donkey,

Nice work.

invoke GlobalFree,[pGlobal]

This is a double free here. No need for this line.

From MSDN :

Quote
fDeleteOnRelease [in]

A value that indicates whether the underlying handle for this stream object should be automatically freed when the stream object is released. If set to FALSE, the caller must free the hGlobal after the final release. If set to TRUE, the final release will automatically free the hGlobal parameter.

invoke CreateStreamOnHGlobal, [pGlobal], TRUE, ADDR pStream

http://msdn.microsoft.com/en-us/library/aa378980(VS.85).aspx

donkey

#9
Hi Vortex,

Thanks, just a reflex action freeing memory. GlobalSize shows 0 after the release so you're right it is freed and I have removed the call. A quick check shows GDI+ is redistributable down to Win98 so compatibility is there although I only really write code to Win2K+ anymore it's nice to know.

ConvertImage FRAME pMemory,dwSize
LOCAL pStream :D
LOCAL pGlobal :D
LOCAL pBitmap :D
LOCAL hBitmap :D

mov D[pStream],NULL

invoke CoTaskMemAlloc, [dwSize]
mov [pGlobal],eax
invoke MemCopy,[pMemory],[pGlobal],[dwSize]

invoke CreateStreamOnHGlobal, [pGlobal], TRUE, ADDR pStream
test eax,eax
jz >
; no interface
invoke CoTaskMemFree,[pGlobal]
xor eax,eax
ret
:
invoke GdipCreateBitmapFromStream,[pStream],offset pBitmap

invoke GdipCreateHBITMAPFromBitmap,[pBitmap],offset hBitmap,0FFFFFFFFh

invoke GdipDisposeImage,[pBitmap]

CoInvoke(pStream,IStream.IUnknown.Release)

mov eax,[hBitmap]

RET
ENDF
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Vortex

Hi donkey,

Another test : I created the stream without copying the data block. Setting the size of stream worked for me.

invoke  CreateStreamOnHGlobal,ADDR pPNG,TRUE,ADDR pPNGstream ; pPNG is equal to pMemory in the GoAsm code

mov     eax,pPNGstream
push    0
push    PNG_FILE_SIZE ; equal to dwSize in the GoAsm code
push    eax
mov     eax,DWORD PTR [eax]
call    IStream.SetSize[eax]


If you have the time, could you try this method in your procedure? I would like to know if this approach is correct.

In your code :

invoke CreateStreamOnHGlobal, [pGlobal], TRUE, ADDR pStream

To test the method, you need to replace pGlobal with pMemory and set the size of the stream with SetSize.

Thanks.

donkey

Hi Vortex,

That will fail in my case, pMemory points to a location in a memory mapped file and that is not a Global memory object so it is not compatible with CreateStreamOnHGlobal. It is more general purpose to simply make sure that the memory object matches the specifications for the API.

edit:
A quick check (because I was curious) shows that yes it does fail with virtual memory objects (like mapped files), SetSize has no effect since no interface was returned.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Mark Jones

Curious, are the graphics in question well-suited to PNG? i.e., low-color lineart or raster/pixel art? Since PNG is a lossless compression, dithering and/or reducing the color count (of high-color images such as photos and renders) prior to saving as .png usually results in a drastically reduced filesize, with little visible artifacting.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

donkey

Quote from: Mark Jones on January 05, 2009, 03:34:32 AM
Curious, are the graphics in question well-suited to PNG? i.e., low-color lineart or raster/pixel art? Since PNG is a lossless compression, dithering and/or reducing the color count (of high-color images such as photos and renders) prior to saving as .png usually results in a drastically reduced filesize, with little visible artifacting.

Not my graphics, you can find what I needed them for here...

http://www.masm32.com/board/index.php?topic=10610.0

Just some fun with MP3 files, most of what I buy from Apple iTunes has PNG attachments so they represent the bulk of my MP3 collection.
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

Vortex

Hi donkey,

Thanks for the test and info. Yes, a convertion routine should take in account virtual memory objects.