Icon to Image problem - finally solved.

Blitz3D Forums/Blitz3D Programming/Icon to Image problem - finally solved.

John Blackledge(Posted 2013) [#1]
[Finally solved - see last post]

I'm using some earlier code from
http://www.blitzbasic.co.nz/Community/posts.php?topic=100754#1192838
to get an icon into an image.
Why?
Because apiDrawIcon() will not draw to a Blitz buffer....
and will not Flip into view
....so must be on a different surface.
So the only way is to read the icon into a Blitz image

But the colours come out wrong.
Can anyone help, who has done this before?

Here's the core code:



Rroff(Posted 2013) [#2]
Is the format of the data type returning the color value from getpixel the same as b3d uses with writepixel ?


John Blackledge(Posted 2013) [#3]
Quote from MSDN user:
'Note that it is possible to set a pixel using SetPixel and then get back a slightly different colour when you use GetPixel on the same pixel. Whether or not this happens depends on the device context and its capabilities and colour depth properties. '

So - the problem is defined.
But what is the answer?

This is infuriating since both
api_DrawIcon( hMemDC, 0, 0, Tbar\hIcon )
and
WinBlitz3D's WB3D_DrawIcon()
produce an image with the correct colours in a window,
but Blitz's GrabImage command simply cannot 'see' the image to grab, and merely grabs the background.
That's why I said the underlying MS drawicon code must be displaying to a different layer/buffer.

Can't I just use WB3D_DrawIcon()?
No, because SetBuffer BackBuffer() and Flip have absolutely no effect on an image which 'isn't there'.

I'm still open to ideas.
If _I'm_ being an idiot (it won't be the first time) I don't mind.


Kryzon(Posted 2013) [#4]
When you're using DrawIcon, you're specifying the DC (the "place" to draw the image) as a new place that you've created. It's the hMemDC.

There are a few things we can test.
Perhaps it could work if instead of this new DC, you would supply the DC for the Blitz window. So you have this:
Graphics( 800, 600, 32, 2 ) ;Create a graphics mode with 32 bits. Not sure if this influences the result.

iconWidth = api_GetSystemMetrics( SM_CXICON )
iconHeight = api_GetSystemMetrics( SM_CYICON )

szExeName$ = "E:\Blitz3D\Blitz3D.exe" + Chr$( 0 )
Tbar\hIcon = api_ExtractIcon( hInst, szExeName$, 0 )

;Retrieve the Blitz window DC.
hDC = api_GetDC( Tbar\hWnd )

;Draw the icon on the Blitz window.
api_DrawIcon( hDC, 0, 0, Tbar\hIcon )

;Copy the icon into an image. I'm not sure if the image is on the back or the front buffer.
Global blitzImage = CreateImage( iconWidth, iconHeight )
CopyRect( 0, 0, iconWidth, iconHeight, 0, 0, BackBuffer(), ImageBuffer( blitzImage ) )

;Do what you want with 'blitzImage.'
;[...]

;No need to clean any object.

End



John Blackledge(Posted 2013) [#5]
Thanks, Kryzon, but the icon is NOT being drawn on the back buffer (that's why I suggested that it must be going to a different layer), as proven when I Flip it does not appear. So I can't get it from there.

So CopyRect( 0, 0, iconWidth, iconHeight, 0, 0, BackBuffer(), ImageBuffer( blitzImage ) )
will only produce a black rectangle.

(It DID draw to the hDC ok, and was then copied to the Blitz image, but as I said, wrong colours.)


Kryzon(Posted 2013) [#6]
Try LockBuffer( BackBuffer() ), DrawIcon(), UnlockBuffer( BackBuffer() ), and then CopyRect() ect.

Also, try to adapt this to your intentions: http://www.blitzbasic.com/codearcs/codearcs.php?code=2682


John Blackledge(Posted 2013) [#7]
Thanks, tried it, but sorry Kryzon.
Neither
api_DrawIcon()
nor
WinBlitz3D's WB3D_DrawIcon()
will draw onto _any_kind_ of Blitz buffer.

These Api calls seem to only be capable of drawing onto a Windows surface.
But they _will_ draw directly onto the screen, which gives me an idea for combining DrawIcon with Blitz (rect etc) graphics..........


John Blackledge(Posted 2013) [#8]
For anybody who's been following this nonsense, while I've been playing with buffers I've found out the most bizarre thing about Blitz....

Run this program:

Graphics 400,300,32,2
Color 128,128,128
Rect 10,10,380,280,1
While Not KeyHit(1)
Wend
End

It doesn't need Back or FrontBuffer or Flip!
It _always_ redraws the rect!
Even if you cover and uncover the window.
As if Blitz has a hidden buffer equivalent to the Windows WM_PAINT mechanism.


Nexinarus(Posted 2014) [#9]
I found this out on the first day I used blitz. Its nothing really new. Its no different then print "string", or text x,y,"string" without setting up the graphics mode.

The reason why i never mentioned anything about it, I thought everyone new about that.

I used to code in QuickBasic. You have to set the graphics mode to pixel drawings and crap. if you dont, you just type crap in DOS.

So in my opinion its like that. It just has the drawing features as a bonus.
To me, its no big deal.

Well thats how i see it. Personally, I think its kinda cool.


John Blackledge(Posted 2014) [#10]
Finally solved the colour problem!
Microsoft store icon colours in reverse, Blue-Geen-Red!
Graphics3D 640,480,32

Const SM_CXICON = 11, SM_CYICON = 12
iconWidth = api_GetSystemMetrics(SM_CXICON)
iconHeight = api_GetSystemMetrics(SM_CYICON)

szExeName$ = "E:\Blitz3D\Blitz3D.exe"
hIcon = api_ExtractIcon(0, szExeName$, 0)

; Get a Windows drawing surface
hDC = api_GetDC(0)
; Get a compatible that we can use.
hMemDC= api_CreateCompatibleDC(hDC)

; Create a blank Windows bitmap
hMemBmp= api_CreateCompatibleBitmap( hDC, iconWidth, iconHeight )

; Draw the icon on the bitmap.
api_SelectObject(hMemDC, hMemBmp)
api_DrawIcon(hMemDC, 0, 0, hIcon)

; Create a blank Blitz image, and set it as the drawing buffer.
blitzImage = CreateImage( iconWidth, iconHeight )
SetBuffer ImageBuffer(blitzImage)

; Copy the icon pixels from the Windows bitmap in the Blitz image
For x = 0 To iconWidth-1
	For y = 0 To iconHeight-1
		; This was why my colours were originally wrong.
		; M$ store icon pixels in Blue-Green-Red format, not Red-Blue-Green!!!!
		; ... so swap them.
		bgr = api_GetPixel(hMemDC, x, y)
		b = bgr Shr 16 And %11111111
		g = bgr Shr 8 And %11111111
		r = bgr And %11111111
		rgb = (r Shl 16) Or (g Shl 8) Or b
		WritePixel(x, y, rgb)
	Next
Next

; Reset the drawing buffer back to Backbuffer for normal use.
SetBuffer BackBuffer()
While Not KeyHit(1)
	DrawImage blitzImage,0,0
	Flip
Wend

;Clean all memory objects.
api_ReleaseDC(0, hDC)
api_DeleteDC(hMemDC)
api_DeleteObject(hMemBMP)
End




Nexinarus(Posted 2014) [#11]
I found out that Icons are so similar to BMPs its not even funny. I made a Icon Editor years ago in QuickBasic with a buddy of mine. He figured out all the icon stuff. When he showed it to me, it was so freaky how similar BMPs and ICOs were.