Page 1 of 1

What's wrong with my alpha blend routine?

Posted: Fri Jul 28, 2006 10:04 pm
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

Posted: Fri Jul 28, 2006 10:33 pm
by srod
A quick observation; you've set H2 to equal ImageWidth(), should that not be ImageHeight() etc?

Posted: Sat Jul 29, 2006 5:16 am
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

Posted: Sat Jul 29, 2006 10:54 am
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!

Posted: Mon Jul 31, 2006 9:52 am
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()

Posted: Mon Jul 31, 2006 12:25 pm
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

Posted: Mon Aug 07, 2006 10:15 am
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