Draw transparent image with windows API?

Just starting out? Need help? Post your questions and find answers here.
TheBeck
User
User
Posts: 39
Joined: Mon May 12, 2003 6:04 am
Location: the far west
Contact:

Draw transparent image with windows API?

Post by TheBeck »

Hi, I am making a 2d game and I do not want it to require directx. If i draw the images using DrawImage() I can not set any transparency. I have to use DisplayTransparentSprite() witch requires directx. If there was a command DrawTransparentImage() then all would be right with the world. Well for me at least.

I found in MSDN an api that will act like DrawTransparentImage(), I think. Only problem is I don't have the required synaptic pathways connecting the neurons in my head to make use of this. If anyone would be so kind as to let me know if this would work with other 2d drawing commands such as StartDrawing() I would be very grateful. Maybe even an example? The best thing would be to wrap this into a procedure called DrawTransparentImage() and everyone could use this until Fred has time to incorporate it into the language.

Link to MSDN api:
http://msdn.microsoft.com/library/defau ... s_2y9g.asp
Nathan Beckstrand -- XPSP2, AMD Athlon XP 3000+, GF2 GTS, 512MB RAM
TheBeck
User
User
Posts: 39
Joined: Mon May 12, 2003 6:04 am
Location: the far west
Contact:

Post by TheBeck »

Here is some code to draw draw a transparent image without using directx or windows API. The zip file contains required image files so you don't have to make your own. There has got to be a better way to do this, this method is very dirty and can't be the fastest, although I was surprised at how fast it is, PureBasic rocks! This code is of course free ;) If you do use it, it is the same as DrawImage() except for the last argument witch is what color to make transparent. You have to make sure to change all the WindowOutput() inside the DrawTransparentImage() procedure to whatever you are drawing on if it is different, I don't know how to fix this.

http://www.thebeck.com/DrawTransparentImage.zip

Here is the code in case you just want to see it:

Code: Select all

#background = 1
#foreground = 2

Procedure DrawTransparentImage(image_id.l,x.l,y.l,rgb.l)
  UseImage(image_id)
  Debug ImageHeight()
  Debug ImageWidth()
  For row = 0 To ImageHeight() - 1
    For col = 0 To ImageWidth() - 1
      StopDrawing()
      StartDrawing(ImageOutput())
      color = Point(col,row)
      If color <> rgb
        StopDrawing()
        StartDrawing(WindowOutput())
        Plot(col + x,row + y,color)
      EndIf
    Next col
  Next row
  StopDrawing()
  StartDrawing(WindowOutput())
EndProcedure

If OpenWindow(1,0,0,400,400,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"DrawTransparentImage")
Else
  End
EndIf
LoadImage(#background,"background.bmp")
LoadImage(#foreground,"foreground.bmp")
Repeat
  StartDrawing(WindowOutput())
  DrawImage(UseImage(#background),0,0)
  DrawTransparentImage(#foreground,WindowMouseX(),WindowMouseY(),RGB(0,0,0))
  StopDrawing()
Until WaitWindowEvent() = #PB_Event_CloseWindow
End
Nathan Beckstrand -- XPSP2, AMD Athlon XP 3000+, GF2 GTS, 512MB RAM
Fred
Administrator
Administrator
Posts: 18162
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

Here is an example which should work on any Windows version. I will probably add this code as native command. Just follow the URL to get the tests pictures. If someone knows a faster way to achieve the same goal, just tell us ;)

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, #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

TheBeck
User
User
Posts: 39
Joined: Mon May 12, 2003 6:04 am
Location: the far west
Contact:

Post by TheBeck »

Thanks Fred, that works perfect! 8)
Nathan Beckstrand -- XPSP2, AMD Athlon XP 3000+, GF2 GTS, 512MB RAM
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Post by Joakim Christiansen »

Nice, just what I needed!
Did you forget to add this Fred? :P
I like logic, hence I dislike humans but love computers.
Intrigued
Enthusiast
Enthusiast
Posts: 501
Joined: Thu Jun 02, 2005 3:55 am
Location: U.S.A.

Post by Intrigued »

This is something I was looking for before as well;however, upon Previewing (F5)... an error dialog popups up and then the Preview crashes.

The error doc (XML) is below (I click on View Details and then it had the info. below list in the temp (error) file):

<?xml version="1.0" encoding="UTF-16"?>
<DATABASE>
<EXE NAME="PureBasic392104750.exe" FILTER="GRABMI_FILTER_PRIVACY">
<MATCHING_FILE NAME="Atl.dll" SIZE="73785" CHECKSUM="0xB17C9B2B" BIN_FILE_VERSION="3.0.8449.0" BIN_PRODUCT_VERSION="6.0.0.8449" PRODUCT_VERSION="6.00.8449" FILE_DESCRIPTION="ATL Module for Windows (ANSI)" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft (R) Visual C++" FILE_VERSION="3.00.8449" ORIGINAL_FILENAME="ATL.DLL" INTERNAL_NAME="ATL" LEGAL_COPYRIGHT="Copyright © Microsoft Corp. 1996-1998" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x4" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x0" LINKER_VERSION="0x20000" UPTO_BIN_FILE_VERSION="3.0.8449.0" UPTO_BIN_PRODUCT_VERSION="6.0.0.8449" LINK_DATE="03/25/1999 14:42:10" UPTO_LINK_DATE="03/25/1999 14:42:10" VER_LANGUAGE="English (United States) [0x409]" />
<MATCHING_FILE NAME="Engine3D.dll" SIZE="612352" CHECKSUM="0xAE1A1BD6" MODULE_TYPE="WIN32" PE_CHECKSUM="0x0" LINKER_VERSION="0x0" LINK_DATE="04/03/2004 22:23:26" UPTO_LINK_DATE="04/03/2004 22:23:26" />
<MATCHING_FILE NAME="FAsm.exe" SIZE="65536" CHECKSUM="0x4311C044" MODULE_TYPE="WIN32" PE_CHECKSUM="0x123E5" LINKER_VERSION="0x0" LINK_DATE="02/10/2005 13:04:26" UPTO_LINK_DATE="02/10/2005 13:04:26" />
<MATCHING_FILE NAME="folink.exe" SIZE="18944" CHECKSUM="0xA7CED0" MODULE_TYPE="WIN32" PE_CHECKSUM="0x1043D" LINKER_VERSION="0x0" LINK_DATE="09/24/2004 15:59:49" UPTO_LINK_DATE="09/24/2004 15:59:49" />
<MATCHING_FILE NAME="PBCompiler-jaPBe.exe" SIZE="134176" CHECKSUM="0x96662F7C" MODULE_TYPE="WIN32" PE_CHECKSUM="0x0" LINKER_VERSION="0x0" LINK_DATE="03/01/2005 11:52:16" UPTO_LINK_DATE="03/01/2005 11:52:16" />
<MATCHING_FILE NAME="PBCompiler.exe" SIZE="134176" CHECKSUM="0x96662F7C" MODULE_TYPE="WIN32" PE_CHECKSUM="0x0" LINKER_VERSION="0x0" LINK_DATE="03/01/2005 11:52:16" UPTO_LINK_DATE="03/01/2005 11:52:16" />
<MATCHING_FILE NAME="polib.exe" SIZE="74240" CHECKSUM="0x83E44FD3" BIN_FILE_VERSION="2.80.1.0" BIN_PRODUCT_VERSION="2.80.0.0" PRODUCT_VERSION="2.80" FILE_DESCRIPTION="Pelles Library Manager" COMPANY_NAME="Pelle Orinius" PRODUCT_NAME="Pelles C for Windows" FILE_VERSION="2.80.1" ORIGINAL_FILENAME="POLIB.EXE" INTERNAL_NAME="POLIB" LEGAL_COPYRIGHT="Copyright © Pelle Orinius 1997-2004" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x10004" VERFILETYPE="0x1" MODULE_TYPE="WIN32" PE_CHECKSUM="0x19245" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="2.80.1.0" UPTO_BIN_PRODUCT_VERSION="2.80.0.0" LINK_DATE="06/10/2004 18:18:57" UPTO_LINK_DATE="06/10/2004 18:18:57" />
<MATCHING_FILE NAME="polink.exe" SIZE="142336" CHECKSUM="0x39A2A7B0" BIN_FILE_VERSION="3.0.0.0" BIN_PRODUCT_VERSION="3.0.0.0" PRODUCT_VERSION="3.00" FILE_DESCRIPTION="Pelles Linker" COMPANY_NAME="Pelle Orinius" PRODUCT_NAME="Pelles C for Windows" FILE_VERSION="3.00.0" ORIGINAL_FILENAME="POLINK.EXE" INTERNAL_NAME="POLINK" LEGAL_COPYRIGHT="Copyright © Pelle Orinius 1998-2005" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x10004" VERFILETYPE="0x1" MODULE_TYPE="WIN32" PE_CHECKSUM="0x273DB" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="3.0.0.0" UPTO_BIN_PRODUCT_VERSION="3.0.0.0" LINK_DATE="01/14/2005 20:34:01" UPTO_LINK_DATE="01/14/2005 20:34:01" />
<MATCHING_FILE NAME="porc.dll" SIZE="114688" CHECKSUM="0xC434015B" BIN_FILE_VERSION="2.80.3.0" BIN_PRODUCT_VERSION="2.80.0.0" PRODUCT_VERSION="2.80" FILE_DESCRIPTION="Pelles Resource Compiler DLL" COMPANY_NAME="Pelle Orinius" PRODUCT_NAME="Pelles C for Windows" FILE_VERSION="2.80.3" ORIGINAL_FILENAME="PORC.DLL" INTERNAL_NAME="PORC" LEGAL_COPYRIGHT="Copyright © Pelle Orinius 2001-2004" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x10004" VERFILETYPE="0x1" MODULE_TYPE="WIN32" PE_CHECKSUM="0x1C899" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="2.80.3.0" UPTO_BIN_PRODUCT_VERSION="2.80.0.0" LINK_DATE="06/11/2004 18:49:05" UPTO_LINK_DATE="06/11/2004 18:49:05" />
<MATCHING_FILE NAME="porc.exe" SIZE="32256" CHECKSUM="0x64CA77FD" BIN_FILE_VERSION="2.80.3.0" BIN_PRODUCT_VERSION="2.80.0.0" PRODUCT_VERSION="2.80" FILE_DESCRIPTION="Pelles Resource Compiler Driver" COMPANY_NAME="Pelle Orinius" PRODUCT_NAME="Pelles C for Windows" FILE_VERSION="2.80.3" ORIGINAL_FILENAME="PORC.DLL" INTERNAL_NAME="PORC" LEGAL_COPYRIGHT="Copyright © Pelle Orinius 1997-2004" VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x10004" VERFILETYPE="0x1" MODULE_TYPE="WIN32" PE_CHECKSUM="0x14E9E" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="2.80.3.0" UPTO_BIN_PRODUCT_VERSION="2.80.0.0" LINK_DATE="06/11/2004 18:32:39" UPTO_LINK_DATE="06/11/2004 18:32:39" />
<MATCHING_FILE NAME="PureBasic392104750.exe" SIZE="15872" CHECKSUM="0xC1D25DD9" MODULE_TYPE="WIN32" PE_CHECKSUM="0x0" LINKER_VERSION="0x0" LINK_DATE="09/25/2005 16:21:18" UPTO_LINK_DATE="09/25/2005 16:21:18" />
</EXE>
<EXE NAME="kernel32.dll" FILTER="GRABMI_FILTER_THISFILEONLY">
<MATCHING_FILE NAME="kernel32.dll" SIZE="983552" CHECKSUM="0x4CE79457" BIN_FILE_VERSION="5.1.2600.2180" BIN_PRODUCT_VERSION="5.1.2600.2180" PRODUCT_VERSION="5.1.2600.2180" FILE_DESCRIPTION="Windows NT BASE API Client DLL" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Windows® Operating System" FILE_VERSION="5.1.2600.2180 (xpsp_sp2_rtm.040803-2158)" ORIGINAL_FILENAME="kernel32" INTERNAL_NAME="kernel32" LEGAL_COPYRIGHT="© Microsoft Corporation. All rights reserved." VERFILEDATEHI="0x0" VERFILEDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0xFF848" LINKER_VERSION="0x50001" UPTO_BIN_FILE_VERSION="5.1.2600.2180" UPTO_BIN_PRODUCT_VERSION="5.1.2600.2180" LINK_DATE="08/04/2004 07:56:36" UPTO_LINK_DATE="08/04/2004 07:56:36" VER_LANGUAGE="English (United States) [0x409]" />
</EXE>
</DATABASE>
Intrigued - Registered PureBasic, lifetime updates user
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

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?
BERESHEIT
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Another way
Updated

Code: Select all

Procedure TransparentRGB(IMG,x,y,RGB) 
    HLC=ImageList_Create_(ImageWidth(),ImageHeight(),#ILC_COLOR32|#ILC_MASK,1,0) 
    ImageList_AddMasked_(HLC,IMG,RGB) 
    DC=BeginPaint_(WindowID(),@PaintStruct.PAINTSTRUCT)
    ImageList_Draw_(HLC,0,DC,x,y,#ILD_TRANSPARENT) 
    ImageList_Destroy_(HLC) 
    EndPaint_(WindowID(),@PaintStruct)
    ImageList_Destroy_(HLC)
EndProcedure 

hWnd = OpenWindow(0, 0, 0,0,0 , #WS_OVERLAPPEDWINDOW | #WS_MAXIMIZE,"Transparent Color") 
IMG=LoadImage(0,  "c:\test2.bmp")  ;************************* 
If IMG 
TransparentRGB(IMG,100,100,#White)  ; here the color to be converted in transparent 
    Repeat 
    Until WaitWindowEvent()=#PB_EventCloseWindow 
EndIf 
End
Last edited by einander on Sun Sep 25, 2005 7:59 pm, edited 2 times in total.
josku_x
Addict
Addict
Posts: 997
Joined: Sat Sep 24, 2005 2:08 pm

Post by josku_x »

hey, I tried that code, but it doesn't work :( I get just white image.
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

Also there is TransparentBlt_() API, but PB don't recognize it.
josku_x
Addict
Addict
Posts: 997
Joined: Sat Sep 24, 2005 2:08 pm

Post by josku_x »

your code messes my image, but duh, atleast Fred's code work :)
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

This one works with WinXP. Not tested with ME - 9x

Code: Select all

#IMG=1
 Procedure CreateTranspBMP(IMG,RGB) 
    IMG=UseImage(IMG)
    ImgList=ImageList_Create_(ImageWidth(),ImageHeight(),#ILC_COLOR16|#ILC_MASK,1,0) 
    ImageList_AddMasked_(ImgList,IMG,RGB) 
    ProcedureReturn ImgList
EndProcedure 


OpenWindow(0,0,0,0,0 , #WS_OVERLAPPEDWINDOW | #WS_MAXIMIZE,"Transparent BMP") 
hDC=GetDC_(WindowID()) 
LoadImage(#IMG,"c:\test1.bmp") ;*************** your image here*************
; ResizeImage(#IMG,80,80)  ; uncomment to resize
Halfw=ImageWidth()/2:Halfh=ImageHeight()/2 ; to center mouse on BMP

TransparentRGB=#White   ; select RGB for transparency ********************
ImgList=CreateTranspBMP(#IMG,TransparentRGB)
MASK=#ILD_TRANSPARENT ; see API ImageList_Draw Function to change Masks
        
Repeat 
    EV=WaitWindowEvent()
    If GetAsyncKeyState_(#VK_LBUTTON)
        If EV=#WM_MOUSEMOVE
            ImageList_Draw_(ImgList,0,hDC,WindowMouseX()-Halfw,WindowMouseY()-Halfh,MASK) 
        EndIf
    EndIf 
Until EV= #PB_Event_CloseWindow 
    
ImageList_Destroy_(ImgList) 
End
Brice Manuel

Post by Brice Manuel »

WooHoo!!!! Fred's example is just what I needed for something I am working on. Thanks to whoever bumped this :wink:
Henrik
Enthusiast
Enthusiast
Posts: 404
Joined: Sat Apr 26, 2003 5:08 pm
Location: Denmark

Post by Henrik »

@einander
If White should be the transparent color, then both works on 98
just that, in the first example you use "test2.bmp" (Freds link) and it do not contain any
white color, test1.bmp does use that and the clouds is transparent.
On 98 that is..
User avatar
einander
Enthusiast
Enthusiast
Posts: 744
Joined: Thu Jun 26, 2003 2:09 am
Location: Spain (Galicia)

Post by einander »

@Henrik:Thanx for your reply.

On my examples you can choose any BMP, and must choose the RGB color that you want to be transparent.

The file c:\test1:bmp is on my HD, and is supposed to be replaced with your own Bmp. (No related with the file test.bmp on Fred's great example.)

I think my 2nd example is less buggy. Both works better with small or medium sized BMPs, 100*200 or less.
Post Reply