What's wrong with my alpha blend routine?

Just starting out? Need help? Post your questions and find answers here.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

What's wrong with my alpha blend routine?

Post by Trond »

I just can't understand this. Only a small part of the image is drawn. And also it's not alpha blending correctly. Does anyone know something about this?

Code: Select all

UseTIFFImageDecoder()

Procedure Min(A, B)
  If A > B
    ProcedureReturn B
  EndIf
  ProcedureReturn A
EndProcedure


Procedure BlitAlphaImage(Img1, Img2)
  Protected hDC
  Protected Mem1, Mem2
  Protected Bmp.BITMAP
  Protected X, Y
  Protected W2 = ImageWidth(Img2)
  Protected H2 = ImageWidth(Img2)
  Protected *OldVal1.RGBQUAD
  Protected *OldVal2.RGBQUAD
  hDC = GetDC_(0)
    GetObject_(ImageID(Img1), SizeOf(BITMAP), @Bmp)
    Mem1 = Bmp\bmBits
    GetObject_(ImageID(Img2), SizeOf(BITMAP), @Bmp)
    Mem2 = Bmp\bmBits
  ReleaseDC_(0, hDC)
  For X = 0 To W2
    For Y = 0 To H2
      *OldVal1 = Mem1+X*W2+Y
      *OldVal1\rgbRed + 15
      *OldVal1\rgbGreen + 15
      *OldVal1\rgbBlue + 15
      ;*OldVal1 = Mem1+X*W2+Y
      ;*OldVal2 = Mem2+X*W2+Y
      ;*OldVal1\rgbRed = ((*OldVal1\rgbRed**OldVal2\rgbReserved)/100) + ((*OldVal2\rgbRed*(100-*OldVal2\rgbReserved)) / 100)
      ;*OldVal1\rgbGreen = ((*OldVal1\rgbGreen**OldVal2\rgbReserved)/100) + ((*OldVal2\rgbGreen*(100-*OldVal2\rgbReserved)) / 100)
      ;*OldVal1\rgbBlue = ((*OldVal1\rgbBlue**OldVal2\rgbReserved)/100) + ((*OldVal2\rgbBlue*(100-*OldVal2\rgbReserved)) / 100)
      ;*OldVal1\rgbReserved = Min(*OldVal1\rgbReserved + *OldVal2\rgbReserved, 255)
    Next
  Next
EndProcedure




OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CreateGadgetList(WindowID(0))


LoadImage(0, "Clock - Back.tiff")
LoadImage(1, "Border.tiff")

BlitAlphaImage(0, 1)

ImageGadget(0, 0, 0, 0, 0, ImageID(0))


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

A quick observation; you've set H2 to equal ImageWidth(), should that not be ImageHeight() etc?
I may look like a mule, but I'm not a complete ass.
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 »

This is the code cut to the bone, with only enough kept to show proper movement through the bitmap. The main problem was related to not moving 4 bytes forward after each blend operation (32bits/pixel). I didn't test the rest of the blending stuff but it should work now. If the blitted bitmap looks reddish in this version, the pixels should be blending right.

Code: Select all

timeBeginPeriod_(1) 

UseTIFFImageDecoder() 

Procedure BlitAlphaImage(Img1, Img2) 
  Protected hDC 
  Protected Mem1, Mem2 
  Protected Bmp.BITMAP 
  Protected X, Y 
  Protected W2 = ImageWidth(Img2) 
  Protected H2 = ImageHeight(Img2) ; <---Changed this line 
  Protected *OldVal1.RGBQUAD       ; (didn't matter because image is square anyway) 
  Protected *OldVal2.RGBQUAD 
  hDC = GetDC_(0) 
    GetObject_(ImageID(Img1), SizeOf(BITMAP), @Bmp) 
    Mem1 = Bmp\bmBits 
    GetObject_(ImageID(Img2), SizeOf(BITMAP), @Bmp) 
    Mem2 = Bmp\bmBits 
  ReleaseDC_(0, hDC) 
  For X = 0 To Bmp\bmWidthBytes -1 Step 4  ; <---Changed this line 
    For Y = 0 To H2 -1                     ; <---Changed this line 
      *OldVal1 = Mem1+X+Bmp\bmWidthBytes*Y ; <---Changed this line 
      *OldVal1\rgbRed + 55                 ; <---Changed this line 
      *OldVal1\rgbGreen + 15               ; (easier to verify correct working with extra red added) 
      *OldVal1\rgbBlue + 15 
    Next 
  Next 
EndProcedure 

OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu) 
CreateGadgetList(WindowID(0)) 

LoadImage(0, "Clock - Back.tiff") 
LoadImage(1, "clock - Back.tiff") ; <---Changed this line to show image before blit 

t=timeGetTime_() 
  BlitAlphaImage(0, 1) 
t2 =timeGetTime_()-t 

ImageGadget(0, 0, 0, 0, 0, ImageID(0)) 
ImageGadget(1, 256,0,0,0, ImageID(1)) ; <---Added this gadget to show image before blit 
TextGadget(2, 170,300,200,20,"Blit took "+Str(t2)+" milliseconds (no debugger)") ; <--Added to check spd

Repeat 
  Select WaitWindowEvent() 
    Case #PB_Event_CloseWindow 
      Break 
  EndSelect 
ForEver
BERESHEIT
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

netmaestro wrote:This is the code cut to the bone, with only enough kept to show proper movement through the bitmap. The main problem was related to not moving 4 bytes forward after each blend operation (32bits/pixel).
Oh, why didn't I think of that. Thanks a bunch!
User avatar
Michael Vogel
Addict
Addict
Posts: 2811
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

Hmm...
thought t I can use your code for fading between two (jpg) pictures, but...

When using RAW format to load the jpegs, the pictures have only 24 bits depth so everything looks scrambled. So my next test was to

use Image_display_format - the images seems to have 32 bit, but I get an error "pointer is null" in the line "*NewVal\rgbRed=(...)" !

Can anyone help?

Code: Select all

Global FadedImage
FadedImage=CreateImage(999,256,256,32)

; Define

	Global Modus=1

	Global ScreenX=GetSystemMetrics_(#SM_CXSCREEN)
	Global ScreenY=GetSystemMetrics_(#SM_CYSCREEN)
	Global FrameSizeX=640
	Global FrameSizeY=480

	Structure PictStruct
		id.l
		x.l
		y.l
		w.l
		h.l
	EndStructure
	Global Dim Picture.PictStruct(2)

; EndDefine

Procedure Scale(nr)
	Protected skalierung.f

	If IsImage(nr)=0
		CreateImage(nr,32,32,#PB_Image_DisplayFormat)
	EndIf

	Picture(nr)\w=ImageWidth(nr)
	Picture(nr)\h=ImageHeight(nr)
	If w>FrameSizeX
		skalierung=FrameSizeX/Picture(nr)\w
		Picture(nr)\w*skalierung
		Picture(nr)\h*skalierung
	EndIf
	If Picture(nr)\h>FrameSizeY
		skalierung.f=FrameSizeY/Picture(nr)\h
		Picture(nr)\w*skalierung
		Picture(nr)\h*skalierung
	EndIf

	Picture(nr)\w=256
	Picture(nr)\h=256

	ResizeImage(nr,Picture(nr)\w,Picture(nr)\h,#PB_Image_Smooth)

	Picture(nr)\id=ImageID(nr)
	Picture(nr)\x=(ScreenX-Picture(nr)\w)>>1
	Picture(nr)\y=(ScreenY-Picture(nr)\h)>>1

	If 0
		Debug picture(nr)\x
		Debug picture(nr)\y
		Debug picture(nr)\w
		Debug picture(nr)\h
	EndIf

	CreateSprite(nr,Picture(nr)\w,Picture(nr)\h,#PB_Sprite_Texture)
	StartDrawing(SpriteOutput(nr))
	DrawImage(Picture(nr)\id,0,0,Picture(nr)\w,Picture(nr)\h); because Resize doesn't work
	StopDrawing()

	CreateSprite3D(nr,nr)

EndProcedure
Procedure Faade(Img1,Img2,c)
	Protected d=255-c

	Protected hDC
	Protected Mem1, Mem2,Mem3
	Protected Bmp.BITMAP
	Protected X, Y
	Protected W2 = ImageWidth(Img2)
	Protected H2 = ImageHeight(Img2) ; <---Changed this line
	Protected *OldVal1.RGBQUAD       ; (didn't matter because image is square anyway)
	Protected *OldVal2.RGBQUAD
	Protected *NewVal.RGBQUAD

hDC = GetDC_(0)
	GetObject_(ImageID(Img1), SizeOf(BITMAP), @Bmp)
	Mem1 = Bmp\bmBits
	GetObject_(ImageID(Img2), SizeOf(BITMAP), @Bmp)
	Mem2 = Bmp\bmBits
	ReleaseDC_(0, hDC)
	
	hDC = GetDC_(0)
	GetObject_(ImageID(999), SizeOf(BITMAP), @Bmp)
	Mem3 = Bmp\bmBits
	ReleaseDC_(0, hDC)

	For X = 0 To Bmp\bmWidthBytes -1 Step 4  ; <---Changed this line
		For Y = 0 To H2 -1                     ; <---Changed this line
			*OldVal1 = Mem1+X+Bmp\bmWidthBytes*Y ; <---Changed this line
			*OldVal2 = Mem2+X+Bmp\bmWidthBytes*Y ; <---Changed this line
			*NewVal = Mem3+X+Bmp\bmWidthBytes *Y ; <---Changed this line
			*NewVal\rgbRed=((*OldVal1\rgbRed)*c + (*OldVal2\rgbRed)*d)>>8
			*NewVal\rgbGreen=((*OldVal1\rgbGreen)*c + (*OldVal2\rgbGreen)*d)>>8
			*NewVal\rgbBlue=((*OldVal1\rgbBlue)*c + (*OldVal2\rgbBlue)*d)>>8
			
			*NewVal\rgbRed=y&255;*OldVal1\rgbRed
			*NewVal\rgbGreen=*OldVal1\rgbGreen
			*NewVal\rgbBlue=*OldVal1\rgbBlue
		Next
	Next

EndProcedure
Procedure Main()
	If (InitSprite() And InitSprite3D() And OpenScreen(ScreenX,ScreenY,32,"Fading"))

		CreateSprite(0,16,16,#PB_Sprite_Texture)
		;TransparentSpriteColor(Spr,$80808)
		StartDrawing(SpriteOutput(0))
		Box(0,0,16,16,$80808)
		StopDrawing()
		CreateSprite3D(0,0)
		ZoomSprite3D(0,ScreenX,ScreenY)

		UseJPEGImageDecoder()
		UsePNGImageDecoder()

		LoadImage(1,"data\1.jpg",#PB_Image_DisplayFormat)
		LoadImage(2,"data\2.jpg", #PB_Image_DisplayFormat)
		Scale(1)
		Scale(2)

		Faade(1,2,200)


		For i=0 To 255 Step 4

			pause=GetTickCount_()+50

			Select Modus

			Case 1
				StartDrawing (ScreenOutput())
				;DrawImage(Picture(1)\id,Picture(1)\x,Picture(1)\y)
				DrawImage(ImageID(999),0,0)
				StopDrawing()

			Case 2
				DisplaySprite(1,Picture(1)\x,Picture(1)\y)
				Start3D()
				DisplaySprite3D(0,0,0,i)
				Stop3D()
				DisplaySprite(2,Picture(2)\x,Picture(2)\y)

			Case 3
				Start3D()
				DisplaySprite3D(0,0,0,255)
				DisplaySprite3D(1,Picture(1)\x,Picture(1)\y,255-i)
				DisplaySprite3D(2,Picture(2)\x,Picture(2)\y,i)
				Stop3D()

			EndSelect

			FlipBuffers()

			Repeat
				WaitWindowEvent(5)
				count+1
				If WindowEvent()=#WM_CHAR
					quit=999
				EndIf
			Until GetTickCount_()>pause

			If quit : Break : EndIf
		Next i

		If quit=0 : Delay(1500) : EndIf
	EndIf

	;MessageRequester(Str(count),"-"
EndProcedure

Main()
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Code: Select all


UsePNGImageDecoder()

Global Dim Lookup.f(255)
For I = 0 To 255
  Lookup(I) = 0.0+I/255
Next

Procedure Min(A, B)
  If A > B
    ProcedureReturn B
  EndIf
  ProcedureReturn A
EndProcedure

Structure RGBTRIPLECRUDE
  rgbBlue.c
  rgbGreen.c
  rgbRed.c
EndStructure

Procedure BlitImageTranlucent(Img1, Img2, Alpha)
  Protected Mem1, Mem2
  Protected Bmp.BITMAP
  Protected X, Y
  Protected *OldVal1.RGBTRIPLECRUDE ; Haha this is the trick
  Protected *OldVal2.RGBTRIPLECRUDE
  GetObject_(ImageID(Img1), SizeOf(BITMAP), @Bmp)
  Mem1 = Bmp\bmBits
  GetObject_(ImageID(Img2), SizeOf(BITMAP), @Bmp)
  Mem2 = Bmp\bmBits
  Target2 = Mem2 + Bmp\bmWidthBytes * Bmp\bmHeight-3
  For *OldVal2 = Mem2 To Target2 Step 3
    *OldVal1 = Mem1
    Mem1 + 3
    *OldVal1\rgbRed   = *OldVal1\rgbRed   * Lookup(255-Alpha) + *OldVal2\rgbRed    * Lookup(Alpha)
    *OldVal1\rgbGreen = *OldVal1\rgbGreen * Lookup(255-Alpha) + *OldVal2\rgbGreen  * Lookup(Alpha)
    *OldVal1\rgbBlue  = *OldVal1\rgbBlue  * Lookup(255-Alpha) + *OldVal2\rgbBlue   * Lookup(Alpha)
  Next
EndProcedure

OpenWindow(0, 0, 0, 512, 384, "", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_BorderLess)
CreateGadgetList(WindowID(0))

; Note, my png images are 24-bit
LoadImage(0, "Terragen___Astounding_by_tigaer.PNG")
LoadImage(1, "gallery_2_0_255974.png")
CreateImage(2, 512, 384, 24)

ResizeImage(0, 512, 384)
ResizeImage(1, 512, 384)


Debug "starting fade"

#Step = 25
For I = 0 To #Step
  StartDrawing(ImageOutput(2))
    DrawImage(ImageID(0), 0, 0)
  StopDrawing()
    BlitImageTranlucent(2, 1, 255/#Step*I)
  StartDrawing(WindowOutput(0))    
    DrawImage(ImageID(2), 0, 0)
  StopDrawing()
Next


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
  EndSelect
ForEver
User avatar
Michael Vogel
Addict
Addict
Posts: 2811
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Post by Michael Vogel »

THANK YOU!

Tronds code ist simple and fast (enough) and works on all notebooks (but mine) - And, I think, all JPGs are 24 Bit, so I can use this routine in my dia show now!

GREAT !

Code: Select all

UseJPEGImageDecoder()
UsePNGImageDecoder()

Structure RGBTRIPLECRUDE
	rgbBlue.c
	rgbGreen.c
	rgbRed.c
EndStructure

Procedure BlitImageTranlucent(Img1,Img2,Alpha)
	Protected Mem1,Mem2
	Protected Bmp.BITMAP
	Protected X,Y
	Protected *OldVal1.RGBTRIPLECRUDE ; Haha this is the trick
	Protected *OldVal2.RGBTRIPLECRUDE
	Protected Beta=255-Alpha
	GetObject_(ImageID(Img1),SizeOf(BITMAP),@Bmp)
	Mem1=Bmp\bmBits
	GetObject_(ImageID(Img2),SizeOf(BITMAP),@Bmp)
	Mem2=Bmp\bmBits
	Target2=Mem2 + Bmp\bmWidthBytes * Bmp\bmHeight-3
	For *OldVal2=Mem2 To Target2 Step 3
		*OldVal1=Mem1
		Mem1 + 3
		*OldVal1\rgbRed=(*OldVal1\rgbRed*Beta+*OldVal2\rgbRed*Alpha)>>8
		*OldVal1\rgbGreen=(*OldVal1\rgbGreen*Beta+*OldVal2\rgbGreen*Alpha)>>8
		*OldVal1\rgbBlue=(*OldVal1\rgbBlue*Beta+*OldVal2\rgbBlue*Alpha)>>8
	Next
EndProcedure

OpenWindow(0,0,0,776,384,"",#PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_BorderLess)
CreateGadgetList(WindowID(0))

; Note,my png images are 24-bit
;LoadImage(0,"Terragen___Astounding_by_tigaer.PNG")
;LoadImage(1,"gallery_2_0_255974.png")

LoadImage(0,"Data\1.jpg")
LoadImage(1,"Data\2.jpg")
;LoadImage(1,"Data\test.bmp")
CreateImage(2,512,384,24)
ResizeImage(0,512,384)
ResizeImage(1,512,384)


DisableDebugger

Debug "starting fade"

zeit-GetTickCount_()
#Step=255
For I=0 To 255 Step 5
	StartDrawing(ImageOutput(2))
	DrawImage(ImageID(0),0,0)
	StopDrawing()
	BlitImageTranlucent(2,1,i)
	StartDrawing(WindowOutput(0))
	DrawImage(ImageID(2),0,0)
	DrawImage(ImageID(1),520,0,256,192)
	DrawImage(ImageID(0),520,192,256,192)
	StopDrawing()
Next
zeit+GetTickCount_()

EnableDebugger
Debug zeit

Repeat
	Select WaitWindowEvent()
	Case #PB_Event_CloseWindow
		Break
	EndSelect
ForEver
Post Reply