Page 2 of 3

Posted: Mon Sep 26, 2005 7:18 pm
by Joakim Christiansen
This don't stop after a while like Fred's did:
I got it from here.

Code: Select all

Procedure DrawTransparentImage(DC, ImageID, x, y, TransparentColor) 
  Protected ImageList, BM.BITMAP 
  
  GetObject_(ImageID, SizeOf(BITMAP), BM.BITMAP) 
  ImageID = CopyImage_(ImageID, #IMAGE_BITMAP, BM\bmWidth, BM\bmHeight, 0) 
  ImageList = ImageList_Create_(BM\bmWidth, BM\bmHeight, #ILC_COLORDDB|#ILC_MASK, 1, 0) 
  ImageList_AddMasked_(ImageList, ImageID, TransparentColor) 
  ImageList_Draw_(ImageList, 0, DC, x, y, #ILD_TRANSPARENT) 
  ImageList_Destroy_(ImageList) 
  DeleteObject_(ImageID) 
EndProcedure 

Enumeration ;Images 
  #Image1 
  #Image2 
EndEnumeration 

CreateImage(#Image1,32,32) 
CreateImage(#Image2,32,32) 

UseImage(#Image1) 
StartDrawing(ImageOutput()) 
  Box(0,0,32,32,RGB(255,0,0)) 
  Box(5,5,22,22,RGB(0,0,0)) 
  StopDrawing() 

UseImage(#Image2) 
StartDrawing(ImageOutput()) 
  Box(0,0,32,32,RGB(0,0,255)) 
  Box(5,5,22,22,RGB(0,0,0)) 
  StopDrawing() 

OpenWindow(0,0,0,200,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"DrawTransparentImage()") 

Repeat 
  Event = WindowEvent() 
  
  X = Random(168) 
  Y = Random(168) 
  Image = Random(#Image2) 
  
  DC = StartDrawing(WindowOutput()) 
    DrawTransparentimage(DC,UseImage(Image),X,Y,RGB(0,0,0)) 
  StopDrawing() 
Until Event = #PB_Event_CloseWindow

Posted: Tue Sep 27, 2005 4:34 am
by Intrigued
netmaestro wrote:Beautiful! Thanks Fred! I think programmers would switch to PB in droves if they knew we were being spoiled like this.

@intrigued: Works perfectly here. Did you download the images and make sure they were available to your program when you ran it?
Thanks netmaestro. That was the deal. I flew right over such in the commented out area of the code chunk.

Posted: Tue Sep 27, 2005 7:47 am
by netmaestro
This don't crash after a while like Fred's did:
OK, that's great. But after a couple hours turning it over in my mind I can't see why Fred's code should have a problem. It is all API calls and he is releasing everything he's creating. So... ??? :?

Posted: Tue Sep 27, 2005 10:44 am
by Brice Manuel
OK, that's great. But after a couple hours turning it over in my mind I can't see why Fred's code should have a problem. It is all API calls and he is releasing everything he's creating. So... ???
Fred's worked fine on my nine test systems here when I was testing it yesterday.

Posted: Tue Sep 27, 2005 2:07 pm
by Joakim Christiansen
netmaestro wrote:
This don't crash after a while like Fred's did:
OK, that's great. But after a couple hours turning it over in my mind I can't see why Fred's code should have a problem. It is all API calls and he is releasing everything he's creating. So... ??? :?
I don't know why it crash either, it's very weird.
This is the code that make it crash on my computer, does it crash on yours?:
Edit:
When I said crash I actually meant that is stoped working, it dind't crash the program or something like that... Sorry about that.

Code: Select all

Procedure DrawTransparentImage(DC, Bitmap, x, y, Width, Height, TransparentColor) 

    ; First, create some DC's. These are our gateways To associated 
    ; bitmaps in RAM 
    maskDC = CreateCompatibleDC_(DC) 
    tempDC = CreateCompatibleDC_(DC) 
    
    SourceDC = CreateCompatibleDC_(DC) 
    SelectObject_(SourceDC, Bitmap) 
    

    ; Then, we need the bitmaps. Note that we create a monochrome 
    ; bitmap here! 
    ; This is a trick we use For creating a mask fast enough. 
    hMaskBmp = CreateBitmap_(Width, Height, 1, 1, 0) 
    hTempBmp = CreateCompatibleBitmap_(DC, Width, Height) 

    ; Then we can assign the bitmaps to the DCs 
    ; 
    hMaskBmp = SelectObject_(maskDC, hMaskBmp) 
    hTempBmp = SelectObject_(tempDC, hTempBmp) 

    ; Now we can create a mask. First, we set the background color 
    ; To the transparent color; then we copy the image into the 
    ; monochrome bitmap. 
    ; When we are done, we reset the background color of the 
    ; original source. 
    TransparentColor= SetBkColor_(SourceDC, TransparentColor) 
    BitBlt_ (maskDC, 0, 0, Width, Height, SourceDC, 0, 0, #SRCCOPY) 
    SetBkColor_(SourceDC, TransparentColor) 

    ; The first we do with the mask is To MergePaint it into the 
    ; destination. 
    ; This will punch a WHITE hole in the background exactly were 
    ; we want the graphics To be painted in. 
    BitBlt_ (tempDC, 0, 0, Width, Height, maskDC, 0, 0, #SRCCOPY) 
    BitBlt_ (DC, X, Y, Width, Height, tempDC, 0, 0, #MERGEPAINT) 

    ; Now we delete the transparent part of our source image. To do 
    ; this, we must invert the mask And MergePaint it into the 
    ; source image. The transparent area will now appear as WHITE. 
    BitBlt_ (maskDC, 0, 0, Width, Height, maskDC, 0, 0, #NOTSRCCOPY) 
    BitBlt_ (tempDC, 0, 0, Width, Height, SourceDC, 0, 0, #SRCCOPY) 
    BitBlt_ (tempDC, 0, 0, Width, Height, maskDC, 0, 0, #MERGEPAINT) 

    ; Both target And source are clean. All we have To do is To And 
    ; them together! 
    BitBlt_ (DC, X, Y, Width, Height, tempDC, 0, 0, #SRCAND) 

    ; Now all we have To do is To clean up after us And free system 
    ; resources.. 
    DeleteObject_ (hMaskBmp) 
    DeleteObject_ (hTempBmp) 
    DeleteDC_ (maskDC) 
    DeleteDC_ (tempDC) 
    DeleteDC_ (SourceDC) 

EndProcedure

Enumeration ;Images 
  #Image1 
  #Image2 
EndEnumeration 

CreateImage(#Image1,32,32) 
CreateImage(#Image2,32,32) 

UseImage(#Image1) 
StartDrawing(ImageOutput()) 
  Box(0,0,32,32,RGB(255,0,0)) 
  Box(5,5,22,22,RGB(0,0,0)) 
  StopDrawing() 

UseImage(#Image2) 
StartDrawing(ImageOutput()) 
  Box(0,0,32,32,RGB(0,0,255)) 
  Box(5,5,22,22,RGB(0,0,0)) 
  StopDrawing() 

OpenWindow(0,0,0,200,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"DrawTransparentImage() BUG") 

Repeat 
  Event = WindowEvent() 
  
  X = Random(168) 
  Y = Random(168) 
  Image = Random(#Image2) 
  
  DC = StartDrawing(WindowOutput()) 
    DrawTransparentimage(DC,UseImage(Image),X,Y,32,32,RGB(0,0,0)) 
  StopDrawing() 
Until Event = #PB_Event_CloseWindow

Posted: Tue Sep 27, 2005 3:45 pm
by rsts
That doesn't appear to be Fred's code.

Fred's runs fine on my computer.

Posted: Tue Sep 27, 2005 4:03 pm
by netmaestro
It's Fred's code all right. I put it in my personal library when he posted it and in testing I substituted the command from my lib to see if that would make a difference and no dice. It doesn't run on my computer. It doesn't exactly crash either. What it does is stop refreshing the drawing surface after 5000 draws. It keeps running and incrementing the counter I added to it, just no refreshing of the window.

Posted: Tue Sep 27, 2005 4:42 pm
by rsts
Thanks for removing the "retarded" comment because to me -

OpenWindow(0, 100, 100, 200, 200, #PB_Window_SystemMenu, "FastTransparency")

LoadImage(0, "Test1.bmp") ; Background
LoadImage(1, "Test2.bmp") ; Image to be drawn as transparent

UseImage(0)
DC = StartDrawing(ImageOutput())
If DC
DrawTransparentimage(DC, UseImage(1), 0, 0, 97, 97, RGB(255, 0, 255))
StopDrawing()
EndIf


CreateGadgetList(WindowID())
ImageGadget(0, 10, 10, 100, 100, UseImage(0))

Repeat
Event = WaitWindowEvent()

Until Event = #PB_Event_CloseWindow


Is NOT the same as -

Enumeration ;Images
#Image1
#Image2
EndEnumeration

CreateImage(#Image1,32,32)
CreateImage(#Image2,32,32)

UseImage(#Image1)
StartDrawing(ImageOutput())
Box(0,0,32,32,RGB(255,0,0))
Box(5,5,22,22,RGB(0,0,0))
StopDrawing()

UseImage(#Image2)
StartDrawing(ImageOutput())
Box(0,0,32,32,RGB(0,0,255))
Box(5,5,22,22,RGB(0,0,0))
StopDrawing()

OpenWindow(0,0,0,200,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"DrawTransparentImage() BUG")

Repeat
Event = WindowEvent()

X = Random(168)
Y = Random(168)
Image = Random(#Image2)

DC = StartDrawing(WindowOutput())
DrawTransparentimage(DC,UseImage(Image),X,Y,32,32,RGB(0,0,0))
StopDrawing()
Until Event = #PB_Event_CloseWindow

and what I said was they didn't appear to be the same.

Fred's does run fine for me.

cheers,

Posted: Sun Oct 02, 2005 1:13 am
by Dr. Dri
Fred's example, except that the user doesn't need to know DC stuff...

Code: Select all

Procedure DrawTransparentImage(Bitmap.l, x.l, y.l, Width.l, Height.l, TransparentColor.l)
  Protected hDC.l, maskDC.l, tempDC.l, sourceDC.l, hMaskBmp.l, hTempBmp.l
  
  !extrn _PB_2DDrawing_CurrentDC
  !MOV eax, dword [_PB_2DDrawing_CurrentDC]
  !MOV [esp+24], eax
  
  If hDC
    maskDC = CreateCompatibleDC_(hDC)
    tempDC = CreateCompatibleDC_(hDC)
   
    sourceDC = CreateCompatibleDC_(hDC)
    SelectObject_(sourceDC, Bitmap)
    
    hMaskBmp = CreateBitmap_(Width, Height, 1, 1, #Null)
    hTempBmp = CreateCompatibleBitmap_(hDC, Width, Height)
    
    hMaskBmp = SelectObject_(maskDC, hMaskBmp)
    hTempBmp = SelectObject_(tempDC, hTempBmp)
    
    TransparentColor = SetBkColor_(sourceDC, TransparentColor)
    BitBlt_(maskDC, 0, 0, Width, Height, sourceDC, 0, 0, #SRCCOPY)
    SetBkColor_(sourceDC, TransparentColor)
    
    BitBlt_(tempDC, 0, 0, Width, Height, maskDC, 0, 0, #SRCCOPY)
    BitBlt_(hDC, X, Y, Width, Height, tempDC, 0, 0, #MERGEPAINT)
    
    BitBlt_(maskDC, 0, 0, Width, Height, maskDC, 0, 0, #NOTSRCCOPY)
    BitBlt_(tempDC, 0, 0, Width, Height, SourceDC, 0, 0, #SRCCOPY)
    BitBlt_(tempDC, 0, 0, Width, Height, maskDC, 0, 0, #MERGEPAINT)
    
    BitBlt_(hDC, X, Y, Width, Height, tempDC, 0, 0, #SRCAND)
    
    DeleteObject_ (hMaskBmp)
    DeleteObject_ (hTempBmp)
    DeleteDC_ (maskDC)
    DeleteDC_ (tempDC)
    DeleteDC_ (SourceDC)
    
    ProcedureReturn #True
  EndIf
EndProcedure

OpenWindow(0, 100, 100, 280, 280, #PB_Window_SystemMenu, "FastTransparency")

LoadImage(0, "Test1.bmp") ; Background
LoadImage(1, "Test2.bmp") ; Image to be drawn as transparent

UseImage(0)

If StartDrawing(ImageOutput())
  DrawTransparentimage(UseImage(1), 0, 0, 128, 128, $FF00FF)
  StopDrawing()
EndIf


CreateGadgetList(WindowID())
ImageGadget(0, 10, 10, 100, 100, UseImage(0))

Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
Dri

Posted: Sun Oct 02, 2005 4:25 am
by netmaestro
Dr Dri, Fred's code stops drawing to the window after 5000 draws as shown by Joakim Christiansen's example above. Running his example and substituting Fred's procedure for your procedure of the same name, I find yours does the same thing. 5000 draws and then it stops drawing. Nobody so far has been able to figure out why this is happening. Can you?

Posted: Sun Oct 02, 2005 11:09 am
by Dr. Dri
i don't know :shock:
i just wanted to have a DrawTransparentImage Similar to DrawImage
and of course i share my code. nothing more, nothing less :?

Dri

Posted: Wed Oct 05, 2005 9:09 pm
by Mischa
This one works fine:

Code: Select all

Procedure DrawTransparentImage(DC, Bitmap, x, y, Width, Height, TransparentColor)

    ; First, create some DC's. These are our gateways To associated
    ; bitmaps in RAM
    maskDC = CreateCompatibleDC_(DC)
    tempDC = CreateCompatibleDC_(DC)
   
    SourceDC = CreateCompatibleDC_(DC)
    SelectObject_(SourceDC, Bitmap)
   

    ; Then, we need the bitmaps. Note that we create a monochrome
    ; bitmap here!
    ; This is a trick we use For creating a mask fast enough.
    hMaskBmp = CreateBitmap_(Width, Height, 1, 1, 0)
    hTempBmp = CreateCompatibleBitmap_(DC, Width, Height)

    ; Then we can assign the bitmaps to the DCs
    ;
    hMaskBmp2 = SelectObject_(maskDC, hMaskBmp)
    hTempBmp2 = SelectObject_(tempDC, hTempBmp)

    ; Now we can create a mask. First, we set the background color
    ; To the transparent color; then we copy the image into the
    ; monochrome bitmap.
    ; When we are done, we reset the background color of the
    ; original source.
    TransparentColor= SetBkColor_(SourceDC, TransparentColor)
    BitBlt_ (maskDC, 0, 0, Width, Height, SourceDC, 0, 0, #SRCCOPY)
    SetBkColor_(SourceDC, TransparentColor)

    ; The first we do with the mask is To MergePaint it into the
    ; destination.
    ; This will punch a WHITE hole in the background exactly were
    ; we want the graphics To be painted in.
    BitBlt_ (tempDC, 0, 0, Width, Height, maskDC, 0, 0, #SRCCOPY)
    BitBlt_ (DC, X, Y, Width, Height, tempDC, 0, 0, #MERGEPAINT)

    ; Now we delete the transparent part of our source image. To do
    ; this, we must invert the mask And MergePaint it into the
    ; source image. The transparent area will now appear as WHITE.
    BitBlt_ (maskDC, 0, 0, Width, Height, maskDC, 0, 0, #NOTSRCCOPY)
    BitBlt_ (tempDC, 0, 0, Width, Height, SourceDC, 0, 0, #SRCCOPY)
    BitBlt_ (tempDC, 0, 0, Width, Height, maskDC, 0, 0, #MERGEPAINT)

    ; Both target And source are clean. All we have To do is To And
    ; them together!
    BitBlt_ (DC, X, Y, Width, Height, tempDC, 0, 0, #SRCAND)

    ; Now all we have To do is To clean up after us And free system
    ; resources..
    DeleteObject_ (hMaskBmp)
    DeleteObject_ (hTempBmp)
    DeleteObject_ (hMaskBmp2)
    DeleteObject_ (hTempBmp2)
    DeleteDC_ (maskDC)
    DeleteDC_ (tempDC)
    DeleteDC_ (SourceDC)

EndProcedure

Enumeration ;Images
  #Image1
  #Image2
EndEnumeration

CreateImage(#Image1,32,32)
CreateImage(#Image2,32,32)

UseImage(#Image1)
StartDrawing(ImageOutput())
  Box(0,0,32,32,RGB(255,0,0))
  Box(5,5,22,22,RGB(0,0,0))
  StopDrawing()

UseImage(#Image2)
StartDrawing(ImageOutput())
  Box(0,0,32,32,RGB(0,0,255))
  Box(5,5,22,22,RGB(0,0,0))
  StopDrawing()

OpenWindow(0,0,0,200,200,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"DrawTransparentImage() NO BUG")

Repeat
  Event = WindowEvent()
 
  X = Random(168)
  Y = Random(168)
  Image = Random(#Image2)
 
  DC = StartDrawing(WindowOutput())
    DrawTransparentimage(DC,UseImage(Image),X,Y,32,32,RGB(0,0,0))
    ReleaseDC_(WindowID(0),DC)
  StopDrawing()
Until Event = #PB_Event_CloseWindow
Can you see the difference?

:wink:

You should take a look at PureArea.net, where you can find
sources like this...sometimes this could be helpful.

..and don't forget, the blitting way is much faster (10 times!?) than
ImageList_AddMasked, DIBs, or such things.

Regards,
Mischa

Posted: Wed Oct 05, 2005 9:21 pm
by netmaestro
Good job Mischa. That was confusing a lot of people for quite some time. I see the difference, but I don't see the need to create the 2's and then destroy them after never using them. I replaced the 2='s with just SelectObject_() and took out the DeleteObject_() lines for them and it still works fine, while not creating confusion with names that never get used. Thanks for clearing this up for us. I can stick this proc in my personal lib now and use it.

Posted: Wed Oct 05, 2005 9:33 pm
by Mischa
You are right, makes no sense here.

Cause there are no "old" bitmaps in these DCs.

Code: Select all

oldobject = SelectObject_(anyDC,newobject)
Regards,
Mischa

Posted: Wed Oct 19, 2005 7:08 pm
by josku_x
this is very great code, but is it possible to use this in commands like ButtonImageGadget()?? thanks for any help will be very appreciated.