Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Post your FreeBASIC tips and tricks here. Please don’t post your code without including an explanation.
D.J.Peters
Posts: 7949
Joined: May 28, 2005 3:28

Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby D.J.Peters » Jan 07, 2019 22:10

It's fast works with all video modes and you can use all blitter modes like PSET, ALPHA, Custom ...

Joshy

file: mirror.bi

Code: Select all

#ifndef __MIRROR_BI__
#define __MIRROR_BI__
' mirror an image or the screen (img=0)
' horizontal or vertical of course you can combine different calls
' e.g. step 1 vertical step 2 horizontal, step 3 vertical ...

' I'm using only GET and PUT so you can use XOR,PSET,ALPHA ...
sub Mirror(byval img as any ptr=0, byval iHorizontal as integer=1)
  static as integer oWidth=0,oHeight=0,oHorizontal=0
  static as any ptr imgA=0,imgB=0
  dim as integer iWidth=any,iHeight=any
  dim as integer xSize=any,ySize=any,xStart=any,yStart,xStep=any,yStep=any
  dim as integer x1=any,x2=any,y1=any,y2=any,iStart=any,iEnd=any
  if img=0 then ' screen
    if ScreenPtr()=0 then exit sub
    ScreenInfo(iWidth,iHeight)
  else ' image 
    if ImageInfo(img,iWidth,iHeight) then exit sub
  end if
  if iHorizontal then iHorizontal=1
  ' realloc images only if the resolution or the mirror axis are changed !
  if iWidth<>oWidth or iHeight<>oHeight or oHorizontal<>iHorizontal then
    oWidth = iWidth : oHeight = iHeight : oHorizontal = iHorizontal
    if iHorizontal then
      xSize=iWidth : ySize=1
    else
      xSize=1: ySize=iHeight
    end if
    if ImgA then ImageDestroy ImgA:ImgA=0
    if ImgB then ImageDestroy ImgB:ImgB=0
    imgA=imageCreate(xSize,ySize)
    imgB=imageCreate(xSize,ySize)
  end if 
  ' now the magic :lol:
  xSize-=1 : ySize-=1
  if iHorizontal then
    x1=0:x2=0:y1=0:y2=iHeight-1 : xStep=0: yStep=1 : iStart=0:iEnd=iHeight-1
  else
    x1=0:x2=iWidth-1:y1=0:y2=0 : xStep=1: yStep=0 : iStart=0:iEnd=iWidth-1
  end if
  while iStart<=iEnd
    Get img,(x1,y1)-step(xSize,ySize), imgA
    Get img,(x2,y2)-step(xSize,ySize), imgB
    Put img,(x1,y1),imgB,pset
    Put img,(x2,y2),imgA,pset
    x1+=xStep : x2-=xStep
    y1+=yStep : y2-=yStep
    iStart+=1 : iEnd-=1
  wend 

end sub 

#endif ' __MIRROR_BI__
Last edited by D.J.Peters on Jan 09, 2019 5:17, edited 4 times in total.
D.J.Peters
Posts: 7949
Joined: May 28, 2005 3:28

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby D.J.Peters » Jan 07, 2019 22:11

test_screen.bas

Code: Select all

#include "mirror.bi"

' test for image

'screenres 640,480,8,2
'screenres 640,480,16,2
screenres 640,480,32,2

screenset 1,0
dim as integer w=200,h=200
var img = ImageCreate(w,h,255)
for i as integer= 1 to 10
  if (i and 1=1) then
    circle img,(rnd*w,rnd*h),1+h*0.24,culng(2^31*rnd()),,,,F
  else
    circle img,(rnd*w,rnd*h),1+h*0.24,culng(2^31*rnd())
  end if
  if (i and 1=1) then
    line img,(rnd*w,rnd*h)-(rnd*w,rnd*h),culng(2^31*rnd()),BF
  else
    line img,(rnd*w,rnd*h)-(rnd*w,rnd*h),culng(2^31*rnd())
  end if
next 


draw string img,(8     ,8       ), "Top Left"    ,254
draw string img,(100-10*8,8     ), "Top Right"   ,culng(2^31*rnd())
draw string img,(100-13*8,100-16), "Bottom Right",culng(2^31*rnd())
draw string img,(8     ,100-16  ), "Bottom Left" ,culng(2^31*rnd())

while inkey()=""
  Mirror(img)       : put (220,140),img,PSET : flip : sleep 100
  Mirror(img,false) : put (220,140),img,PSET : flip : sleep 100
wend
Last edited by D.J.Peters on Jan 09, 2019 5:15, edited 2 times in total.
jdebord
Posts: 525
Joined: May 27, 2005 6:20
Location: Limoges, France
Contact:

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby jdebord » Jan 08, 2019 8:45

Thank you very much ! This is an excellent complement to your FBImage and Multiput libraries.
D.J.Peters
Posts: 7949
Joined: May 28, 2005 3:28

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby D.J.Peters » Jan 08, 2019 8:57

added "test_screen.bas" and "test_image.bas" in second post.

Joshy
Last edited by D.J.Peters on Jan 09, 2019 5:16, edited 1 time in total.
dodicat
Posts: 6163
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby dodicat » Jan 09, 2019 1:56

very neat.
With an image I had to
...
iStart+=1 : iEnd-=1
wend
put(0,0),img,pset '<----------
if img=0 then ScreenUnlock
end sub

to see it on the screen.
(hope that is correct!)
D.J.Peters
Posts: 7949
Joined: May 28, 2005 3:28

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby D.J.Peters » Jan 09, 2019 2:57

@dodicat does your tested image has odd or even numbers as width or height ?

If this are the problem I can fix it easily.

Joshy
dodicat
Posts: 6163
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby dodicat » Jan 09, 2019 3:04

Here is the image I used (with a straightforward mirror function).

Code: Select all

Function reverse(Byref im As Any Ptr,dirn as long=0) As Any Ptr
    #define ppset(_x,_y,colour)    *Cptr(Ulong Ptr,row+ (_y)*pitch+ (_x) Shl 2)  =(colour)
    #define ppoint(_x,_y)          *Cptr(Ulong Ptr,row + (_y)*pitch + (_x) Shl 2)
    Dim As Integer pitch
    Dim As Any Ptr row
    Dim As Ulong Ptr pixel
    Dim As Integer dx,dy
    Imageinfo im,dx,dy,,pitch,row
    Static As Ulong a(dx-1,dy-1)
    For y As Integer=0 To dy-1
        For x As Integer=0 To dx-1
            a(x,y)=ppoint(x,y)
        Next x
    Next y
    if dirn=0 then 'horizontal
    For y As Integer=0 To dy-1
        For x As Integer=0 To dx-1
            ppset((dx-1)-x,y,a(x,y))
        Next x
    Next y
    else 'vertical
    For y As Integer=0 To dy-1
        For x As Integer=0 To dx-1
            ppset(x,(dy-1)-y,a(x,y))
        Next x
    Next y
    end if
    Return im
End Function

'===================================

Screen 20,32
Dim As Any Ptr im=Imagecreate (1000,750,rgb(200,200,200))
Windowtitle("Press space key to flip the baloons")
'=========draw to image======
For z As Integer=0 To 20
    Line im,(50+40*z,  200+90*Sin(z))-(200,400),Rgb(0,0,0)
    Circle im,(50+40*z,200+90*Sin(z)),20+z,Rgb(z*10,200,255-10*z),,,,f
    Circle im,(50+40*z,200+90*Sin(z)),20+z,Rgb(z*10,0,255-10*z)
Next z
for x as long=0 to 999
    for y as long=400 to 749
        pset im,(x,y),rgb(x,x xor y,y)
    next
    next
Draw String im,(100,100),"HELLO",Rgb(0,0,0)
Line im,(0,0)-(999,749),0,b
'============================
Color ,Rgb(100,100,255)
dim as double t1,t2
dim as long k=1
Do
    k=-k
    Screenlock
    Cls
   
    t1=timer
    Put(10,10),reverse(im,1+k),pset
    t2=timer
   
    draw string (30,30),"Flipping time  " &(t2-t1),0
    Screenunlock
    Sleep
    Sleep 1,1
Loop Until Inkey=Chr(27)
Sleep
 
D.J.Peters
Posts: 7949
Joined: May 28, 2005 3:28

Re: Mirror an Image or the Screen horizontal or vertical only with GET and PUT.

Postby D.J.Peters » Jan 09, 2019 4:44

@dodicat your loops needs for horizontal or vertical the same time and that behavior is normal while you move in a loop the same number of pixels
get and put is horizontal match faster

i get here:
0.023 your pixel by pixel horizontal vertical
0.023 get put vertical
0.004 get put horizontal

I removed stuff from "mirror.bi" use the latest include file from first post !

Joshy

Code: Select all

#include "mirror.bi"
Screen 20,32
Dim As Any Ptr im=Imagecreate (1000,750,rgb(200,200,200))
Windowtitle("Press space key to flip the baloons")
'=========draw to image======
For z As Integer=0 To 20
    Line im,(50+40*z,  200+90*Sin(z))-(200,400),Rgb(0,0,0)
    Circle im,(50+40*z,200+90*Sin(z)),20+z,Rgb(z*10,200,255-10*z),,,,f
    Circle im,(50+40*z,200+90*Sin(z)),20+z,Rgb(z*10,0,255-10*z)
Next z
for x as long=0 to 999
    for y as long=400 to 749
        pset im,(x,y),rgb(x,x xor y,y)
    next
    next
Draw String im,(100,100),"HELLO",Rgb(0,0,0)
Line im,(0,0)-(999,749),0,b
'============================
Color ,Rgb(100,100,255)
dim as double t1,t2
dim as long k=1
Do
    k=-k
    windowtitle "k: " & k
    Screenlock
    Cls
   
    t1=timer
    mirror(im,1+k)
    Put(10,10),im,PSET
    'Put(10,10),reverse(im,1+k),pset
    t2=timer
   
    draw string (30,30),"Flipping time  " &(t2-t1),0
    Screenunlock
    Sleep
    Sleep 1,1
Loop Until Inkey=Chr(27)

Return to “Tips and Tricks”

Who is online

Users browsing this forum: No registered users and 1 guest