Overview

PerspectiveTransformEffectLib applies a 3D perspective transformation to an image by manipulating its four corner points, wrapping the FireMonkey TPerspectiveTransformEffect component. By moving the corners independently, you can create perspective tilts, skewing, and 3D-like distortions — useful for placing images on angled surfaces or creating dynamic visual effects.

PropertyDetails
LibraryPerspectiveTransformEffectLib
Prefixpersp_
WrapsTPerspectiveTransformEffect
Functions26
TypeVisual effect (geometric transform)
CategoryCountDescription
Creation / Destruction2Create and free effect
Corner Points16Get/set X,Y for 4 corners
Effect Control4Enabled and trigger get/set
Error Handling4Error codes and messages
⚠ Pixel Coordinates: This effect uses pixel coordinates, not normalized 0–1 values. You must set the corners based on your actual image dimensions. The library initializes with small default values that may make images invisible — always set all four corners explicitly.

Coordinate System

The effect defines the image shape by four corner points in pixel coordinates. For a 200×150 image, the default (undistorted) layout is:

╯ coordinate-diagram
(0,0) TopLeft ──────────── TopRight (200,0)
        │                      │
        │       I M A G E      │
        │                      │
(0,150) BottomLeft ──────── BottomRight (200,150)
CornerDefault XDefault YFunctions
Top-Left00persp_topleftx / persp_toplefty
Top-RightimgW0persp_toprightx / persp_toprighty
Bottom-RightimgWimgHpersp_bottomrightx / persp_bottomrighty
Bottom-Left0imgHpersp_bottomleftx / persp_bottomlefty
💡 Initialization Pattern: Always set all 8 values (4 corners × X,Y) to your image dimensions immediately after creation. Then modify individual corners to create perspective distortion.

Cross-Platform Support

PlatformSupport
Windows✅ Full support
Linux✅ Full support
Android✅ Full support

Creation & Destruction

persp#(parent#)

Creates a new perspective transform effect attached to the specified visual control.

ParameterTypeDescription
parent#PointerTarget visual control (e.g., image)
ReturnsPointerEffect handle, or 0 on failure

persp_free(effect#)

Destroys the effect and releases associated resources.

╯ create-perspective.bas
let imgW = 200
let imgH = 150

let persp# = persp#(img#)

' Always initialize all corners first!
persp_topleftx#(persp#, 0)
persp_toplefty#(persp#, 0)
persp_toprightx#(persp#, imgW)
persp_toprighty#(persp#, 0)
persp_bottomrightx#(persp#, imgW)
persp_bottomrighty#(persp#, imgH)
persp_bottomleftx#(persp#, 0)
persp_bottomlefty#(persp#, imgH)

Error Handling

FunctionSignatureDescription
persp_error()persp_error@Returns last error code (0 = none)
persp_errormsg$()persp_errormsg$@Returns last error message
persp_strerror$(code)persp_strerror$@nConverts error code to text
persp_clearerror()persp_clearerror@Clears the error state

Corner Points

Each of the four corners has independent X and Y coordinates, measured in pixels relative to the image dimensions.

Top-Left Corner

FunctionSignatureDescription
persp_topleftx#(effect#, value)persp_topleftx#@#nSet top-left X (pixels)
persp_topleftx(effect#)persp_topleftx@#Get top-left X
persp_toplefty#(effect#, value)persp_toplefty#@#nSet top-left Y (pixels)
persp_toplefty(effect#)persp_toplefty@#Get top-left Y

Top-Right Corner

FunctionSignatureDescription
persp_toprightx#(effect#, value)persp_toprightx#@#nSet top-right X (pixels)
persp_toprightx(effect#)persp_toprightx@#Get top-right X
persp_toprighty#(effect#, value)persp_toprighty#@#nSet top-right Y (pixels)
persp_toprighty(effect#)persp_toprighty@#Get top-right Y

Bottom-Right Corner

FunctionSignatureDescription
persp_bottomrightx#(effect#, value)persp_bottomrightx#@#nSet bottom-right X (pixels)
persp_bottomrightx(effect#)persp_bottomrightx@#Get bottom-right X
persp_bottomrighty#(effect#, value)persp_bottomrighty#@#nSet bottom-right Y (pixels)
persp_bottomrighty(effect#)persp_bottomrighty@#Get bottom-right Y

Bottom-Left Corner

FunctionSignatureDescription
persp_bottomleftx#(effect#, value)persp_bottomleftx#@#nSet bottom-left X (pixels)
persp_bottomleftx(effect#)persp_bottomleftx@#Get bottom-left X
persp_bottomlefty#(effect#, value)persp_bottomlefty#@#nSet bottom-left Y (pixels)
persp_bottomlefty(effect#)persp_bottomlefty@#Get bottom-left Y

Effect Control

FunctionSignatureDescription
persp_enabled#(effect#, value)persp_enabled#@#nEnable (1) or disable (0)
persp_enabled(effect#)persp_enabled@#Gets enabled state
persp_trigger#(effect#, trigger$)persp_trigger#@#$Sets trigger string
persp_trigger$(effect#)persp_trigger$@#Gets trigger string

Complete Examples

Example 1: Basic Perspective Tilt

╯ perspective-tilt.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let persp# = Pointer#(0)

let imgW = 200
let imgH = 150

frm# = form#("Perspective Demo", 400, 350)

img# = image#(frm#)
image_bounds#(img#, 100, 50, imgW, imgH)
image_load#(img#, "https://picsum.photos/200/150")

persp# = persp#(img#)

' Initialize to full image size
persp_topleftx#(persp#, 0)
persp_toplefty#(persp#, 0)
persp_toprightx#(persp#, imgW)
persp_toprighty#(persp#, 0)
persp_bottomrightx#(persp#, imgW)
persp_bottomrighty#(persp#, imgH)
persp_bottomleftx#(persp#, 0)
persp_bottomlefty#(persp#, imgH)

' Narrow at top — creates receding perspective
persp_topleftx#(persp#, 20)
persp_toprightx#(persp#, imgW - 20)

form_show(frm#)

Example 2: Interactive Corner Control

╯ interactive-perspective.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let persp# = Pointer#(0)
let trkTLX# = Pointer#(0)
let trkTRX# = Pointer#(0)
let lblTLX# = Pointer#(0)
let lblTRX# = Pointer#(0)

let imgW = 200
let imgH = 150

frm# = form#("Perspective Control", 500, 450)

img# = image#(frm#)
image_bounds#(img#, 150, 30, imgW, imgH)
image_load#(img#, "https://picsum.photos/200/150")

persp# = persp#(img#)
persp_topleftx#(persp#, 0)
persp_toplefty#(persp#, 0)
persp_toprightx#(persp#, imgW)
persp_toprighty#(persp#, 0)
persp_bottomrightx#(persp#, imgW)
persp_bottomrighty#(persp#, imgH)
persp_bottomleftx#(persp#, 0)
persp_bottomlefty#(persp#, imgH)

' Top-Left X slider
lblTLX# = label#(frm#, "Top-Left X: 0", 30, 200)
trkTLX# = trackbar#(frm#)
trackbar_bounds#(trkTLX#, 30, 225, 200, 25)
trackbar_max#(trkTLX#, 50)
trackbar_value#(trkTLX#, 0)
trackbar_onchange#(trkTLX#, "OnTLX")

' Top-Right X slider
lblTRX# = label#(frm#, "Top-Right X: 200", 260, 200)
trkTRX# = trackbar#(frm#)
trackbar_bounds#(trkTRX#, 260, 225, 200, 25)
trackbar_max#(trkTRX#, 50)
trackbar_value#(trkTRX#, 50)
trackbar_onchange#(trkTRX#, "OnTRX")

form_show(frm#)

function OnTLX(sender#) local x
  let x = trackbar_value(trkTLX#)
  persp_topleftx#(persp#, x)
  label_text#(lblTLX#, "Top-Left X: " + str$(x))
endfunction

function OnTRX(sender#) local x
  let x = 150 + trackbar_value(trkTRX#)
  persp_toprightx#(persp#, x)
  label_text#(lblTRX#, "Top-Right X: " + str$(x))
endfunction

Example 3: Preset Perspective Modes

╯ perspective-presets.bas
let frm# = Pointer#(0)
let img# = Pointer#(0)
let persp# = Pointer#(0)
let lblMode# = Pointer#(0)
let imgW = 200
let imgH = 150

frm# = form#("Perspective Presets", 450, 400)

img# = image#(frm#)
image_bounds#(img#, 125, 30, imgW, imgH)
image_load#(img#, "https://picsum.photos/200/150")

persp# = persp#(img#)
persp_topleftx#(persp#, 0)
persp_toplefty#(persp#, 0)
persp_toprightx#(persp#, imgW)
persp_toprighty#(persp#, 0)
persp_bottomrightx#(persp#, imgW)
persp_bottomrighty#(persp#, imgH)
persp_bottomleftx#(persp#, 0)
persp_bottomlefty#(persp#, imgH)

lblMode# = label#(frm#, "Mode: Normal", 175, 200)

let btn1# = button#(frm#, "Normal")
button_bounds#(btn1#, 30, 240, 80, 30)
button_onclick#(btn1#, "ModeNormal")

let btn2# = button#(frm#, "Tilt Top")
button_bounds#(btn2#, 120, 240, 80, 30)
button_onclick#(btn2#, "ModeTilt")

let btn3# = button#(frm#, "Tilt Left")
button_bounds#(btn3#, 210, 240, 80, 30)
button_onclick#(btn3#, "ModeLeft")

let btn4# = button#(frm#, "Skew")
button_bounds#(btn4#, 300, 240, 80, 30)
button_onclick#(btn4#, "ModeSkew")

form_show(frm#)

function ModeNormal(sender#)
  persp_topleftx#(persp#, 0)
  persp_toplefty#(persp#, 0)
  persp_toprightx#(persp#, imgW)
  persp_toprighty#(persp#, 0)
  persp_bottomrightx#(persp#, imgW)
  persp_bottomrighty#(persp#, imgH)
  persp_bottomleftx#(persp#, 0)
  persp_bottomlefty#(persp#, imgH)
  label_text#(lblMode#, "Mode: Normal")
endfunction

function ModeTilt(sender#)
  persp_topleftx#(persp#, 30)
  persp_toprightx#(persp#, imgW - 30)
  persp_bottomleftx#(persp#, 0)
  persp_bottomrightx#(persp#, imgW)
  label_text#(lblMode#, "Mode: Tilt Top")
endfunction

function ModeLeft(sender#)
  persp_toplefty#(persp#, 15)
  persp_bottomlefty#(persp#, imgH - 15)
  persp_toprighty#(persp#, 0)
  persp_bottomrighty#(persp#, imgH)
  label_text#(lblMode#, "Mode: Tilt Left")
endfunction

function ModeSkew(sender#)
  persp_topleftx#(persp#, 20)
  persp_toprighty#(persp#, 15)
  persp_bottomrightx#(persp#, imgW - 20)
  persp_bottomlefty#(persp#, imgH - 15)
  label_text#(lblMode#, "Mode: Skew")
endfunction

Best Practices

PracticeWhy
Always initialize all 8 corner valuesDefault values are small and may make the image invisible
Use image dimensions for defaultsSet corners to (0,0), (W,0), (W,H), (0,H) first
Move corners inward for receding perspectiveNarrowing the top creates "tilting away" illusion
Keep coordinates within image boundsExtreme values may produce unexpected distortions
Store image dimensions in variablesMakes corner calculations cleaner and reusable

Quick Reference

FunctionSignatureDescription
CREATION & DESTRUCTION
persp#(parent#)persp#@#Create effect
persp_free(effect#)persp_free@#Destroy effect
TOP-LEFT CORNER
persp_topleftx#(effect#, value)persp_topleftx#@#nSet top-left X
persp_topleftx(effect#)persp_topleftx@#Get top-left X
persp_toplefty#(effect#, value)persp_toplefty#@#nSet top-left Y
persp_toplefty(effect#)persp_toplefty@#Get top-left Y
TOP-RIGHT CORNER
persp_toprightx#(effect#, value)persp_toprightx#@#nSet top-right X
persp_toprightx(effect#)persp_toprightx@#Get top-right X
persp_toprighty#(effect#, value)persp_toprighty#@#nSet top-right Y
persp_toprighty(effect#)persp_toprighty@#Get top-right Y
BOTTOM-RIGHT CORNER
persp_bottomrightx#(effect#, value)persp_bottomrightx#@#nSet bottom-right X
persp_bottomrightx(effect#)persp_bottomrightx@#Get bottom-right X
persp_bottomrighty#(effect#, value)persp_bottomrighty#@#nSet bottom-right Y
persp_bottomrighty(effect#)persp_bottomrighty@#Get bottom-right Y
BOTTOM-LEFT CORNER
persp_bottomleftx#(effect#, value)persp_bottomleftx#@#nSet bottom-left X
persp_bottomleftx(effect#)persp_bottomleftx@#Get bottom-left X
persp_bottomlefty#(effect#, value)persp_bottomlefty#@#nSet bottom-left Y
persp_bottomlefty(effect#)persp_bottomlefty@#Get bottom-left Y
EFFECT CONTROL
persp_enabled#(effect#, value)persp_enabled#@#nEnable/disable
persp_enabled(effect#)persp_enabled@#Get enabled state
persp_trigger#(effect#, trigger$)persp_trigger#@#$Set trigger
persp_trigger$(effect#)persp_trigger$@#Get trigger
ERROR HANDLING
persp_error()persp_error@Last error code
persp_errormsg$()persp_errormsg$@Last error message
persp_strerror$(code)persp_strerror$@nCode to text
persp_clearerror()persp_clearerror@Clear error state

See Also

LibraryDescription
AffineTransformEffectLib2D transformations (scale, rotate, translate)
WrapEffectLibWrap/warp distortion
PinchEffectLibPinch/bulge distortion