Code archives/Graphics/Shadow from an image

This code has been declared by its author to be Public Domain code.

Download source code

Shadow from an image by aCiD22003
This function creates a shadow an image, by reading the "red" value and setting it to all three rgb values, amking a grey. its reasonably fast aswell.
Function GenerateShadow(img, r = 255, g = 0, b = 255)
	setbuffer imagebuffer(img)
	lockbuffer
	for x = 0 to imagewidth(img) - 1
		for y = 0 to imageheight(img) - 1
			col = readpixelfast (x, y)
			color 0, 0, col
			if not (colorred() = r and colorgreen() = g and colorblue() = 255)
				color colorred(), colorred(), colorred()
				plot x, y
			endif
		next
	next
	unlockbuffer
	setbuffer backbuffer()
	
	return img
end function

Comments

bobbo2004
Hmmm... it doesn't work on BlitzPlus.
First: you are writing on the img, it is better to create a copy.
Second: you should set the buffer back to the original Buffer, not to BackBuffer().
Third: you can't use Plot on a locked buffer, you must unlock it first.

; SHADOW GENERATOR, the mask color is not affected
Function GenerateShadow(sourceImg, r = 0, g = 0, b =0)
	
	img=CopyImage(sourceImg)
	
	originalBuffer=GraphicsBuffer()
	
	SetBuffer ImageBuffer(img)
	LockBuffer
	For x = 0 To ImageWidth(img) - 1
		For y = 0 To ImageHeight(img) - 1
		
			col = ReadPixelFast (x, y)
			
			; convert to rgb values
			r1=(col Shl 8)Shr 24
			g1=(col Shl 16)Shr 24
			b1=(col Shl 24)Shr 24
						
			If Not (r1 = r And g1 = g And b1 = b)
			
				UnlockBuffer

				Color r1,r1,r1
								
				Plot x,y
				;WritePixelFast x,y,calculatenewcolor
				LockBuffer
				
			EndIf
		Next
	Next
	
	UnlockBuffer
	SetBuffer originalBuffer
	
	Return img
	
End Function


Use WritePixelFast would be much better than Plot of course, just let me find some time to code it.
This is more a grayscale converter than a real shadow... but it is easier to convert it into a shadow, you must use always the same r g b gray value instead of converting each rgb color to a different grayscale level.


bobbo2004
Here is the final version of the functions:
GenerateShadow() for genearting a shadow with a unique gray color, and GenerateGrayScale() for a grayscale version of the orignal image

There is also a small example to test it, just change the path and maskcolor of your image (I tried with a red maskcolor).

Graphics 640,480,16,2
SetBuffer BackBuffer()

myImage=LoadImage("gfx\zelda1.bmp")
MaskImage myImage,255,0,0

myShadow=GenerateShadow(myImage,255,0,0,80)
myGrayScale=GenerateGrayScale(myImage,255,0,0)


While KeyDown(1)=0

 Cls
 
 
 DrawImage myShadow,MouseX(),MouseY()
 DrawImage myGrayScale,MouseX()-100,MouseY()-100
 DrawImage myImage,0,0
  
 Flip
 
Wend

End

; SHADOW GENERATOR, the mask color is not affected
; coded by Roberto Comuniello, 2004, www.sintetik.it
; sourceImg: source Image handle
; r: red mask color
; g: green mask color
; b: blue mask color
; shadowLevel: intensity of shadow (grey color) from 0 to 255
Function GenerateShadow(sourceImg, r = 0, g = 0, b =0, shadowLevel=100)

	img=CopyImage(sourceImg)
	myWidth=ImageWidth(img)-1
	myHeight=ImageHeight(img)-1
	myMask=GetRGB(r,g,b)
	myShadow=GetRGB(shadowLevel,shadowLevel,shadowLevel)
	
	originalBuffer=GraphicsBuffer()
	SetBuffer ImageBuffer(img)
	LockBuffer
	
	For x = 0 To myWidth
		For y = 0 To myHeight
		
			col = ReadPixelFast (x, y)
								
			If Not (col=myMask)
			
				WritePixelFast x,y,myShadow
								
			EndIf
		Next
	Next
	
	UnlockBuffer
	SetBuffer originalBuffer
	
	Return img
	
End Function

; GRAYSCALE GENERATOR, the mask color is not affected
; the grayscale is based on the red color of each pixels
; coded by Roberto Comuniello, 2004, www.sintetik.it
; it works fine even if you have a red mask (255,0,0)
; sourceImg: source Image handle
; r: red mask color
; g: green mask color
; b: blue mask color
Function GenerateGrayScale(sourceImg, r = 0, g = 0, b =0)

	img=CopyImage(sourceImg)
	myWidth=ImageWidth(img)-1
	myHeight=ImageHeight(img)-1
	myMask=GetRGB(r,g,b)
		
	originalBuffer=GraphicsBuffer()
	SetBuffer ImageBuffer(img)
	LockBuffer
	
	For x = 0 To myWidth
		For y = 0 To myHeight
		
			col = ReadPixelFast (x, y)
								
			If Not (col=myMask)
			
				r1=GetR(col)
				myNewColor=GetRGB(r1,r1,r1)		
				WritePixelFast x,y,myNewColor
								
			EndIf
		Next
	Next
	
	UnlockBuffer
	SetBuffer originalBuffer
	
	Return img
	
End Function

; general purpose RGB converter functions
Function GetRGB(R,G,B)
 Return $FF000000 Or R Shl 16 Or G Shl 8 Or B
End Function

Function GetR(RGB)
 Return RGB Shr 16 And %11111111
End Function

Function GetG(RGB)
 Return RGB Shr 8 And %11111111
End Function

Function GetB(RGB)
 Return RGB And %11111111
End Function



bobbo2004
Here is the final version, with shadow transparency as an option! Simple and quite good to see. Just try it with a tiled background as I did.
Maybe it should be optimized but it is already quite good.

Graphics 640,480,16,2
SetBuffer BackBuffer()

myImage=LoadImage("gfx\zelda1.bmp")
MaskImage myImage,255,0,0

myShadow=GenerateShadow(myImage,255,0,0,80,1)
myGrayScale=GenerateGrayScale(myImage,255,0,0)

myTile=LoadImage("gfx\tile.bmp")



While KeyDown(1)=0

 TileBlock myTile
  
 DrawImage myShadow,MouseX(),MouseY()
 DrawImage myGrayScale,MouseX()-100,MouseY()-100
 DrawImage myImage,0,0
  
 Flip
 
Wend

End

; SHADOW GENERATOR, the mask color is not affected
; coded by Roberto Comuniello, 2004, www.sintetik.it
; sourceImg: source Image handle
; r: red mask color
; g: green mask color
; b: blue mask color
; shadowLevel: intensity of shadow (grey color) from 0 to 255
; transparent flag: true or false (a fake, cheap transparency effect made with mask color)
Function GenerateShadow(sourceImg, r = 0, g = 0, b =0, shadowLevel=100, transparent=False)

	img=CopyImage(sourceImg)
	myWidth=ImageWidth(img)-1
	myHeight=ImageHeight(img)-1
	myMask=GetRGB(r,g,b)
	myShadow=GetRGB(shadowLevel,shadowLevel,shadowLevel)
	
	originalBuffer=GraphicsBuffer()
	SetBuffer ImageBuffer(img)
	LockBuffer
	
	flipper=False
	
	For x = 0 To myWidth
	
		flipper=Not flipper
	
		For y = 0 To myHeight
		
			col = ReadPixelFast (x, y)
								
			If Not (col=myMask) Then
				
				If flipper Then
					myCondition=(y Mod 2)
				Else
					myCondition=(Not(y Mod 2))
				End If
						
				If transparent And myCondition Then
					theShadow=myMask
				Else
					theShadow=myShadow
				End If
				
				WritePixelFast x,y,theShadow
								
			EndIf
		Next
	Next
	
	UnlockBuffer
	SetBuffer originalBuffer
	
	Return img
	
End Function

; GRAYSCALE GENERATOR, the mask color is not affected
; the grayscale is based on the red color of each pixel
; coded by Roberto Comuniello, 2004, www.sintetik.it
; it works fine even if you have a red mask (255,0,0)
; sourceImg: source Image handle
; r: red mask color
; g: green mask color
; b: blue mask color
Function GenerateGrayScale(sourceImg, r = 0, g = 0, b =0)

	img=CopyImage(sourceImg)
	myWidth=ImageWidth(img)-1
	myHeight=ImageHeight(img)-1
	myMask=GetRGB(r,g,b)
		
	originalBuffer=GraphicsBuffer()
	SetBuffer ImageBuffer(img)
	LockBuffer
	
	For x = 0 To myWidth
		For y = 0 To myHeight
		
			col = ReadPixelFast (x, y)
								
			If Not (col=myMask)
			
				r1=GetR(col)
				myNewColor=GetRGB(r1,r1,r1)		
				WritePixelFast x,y,myNewColor
								
			EndIf
		Next
	Next
	
	UnlockBuffer
	SetBuffer originalBuffer
	
	Return img
	
End Function

; general purpose RGB converter functions
Function GetRGB(R,G,B)
 Return $FF000000 Or R Shl 16 Or G Shl 8 Or B
End Function

Function GetR(RGB)
 Return RGB Shr 16 And %11111111
End Function

Function GetG(RGB)
 Return RGB Shr 8 And %11111111
End Function

Function GetB(RGB)
 Return RGB And %11111111
End Function



aCiD22004
wtf was i thinking using plot?! this was quite a whiel ago mind, and must of the comments in the first post would never have occoured :P thanks for the alpha shadow one (i had a function like that but never uploaded it :D) Should be useful to everyone else i think


Code Archives Forum