TransformImage function - Flips and rotates an image

Share your advanced PureBasic knowledge/code with the community.
Axeman
User
User
Posts: 89
Joined: Mon Nov 03, 2003 5:34 am

TransformImage function - Flips and rotates an image

Post by Axeman »

This function will flip an image on the X and/or Y axis and can also rotate it clockwise in 90 degree increments. See the demo code at the bottom for an example (you'll need to supply your own "input_test.jpg" image with that demo code).

EDIT: Modified the code to support transparent images.

TEST IMAGES: https://imgur.com/a/V37AQvS
Either rename them to 'input_test.jpg' and 'input_test.png' or change the filenames in the code below.

Code: Select all

Procedure TransformImage( source_image, flip_mode = 0, rotation_mode = 0, free_source_image = 1 )
; Transforms the source image by first flipping and then rotating it as specified.
; Note that there's a lot of overlap between flip and rotation operations in terms of the end result. I've kept the operations separate though as it makes them easier to work with conceptually.
; Returns a zero on failure or the Purebasic ID of the new rotated image on success.
; PARAMETERS:-
; source_image - The Purebasic ID of the source image to be rotated.
; flip_mode - 0 = Don't flip (default). 1 = Flip vertically. 2 = Flip horizontally. 3 = Flip both vertically and horizontally.
; rotation_mode - 0 = Don't rotate (default). 1 = Rotate 90 degrees clockwise (default). 2 = Rotate 180 degrees clockwise. 3 = Rotate 270 degrees clockwise.
; free_source_image - 0 = Don't free source image. 1 = Free source image (default).

If IsImage( source_image ) = 0 : ProcedureReturn 0 : EndIf ; The source image was invalid, so abort.

source_image_width = ImageWidth( source_image )
source_image_height = ImageHeight( source_image )

If ( flip_mode < 0 ) Or ( flip_mode > 3 ) : ProcedureReturn 0 : EndIf ; Abort if the flip mode is invalid.

Select rotation_mode
	Case 0, 2 ; Rotate 0 or 180 degrees clockwise.
		output_image_width = source_image_width
		output_image_height = source_image_height
	Case 1, 3 ; Rotate 90 or 270 degrees clockwise.
		output_image_width = source_image_height
		output_image_height = source_image_width
	Default
		ProcedureReturn 0 ; The rotation mode was invalid, so abort.
EndSelect

; Create an array for the pixel data and copy the pixel data to it. This will also perform any flagged flip operations.
array_max_x = source_image_width - 1
array_max_y = source_image_height - 1
Dim TempPixelArray.l( array_max_x, array_max_y )
StartDrawing( ImageOutput( source_image ) )
DrawingMode( #PB_2DDrawing_AllChannels )
For y = 0 To array_max_y
	For x = 0 To array_max_x
		Select flip_mode
		Case 0 ; Don't flip.
			TempPixelArray( x, y ) = Point( x, y )
		Case 1 ; Flip vertically.
			TempPixelArray( x, y ) = Point( x, array_max_y - y )
		Case 2 ; Flip horizontally.
			TempPixelArray( x, y ) = Point( array_max_x - x, y )
		Case 3 ; Flip both vertically and horizontally.
			TempPixelArray( x, y ) = Point( array_max_x - x, array_max_y - y )
		EndSelect
	Next
Next
StopDrawing()

; Create the output image.
output_image = CreateImage( #PB_Any, output_image_width, output_image_height, ImageDepth( source_image ) ) : If output_image = 0 : ProcedureReturn 0 : EndIf
output_image_max_x = output_image_width - 1
output_image_max_y = output_image_height - 1

; Copy the pixel data from the pixel array to a new output image.
StartDrawing( ImageOutput( output_image ) )
DrawingMode( #PB_2DDrawing_AllChannels )

Select rotation_mode
	Case 0 ; Don't rotate.
		For y = 0 To array_max_y
			For x = 0 To array_max_x
				Plot( x, y , TempPixelArray( x, y ) )
			Next
		Next
		
	Case 1 ; Rotate 90 degrees clockwise.
		out_x = output_image_max_x
		For y = 0 To array_max_y
			out_y = 0
			For x = 0 To array_max_x
				Plot( out_x, out_y , TempPixelArray( x, y ) )
				out_y + 1
			Next
			out_x - 1
		Next
		
	Case 2 ; Rotate 180 degrees clockwise.
		out_y = output_image_max_y
		For y = 0 To array_max_y
			out_x = output_image_max_x
			For x = 0 To array_max_x
				Plot( out_x, out_y , TempPixelArray( x, y ) )
				out_x - 1
			Next
			out_y - 1
		Next
		
	Case 3 ; Rotate 270 degrees clockwise.
		out_x = 0
		For y = 0 To array_max_y
			out_y = output_image_max_y
			For x = 0 To array_max_x
				Plot( out_x, out_y , TempPixelArray( x, y ) )
				out_y - 1
			Next
			out_x + 1
		Next
		
EndSelect

StopDrawing()

If free_source_image : FreeImage( source_image ) : EndIf ; Free the source image if it is flagged to be freed.

ProcedureReturn output_image
EndProcedure



; ======================



; TEST IMAGES: https://imgur.com/a/V37AQvS
; Either rename them to 'input_test.jpg' and 'input_test.png' or change the filenames in the code below.



; *** JPEG DEMO CODE ***

UseJPEGImageDecoder()
UseJPEGImageEncoder()

source_image = LoadImage( #PB_Any, "input_test.jpg" )

output_image = TransformImage( source_image, 1, 1 ) ; source_image, flip_mode = 0, rotation_mode = 0, free_source_image = 1
; PARAMETERS:-
; source_image - The Purebasic ID of the source image to be rotated.
; flip_mode - 0 = Don't flip (default). 1 = Flip vertically. 2 = Flip horizontally. 3 = Flip both vertically and horizontally.
; rotation_mode - 0 = Don't rotate (default). 1 = Rotate 90 degrees clockwise (default). 2 = Rotate 180 degrees clockwise. 3 = Rotate 270 degrees clockwise.
; free_source_image - 0 = Don't free source image. 1 = Free source image (default).

If output_image = 0 : Debug( "ERROR: 'TransformImage' failed." ) : End : EndIf

SaveImage( output_image, "output_test.jpg", #PB_ImagePlugin_JPEG, 10 )



; ; *** PNG DEMO CODE (to test transparency) ***
; 
; UsePNGImageDecoder()
; UsePNGImageEncoder()
; 
; source_image = LoadImage( #PB_Any, "input_test.png" )
; 
; output_image = TransformImage( source_image, 1, 1 ) ; source_image, flip_mode = 0, rotation_mode = 0, free_source_image = 1
; ; PARAMETERS:-
; ; source_image - The Purebasic ID of the source image to be rotated.
; ; flip_mode - 0 = Don't flip (default). 1 = Flip vertically. 2 = Flip horizontally. 3 = Flip both vertically and horizontally.
; ; rotation_mode - 0 = Don't rotate (default). 1 = Rotate 90 degrees clockwise (default). 2 = Rotate 180 degrees clockwise. 3 = Rotate 270 degrees clockwise.
; ; free_source_image - 0 = Don't free source image. 1 = Free source image (default).
; 
; If output_image = 0 : Debug( "ERROR: 'TransformImage' failed." ) : End : EndIf
; 
; SaveImage( output_image, "output_test.png", #PB_ImagePlugin_PNG, 0, 32 )
Last edited by Axeman on Fri Aug 06, 2021 1:08 am, edited 1 time in total.
User avatar
Fangbeast
PureBasic Protozoa
PureBasic Protozoa
Posts: 4747
Joined: Fri Apr 25, 2003 3:08 pm
Location: Not Sydney!!! (Bad water, no goats)

Re: TransformImage function - Flips and rotates an image

Post by Fangbeast »

Good stuff, that's going to come in handy.
Amateur Radio, D-STAR/VK3HAF
User avatar
STARGÅTE
Addict
Addict
Posts: 2067
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: TransformImage function - Flips and rotates an image

Post by STARGÅTE »

The code would be more "handy", if it would work with transparent images.
You have to ask also for the ImageDepth, when you create the new image and copy the pixels using DrawingMode(#PB_2DDrawing_AllChannels)
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
Axeman
User
User
Posts: 89
Joined: Mon Nov 03, 2003 5:34 am

Re: TransformImage function - Flips and rotates an image

Post by Axeman »

STARGÅTE wrote: Thu Aug 05, 2021 9:51 am The code would be more "handy", if it would work with transparent images.
You have to ask also for the ImageDepth, when you create the new image and copy the pixels using DrawingMode(#PB_2DDrawing_AllChannels)
Fair point, but I needed this for a specific project that didn't need transparency. You can modify it to be however you need it.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: TransformImage function - Flips and rotates an image

Post by Kwai chang caine »

Thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Axeman
User
User
Posts: 89
Joined: Mon Nov 03, 2003 5:34 am

Re: TransformImage function - Flips and rotates an image

Post by Axeman »

Edited the code to add support for transparency, as STARGÅTE suggested. I've also set up a couple of test images (JPG and PNG with transparency) which are linked in the main post.
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: TransformImage function - Flips and rotates an image

Post by Kwai chang caine »

Tested the new code, with your PNG
Works nice here :D
Thanks a new time for sharing 8)
ImageThe happiness is a road...
Not a destination
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: TransformImage function - Flips and rotates an image

Post by davido »

@Axeman,
Thank you, very much, for taking the trouble to make your, already excellent, code support transparency. :D
DE AA EB
Post Reply