Page 3 of 3

Posted: Sat Dec 10, 2005 11:42 am
by Xombie
I've been banging my head against this one for a bit. I can get your example to work great but when I try to merge it into my code, it fails. Only a pure black image is outputted. Here's a snippet of the code that does the work.

Code: Select all

*xVideo\AVS\pGetFrame = CallFunctionFast(_VideoAddress\AVIStreamGetFrameOpen, *xVideo\AVS\pAVIStream, #AVIGETFRAMEF_BESTDISPLAYFMT)
;
*bih = CallFunctionFast(_VideoAddress\AVIStreamGetFrame, *xVideo\AVS\pGetFrame, inFrame) 
;
If *bih
   ;
   hDC = GetDC_(ImageID(*xVideo\ImageSubtitle)) 
   ;
   hCDC = CreateCompatibleDC_(hDC)
   ;
   If hCDC
      ;
      SelectObject_(hCDC, ImageID(*xVideo\ImageSubtitle))
      ;
      SetDIBits_(hCDC, ImageID(*xVideo\ImageSubtitle), 0, *bih\biHeight, *bih + SizeOf(BITMAPINFOHEADER), *bih, #DIB_RGB_COLORS)
      ;
      SaveImage(*xVideo\ImageSubtitle, "t1.bmp")
      ;
      ;DrawImage(ImageID(*xVideo\ImageSubtitle), 0, 0)
      dcVideo = StartDrawing(ImageOutput(*xVideo\ImageVideo))
      ;
      If dcVideo
         ;
         mciSendString_("update "+*xVideo\Alias+" hdc "+Str(dcVideo)+" wait", #Null, 0, 0)
         ;
         SaveImage(*xVideo\ImageVideo, "t2.bmp")
         ;
         DrawTransparentImage(dcVideo, ImageID(*xVideo\ImageSubtitle), 0, 0, *xVideo\Properties\Width, *xVideo\Properties\Height, RGB(0, 0, 255))
         ;
         StopDrawing()
         ;
         SaveImage(*xVideo\ImageVideo, "t3.bmp")
         ;
      EndIf
      ;
      DeleteDC_(hCDC)
      ;
   EndIf
   ;
   ReleaseDC_(ImageID(*xVideo\ImageSubtitle), hDC)
   ;
   ; SetGadgetState(*xVideo\idParent, ImageID(*xVideo\ImageVideo))
   ;
EndIf
;
CallFunctionFast(_VideoAddress\AVIStreamGetFrameClose, *xVideo\AVS\pGetFrame) : *xVideo\AVS\pGetFrame = 0
Hopefully that kind of makes sense. It's just a part of the whole but it's the part that does the work. "t1.bmp" is saved correctly. It's the image/mask. It is mostly blue except for an image. "t2.bmp" is also correct and contains the background image. "t3.bmp" should be a combination of t1 & t2 with t2 as the background and t1 pasted on top. However, "t3.bmp" is just a pure black image when it is saved. I don't understand what's wrong. I'm using Mischa's version and his demonstration works perfectly for my t1 & t2 images.

Am I making an obvious mistake somewhere?

EDIT: I figured it out with El_Choni's wonderful help. It was the SelectObject_() line causing problems. Once that is removed, it's fine. Also, I needed to change the GetDC_() to use GetDesktopWindow_().

Thanks, El_Choni!

Posted: Wed May 23, 2007 2:39 pm
by Zizaco
In PB 4.0 why does it dont work?

I've changed some things like the "UseImage()" comand (that doesnt exist anymore).

my code:

Code: Select all

;
; Conversion for PB of a Vegard Fiksdal Technologies code
; http://www.codeguru.com/vb/gen/vb_graphics/transparency/article.php/c5329/
;
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



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

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

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


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

Repeat
  Event = WaitWindowEvent()
 
Until Event = #PB_Event_CloseWindow 
It should work right?

(sorry for my bad english)

Posted: Wed May 23, 2007 2:53 pm
by Brice Manuel
Zizaco wrote:In PB 4.0 why does it dont work?
A lot of syntax changed in 4.0.

The 4.0 code below should work:

Code: Select all

; 
; Conversion for PB of a Vegard Fiksdal Technologies code 
; http://www.codeguru.com/vb/gen/vb_graphics/transparency/article.php/c5329/ 
; 
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 



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

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

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


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

Repeat 
  Event = WaitWindowEvent() 
  
Until Event = #PB_Event_CloseWindow

Posted: Wed May 23, 2007 2:55 pm
by srod
Change

Code: Select all

ImageGadget(0, 10, 10, 100, 100, 0) 
to

Code: Select all

ImageGadget(0, 10, 10, 100, 100, ImageId(0)) 
:)


**EDIT: too slow! Brice beat me to it!

Posted: Wed May 23, 2007 2:57 pm
by Zizaco
Oh, Thanks...
I got it to work

Posted: Sun Oct 21, 2007 11:11 pm
by #NULL
that should be the PB4x-version including Mischa's and netmaestro's fix.
maybe someone who knows about such could have a look if everthing is correct like this?

Code: Select all

EnableExplicit


Procedure DrawTransparentImage(DC, Bitmap, x, y, Width, Height, TransparentColor)
  Protected maskDC.l
  Protected tempDC.l
  Protected SourceDC.l
  Protected hMaskBmp.l
  Protected hTempBmp.l
  
  ; 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
  ;
  SelectObject_(maskDC, hMaskBmp)
  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)

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

StartDrawing(ImageOutput(#Image2))
  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,"DrawTransparentImage() BUGfixed",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

Repeat
  Define Event = WindowEvent()
 
  Define X = Random(168)
  Define Y = Random(168)
  Define Image = Random(#Image2)
 
  Define DC = StartDrawing(WindowOutput(0))
    DrawTransparentimage(DC,ImageID(Image),X,Y,32,32, RGB(0,0,0))
  StopDrawing()
Until Event = #PB_Event_CloseWindow
thank's for that useful procedure!
would it be too difficult to do that on linux/mac too for an PB-integrated command?

Re: Draw transparent image with windows API?

Posted: Fri Apr 08, 2016 6:38 pm
by #NULL
using this function to draw on a sprite seems to do nothing with pb 5.42. it worked with pb 4.41, also it works when drawing on an image/window/screen output, but not on sprite output. CreateCompatibleDC() seems to fail in that case. some ideas why?

Code: Select all

EnableExplicit


Procedure DrawTransparentImage(DC, Bitmap, x, y, Width, Height, TransparentColor)
  Protected maskDC.l
  Protected tempDC.l
  Protected SourceDC.l
  Protected hMaskBmp.l
  Protected hTempBmp.l
 
  ; 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
  ;
  SelectObject_(maskDC, hMaskBmp)
  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
  #Image1
EndEnumeration

CreateImage(#Image1,32,32)
StartDrawing(ImageOutput(#Image1))
  Box(0,0,32,32,RGB(255,0,0))
  Box(5,5,22,22,RGB(0,0,0))
StopDrawing()
  
InitSprite()
OpenWindow(0,0,0,400,600,"DrawTransparentImage()",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0), 0, 0, 400, 600)

CreateSprite(123, 200, 200)
Define DC = StartDrawing(SpriteOutput(123))
  Box(0,0,200,200,RGB(0,123,0))
  DrawImage(ImageID(#Image1),10,10,32,32)
  DrawTransparentImage(DC,ImageID(#Image1),10,50,32,32, RGB(0,0,0))
StopDrawing()

Repeat
  Define Event = WindowEvent()
  ClearScreen(RGB(100,100,100))
  
  Define DC = StartDrawing(ScreenOutput())
    DrawImage(ImageID(#Image1),10,10,32,32)
    DrawTransparentImage(DC,ImageID(#Image1),10,100,32,32, RGB(0,0,0))
  StopDrawing()
  
  DisplaySprite(123, 10, 200)
  
  FlipBuffers()
Until Event = #PB_Event_CloseWindow