News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

Turn Image (Rotate an Image 90's degrees)

Started by kevin, February 09, 2023, 06:01:37 AM

Previous topic - Next topic

kevin

 Turn Image (Rotate Image 90's degrees)


  This PlayBASIC source code example will rotate an image by 90 degrees, turning it clock wise.  

  The method used in this example is a little lower level than normal, here we're introducing the concept of the accessing pixel data directly using the peek and poke commands.

 You see an image is just a block of memory that we interpret that data within as pixel colour data.  Different types of images store the pixel data differently but in this example we're assuming the pixels are 32bit Integers.   Which is convenient as that means we can use the PeekINT and PokeINT commands to read and write pixel data.  

 The logic of the Turn function is boils down this.  First we grab the image that was passed ins size and it's address inside your computers memory.   Once we have the size, we create an output image that swaps the width and height.  

  In the conversion loop we walk through the source image from the top left hand corner (pixel 0X, 0Y)  and write these pixels down the destination image.     So the top row of pixels from the source image become the right hand column in the destination image..      

  To run the code you'll need to supply it with an image to load, which it'll scale down to fit on the screen for demo purposes.   Anyway..  do with it what you want !





PlayBASIC Code: [Select]
   cls $ff00ff

File$="---FILE---NAME---OF-IMAGE-ON-YOUR-COMPUTER"

Img= LoadNewIMage(File$,2)
scaleimage img,640,400,1
drawimage img,0,0,false

Img2=Turn_IMage(img)

drawimage img2,640,0,false

sync
waitkey


// Compute Src Modulo


Function Turn_IMage(SrcIMAGE)

Width=GetIMageWidth(SrcIMAGE)
Height=GetIMageHeight(SrcIMAGE)

SrcPTR =GetImagePTR(SrcIMAGE)
SrcMODULO =GetImagePITCH(SrcIMAGE)

DestIMage= NewFXIMage(Height,Width)
DestPTR =GetImagePTR(DestIMAGE)
DestMODULO =GetImagePITCH(DestIMAGE)

For ylp=0 to Height-1

// Very going to move through this image across
SrcSTEP = 4

// compute the address ot pixel 0,0
SrcRowPTR = SrcPTR+(SrcMODULO*ylp)

// output on the right / top of dest
DestRowPTR = DestPTR+((Height-ylp-1)*4)
DestSTEP = DestMODULO

For xlp=0 to Width-1
ThisARGB= PeekINT(SrcROWPTR)
SrcROWPTR+=SrcSTEP

PokeINT DestROWPTR,ThisARGB
DestROWPTR+=DestSTEP
next
next

EndFunction DestIMage





   Turn Image Unrolled

      Here's a version of the source code that includes two versions of the turn Image function.  The first is a slightly cleaned up version of the oe above while the second is unrolled to copy 16 pixel blocks at a time.    What this does is removes the FOR/NEXT cost per pixel.   So in the first version we're computing a inner For Xlp /  for every pixel procesed but in the second one we've only loop a 16th of the time..  

     Speed wise we gain around 10% (more in older versions of PB) while really having an impact upon the complexity of the source code.



PlayBASIC Code: [Select]
   openscreen 1280,600,32,1

cls $ff00ff

File$="---FILE---NAME---OF-IMAGE-ON-YOUR-COMPUTER"

Img= LoadNewIMage(File$,2)
// scaleimage img,640,400,1

For Frames#=1 to 100

// Clear Screen to RGB(255,0,255) which is the same as $FF00FF in hex
cls $ff00ff

// draw none rotated iage
drawimage img,0,0,false

// call the turn image
ts=timer()
Img2=Turn_IMage(img)
t1+=timer()-ts
print t1/frames#
if GetIMageStatus(Img2) then drawimage img2,400,0,false


// Call Turn image unrolled
ts=timer()
Img3=Turn_IMage_UNROLLED(img)
t2+=timer()-ts
print t2/frames#
if GetIMageStatus(Img3) then drawimage img3,800,0,false


// delete the two newly created images so
deleteimage img2
deleteimage img3


// Flip the back buffer to the front
sync

// loop back to the FOR statement bump the counter and it reachs it's
// upper limit
next


// Once the loop is complete
print " For Turn Image:"+str$(t1)
print " Turn Image UNrolled:"+str$(t2)

Speed#= T2/float(T1) * 100
print " Unrolled is "+str$(100-Speed#)+"% faster "

print "DONE"
sync
waitkey


// -------------------------------------------------------------
// -------------------------------------------------------------
// ------------------>> TURN IMAGE (32bit) --------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// This function creates a rotated version of the source image
// The output image is returned as a new image index. The
// source image is left intact.
// -------------------------------------------------------------



Function Turn_IMAGE(SrcIMAGE)

// check if the source image exist, if not EXIT
if GetImageStatus(SrcIMAGE)=false then ExitFunction 0

// get it's size
SrcWidth =GetIMageWidth(SrcIMAGE)
SrcHeight =GetIMageHeight(SrcIMAGE)
SrcDEPTH =GetIMageDEPTH(SrcIMAGE)

// Check if this is a 32bit surface, if not, exit
if SrcDEPTH<>32 then ExitFunction 0
SrcPTR =GetImagePTR(SrcIMAGE)
SrcMODULO =GetImagePITCH(SrcIMAGE)


// Create output image
DestIMage = NewFXIMage(SrcHeight,SrcWidth)
DestPTR =GetImagePTR(DestIMAGE)
DestMODULO =GetImagePITCH(DestIMAGE)

For ylp=0 to SrcHeight-1

// Very going to move through this image across
SrcSTEP = 4

// compute the address ot pixel 0 along each row
// within the source image
SrcRowPTR = SrcPTR+(SrcMODULO*ylp)

// output on the right / top of dest, moving down
// for each column
DestRowPTR = DestPTR+((SrcHeight-ylp-1)*4)
DestSTEP = DestMODULO

For xlp=0 to SrcWidth-1
ThisARGB= PeekINT(SrcROWPTR)
SrcROWPTR+=SrcSTEP

PokeINT DestROWPTR,ThisARGB
DestROWPTR+=DestSTEP
next
next

EndFunction DestIMage



// -------------------------------------------------------------
// -------------------------------------------------------------
// ------------------>> TURN IMAGE UNROLLED (32bit) --------------------
// -------------------------------------------------------------
// -------------------------------------------------------------
// This function creates a rotated version of the source image
// The output image is returned as a new image index. The
// source image is left intact.
// -------------------------------------------------------------



Function Turn_IMAGE_UNROLLED(SrcIMAGE)

// check if the source image exist, if not EXIT
if GetImageStatus(SrcIMAGE)=false then ExitFunction 0

// get it's size
SrcWidth =GetIMageWidth(SrcIMAGE)
SrcHeight =GetIMageHeight(SrcIMAGE)
SrcDEPTH =GetIMageDEPTH(SrcIMAGE)

// Check if this is a 32bit surface, if not, exit
if SrcDEPTH<>32 then ExitFunction 0
SrcPTR =GetImagePTR(SrcIMAGE)
SrcMODULO =GetImagePITCH(SrcIMAGE)

// The number of pixels left over at the end of a row
Login required to view complete source code



    PlayBASIC Documentation:

   - PeekINT
   - PokeINT