Simple image processing

Share your advanced PureBasic knowledge/code with the community.
Balatro
User
User
Posts: 15
Joined: Sun Oct 05, 2003 2:27 pm

Simple image processing

Post by Balatro »

Hello,

here are some simple but fairly effective procedures for image manipulation: 180 degrees rotation, 90 degrees rotation, mirror, flip, greyscaling, inversion, image brightness and image contrast. There are probably more elegant ways to implement these things, and certainly more optimized ones (using lookup tables etc)... but maybe someone will have use for these.

Note: The alpha-macros are not used in these procedures but I included them anyway to show one possible way of blending two color values. If you need to blend colors inside an image processing procedure, it is best to use a macro anway. I'll post my noise and matrix filter -procedures later to show how I use them.

Code: Select all

EnableExplicit

;*********************************************************************
;*
;*
;-   MACROS
;*
;*
;{********************************************************************

Macro RGB(Red, Green, Blue)

    ((Blue << 8 + Green) << 8 ) + Red
    
EndMacro

Macro Red(Color)

	Color & 16777215 >> 16

EndMacro

Macro Green(Color)

	(Color & 65535) >> 8

EndMacro

Macro Blue(Color)

	Color >> 16

EndMacro

Macro Normalize(Red, Green, Blue)

	If Red < 0
		
		Red = 0
		
	ElseIf Red > 255
	
		Red = 255
		
	EndIf
        
    If Green < 0
    
    	Green = 0
    	
    ElseIf Green > 255
    
    	Green = 255
    	
    EndIf
    
    If Blue < 0
    
    	Blue = 0
    
    ElseIf Blue > 255
    
    	Blue = 255
    	
    EndIf

EndMacro

;}********************************************************************

;*********************************************************************
;*
;*
;-   ALPHA
;*
;*
;{********************************************************************

Macro Blend75(ColorA, Color)

	RGB((Red(ColorA) >> 1 + Red(ColorA) >> 2 + Red(ColorO) >> 2), (Green(ColorA) >> 1 + Green(ColorA) >> 2 + Green(ColorO) >> 2), (Blue(ColorA) >> 1 + Blue(ColorA) >> 2 + Blue(ColorO) >> 2))

EndMacro

Macro Blend50(ColorA, ColorO)

	RGB((Red(ColorA) >> 1 + Red(ColorO) >> 1), (Green(ColorA) >> 1 + Green(ColorO) >> 1), (Blue(ColorA) >> 1 + Blue(ColorO) >> 1))

EndMacro

Macro Blend(ColorA, ColorO, Alpha)

	RGB(((Red(ColorA) * Alpha + Red(ColorO) * (256 - Alpha)) >> 8), ((Green(ColorA) * Alpha + Green(ColorO) * (256 - Alpha)) >> 8), ((Blue(ColorA) * Alpha + Blue(ColorO) * (256 - Alpha)) >> 8))

EndMacro

;}********************************************************************

;*********************************************************************
;*
;*
;-   MEMORY
;*
;*
;{********************************************************************

Procedure CopyImageToMemory(ImageNumber, Memory)

	Protected TemporaryDC.L, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO

    TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
    
    GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)
       
    TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
    TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
    TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
    TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
    TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
    TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB

    GetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)

    DeleteDC_(TemporaryDC)
    
EndProcedure

Procedure CopyMemoryToImage(Memory, ImageNumber)
  
  	Protected TemporaryDC.L, TemporaryBitmap.BITMAP, TemporaryBitmapInfo.BITMAPINFO
  
    TemporaryDC = CreateDC_("DISPLAY", #Null, #Null, #Null)
    
    GetObject_(ImageID(ImageNumber), SizeOf(BITMAP), TemporaryBitmap.BITMAP)

    TemporaryBitmapInfo\bmiHeader\biSize        = SizeOf(BITMAPINFOHEADER)
    TemporaryBitmapInfo\bmiHeader\biWidth       = TemporaryBitmap\bmWidth
    TemporaryBitmapInfo\bmiHeader\biHeight      = -TemporaryBitmap\bmHeight
    TemporaryBitmapInfo\bmiHeader\biPlanes      = 1
    TemporaryBitmapInfo\bmiHeader\biBitCount    = 32
    TemporaryBitmapInfo\bmiHeader\biCompression = #BI_RGB
   
    SetDIBits_(TemporaryDC, ImageID(ImageNumber), 0, TemporaryBitmap\bmHeight, Memory, TemporaryBitmapInfo, #DIB_RGB_COLORS)
    
    DeleteDC_(TemporaryDC)
  
EndProcedure

;}********************************************************************

;*********************************************************************
;*
;*
;-   ROTATION
;*
;*
;{********************************************************************

Procedure Rotate180(ImageNumber)

	Protected MemorySize, *MemoryOrigin, *MemoryTarget, Counter

	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*MemoryOrigin = AllocateMemory(MemorySize)
	*MemoryTarget = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *MemoryOrigin)
	
	For Counter = 0 To MemorySize - 1 Step 4
			
		PokeL(*MemoryTarget + MemorySize - Counter - 4, PeekL(*MemoryOrigin + Counter))
			
	Next

	CopyMemoryToImage(*MemoryTarget, ImageNumber)

	FreeMemory(*MemoryOrigin)
	FreeMemory(*MemoryTarget)

EndProcedure

Procedure Rotate90(ImageNumber)

	Protected TemporaryImage, MemorySizeOrigin, MemorySizeTarget, *MemoryOrigin, *MemoryTarget
	
	Protected Origin, Target, W, H, X, Y

	TemporaryImage = CreateImage(#PB_Any, ImageHeight(ImageNumber), ImageWidth(ImageNumber), ImageDepth(ImageNumber))

	MemorySizeOrigin = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)
	MemorySizeTarget = (ImageWidth(TemporaryImage) * ImageHeight(TemporaryImage) << 2)

	*MemoryOrigin = AllocateMemory(MemorySizeOrigin)
	*MemoryTarget = AllocateMemory(MemorySizeTarget)
	
	CopyImageToMemory(ImageNumber, *MemoryOrigin)
		
	W = ImageWidth(ImageNumber)
	H = ImageHeight(ImageNumber)
		
	For Y = 0 To H - 1
	
		For X = 0 To W - 1
		
 			Origin = (Y * W + X) << 2
 			
 			Target = ((H - Y - 1) + (X * H)) << 2

			PokeL(*MemoryTarget + Target, PeekL(*MemoryOrigin + Origin))

		Next
	
	Next

	CopyMemoryToImage(*MemoryTarget, TemporaryImage)

	FreeImage(ImageNumber)

	CopyImage(TemporaryImage, ImageNumber)
	
	FreeImage(TemporaryImage)

	FreeMemory(*MemoryOrigin)
	FreeMemory(*MemoryTarget)

EndProcedure

Procedure Mirror(ImageNumber)
 
 	Protected MemorySize, *MemoryOrigin, *MemoryTarget
 	
 	Protected Origin, Target, W, H, X, Y
 
 	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*MemoryOrigin = AllocateMemory(MemorySize)
	*MemoryTarget = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *MemoryOrigin)
	
	W = ImageWidth(ImageNumber)
	H = ImageHeight(ImageNumber)	
	
	For Y = 0 To H - 1
	
		For X = 0 To W - 1

			Origin = (Y * W + X) << 2

			Target = ((W - X) + (Y * W - 1)) << 2

			PokeL(*MemoryTarget + Target, PeekL(*MemoryOrigin + Origin))

		Next
	
	Next
	
	CopyMemoryToImage(*MemoryTarget, ImageNumber)

	FreeMemory(*MemoryOrigin)
	FreeMemory(*MemoryTarget)
 
EndProcedure

Procedure Flip(ImageNumber)
 
  	Protected MemorySize, *MemoryOrigin, *MemoryTarget
 	
 	Protected Origin, Target, W, H, X, Y
 
 	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*MemoryOrigin = AllocateMemory(MemorySize)
	*MemoryTarget = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *MemoryOrigin)
	
	W = ImageWidth(ImageNumber)
	H = ImageHeight(ImageNumber)	
	
	For Y = 0 To H - 1
	
		For X = 0 To W - 1

			Origin = (Y * W + X) << 2
			
			Target = ((H - Y - 1) * W + X) << 2

			PokeL(*MemoryTarget + Target, PeekL(*MemoryOrigin + Origin))

		Next
	
	Next
	
	CopyMemoryToImage(*MemoryTarget, ImageNumber)

	FreeMemory(*MemoryOrigin)
	FreeMemory(*MemoryTarget)
 
EndProcedure

;}********************************************************************

;*********************************************************************
;*
;*
;-   COLOR
;*
;*
;{********************************************************************

Procedure Greyscale(ImageNumber)

  	Protected MemorySize, *Memory
 	
 	Protected Counter, Color

	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*Memory = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *Memory)
	
	For Counter = 0 To MemorySize - 1 Step 4
				
		Color = PeekL(*Memory + Counter)
				
		Color = (Red(Color) + Green(Color) + Blue(Color)) / 3
				
		PokeL(*Memory + Counter, RGB(Color, Color, Color))

	Next

	CopyMemoryToImage(*Memory, ImageNumber)

	FreeMemory(*Memory)

EndProcedure

Procedure Invert(ImageNumber)

  	Protected MemorySize, *Memory
 	
 	Protected Counter, Color, Red, Green, Blue

	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*Memory = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *Memory)
	
	For Counter = 0 To MemorySize - 1 Step 4
				
		Color = PeekL(*Memory + Counter)
				
		Red = 255 - Red(Color)
		Green = 255 - Green(Color)
		Blue = 255 - Blue(Color)
				
		PokeL(*Memory + Counter, RGB(Red, Green, Blue))

	Next

	CopyMemoryToImage(*Memory, ImageNumber)

	FreeMemory(*Memory)

EndProcedure

Procedure Brightness(ImageNumber, Brightness)

  	Protected MemorySize, *Memory
 	
 	Protected Counter, Color, Red, Green, Blue

	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*Memory = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *Memory)
	
	For Counter = 0 To MemorySize - 1 Step 4
				
		Color = PeekL(*Memory + Counter)
				
		Red = Red(Color) + Brightness
		Green = Green(Color) + Brightness
		Blue = Blue(Color) + Brightness
				
		Normalize(Red, Green, Blue)
				
		PokeL(*Memory + Counter, RGB(Red, Green, Blue))

	Next

	CopyMemoryToImage(*Memory, ImageNumber)

	FreeMemory(*Memory)

EndProcedure

Procedure Contrast(ImageNumber, Contrast.F)

  	Protected MemorySize, *Memory
 	
 	Protected Counter, Color, Red, Green, Blue

	MemorySize = (ImageWidth(ImageNumber) * ImageHeight(ImageNumber) << 2)

	*Memory = AllocateMemory(MemorySize)
	
	CopyImageToMemory(ImageNumber, *Memory)
	
	For Counter = 0 To MemorySize - 1 Step 4
				
		Color = PeekL(*Memory + Counter)
		
		Red = ((Red(Color) - 128) * Contrast) + 128
		Green = ((Green(Color) - 128) * Contrast) + 128
		Blue = ((Blue(Color) - 128) * Contrast) + 128
		
		Normalize(Red, Green, Blue)
				
		PokeL(*Memory + Counter, RGB(Red, Green, Blue))

	Next

	CopyMemoryToImage(*Memory, ImageNumber)

	FreeMemory(*Memory)

EndProcedure

;}********************************************************************