MultiPut V2.0 :-)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

Re: MultiPut V2.0 :-)

Post by leopardpm »

for the rotation, will you use the full 0 to 360 degrees, or just steps like 0,45,90,135,180,225,etc....?
leopardpm
Posts: 1795
Joined: Feb 28, 2009 20:58

Re: MultiPut V2.0 :-)

Post by leopardpm »

bcohio2001 wrote:Trying to just save memory. ... I have a MINUMUM of 53 images, 52 'cards' and at least one 'back'. Maybe the two Jokers.
About the only thing that I could think of at the moment would be create another temp image, Put the 'ShowThis' in it using the PReset.
Then use Multiput to rotate and put it on screen.
that ain't alot of memory usage at all.. I would say to definitely do it with a second ShowThis...

Code: Select all

'Rot value (Rotate) not used at the moment
Sub Card.DrawImg(ByVal XLoc As Integer, ByVal YLoc As Integer, GetCard As Integer, Selected As Integer, Rot As Single=0)
	Dim As Any Ptr ShowThis(1)
	ShowThis(0)  = 0
	'
	Select Case GetCard
		Case -1
			ShowThis(0) = Backs(CurBackGr)
		Case 0 To 51
			ShowThis(0) = Deck52(GetCard)
		Case 52
			If Jokers Then ShowThis(0) = JokerBlack
		Case 53
			If Jokers Then ShowThis(0) = JokerRed
		Case Else
			'54+
			'special image
			'As Integer Special
			'As Any Ptr SpecialRC(Any)
			If Special > GetCard - 54 Then ShowThis(0) = SpecialRC(GetCard - 54)
	End Select
	'If Rot > 0 Then
	'	'insert rotation code or call a sub/function
	'EndIf
	......put ShowThis(0) into ShowThis(1) using PRESET here
	if ShowThis(0) then MultiPut ,xloc,yloc,ShowThis(Selected),1,1,rotation,transparent
End Sub
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: MultiPut V2.0 :-)

Post by bcohio2001 »

Is there a way via the parameters sent to change the point of rotation?
As I see it, it is like putting a "pin" in the center of a picture and to be able to spin it.
I would like the "pin" to be somewhere else, for my use, in the upper left corner.
Muttonhead
Posts: 139
Joined: May 28, 2009 20:07

Re: MultiPut V2.0 :-)

Post by Muttonhead »

@bcohio2001:
I have always tried to discover the secret of Multiput, there I have never succeeded ... :(
So the following snippet is more a homage to dj... great work!
but it contains exactly the feature you are looking for:
https://www.freebasic-portal.de/porticu ... -1827.html

Mutton
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: MultiPut V2.0 :-)

Post by D.J.Peters »

I open only the the door for you
but you must self going thru it :-)

Joshy
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: MultiPut V2.0 :-)

Post by Dr_D »

Here is a tip... translate, rotate, translate back. :)
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: MultiPut V2.0 :-)

Post by bcohio2001 »

@Mutton
Thanks.
And FYI received error:
RotPut.bas(14) error 14: Expected identifier, found 'Image' in 'dim as Image ptr Src_Header,Dest_Header 'Zeiger um an die Daten im ImageHeader zu kommen'
Assuming that you included 'fbgfx.bi' somewhere else in a larger project.
Will just use ImageInfo in my copy.

*Edit*
I guess I ASSuMEd wrong, notice the emphasis on 'me'.
Is not in 'fbgfx.bi'!
Much more to it than just getting ImageInfo and like you is beyond me.
Last edited by bcohio2001 on May 26, 2016 17:17, edited 1 time in total.
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: MultiPut V2.0 :-)

Post by Dr_D »

Alas, Rotozoom has the capability as well, but it has fallen by the wayside. :p
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: MultiPut V2.0 :-)

Post by bcohio2001 »

@D.J. Peters

Please specify in either the code or in the first post text that rotating an image with an odd width or height can result in loss of an edge of the image.
All your tests are with images with even dimensions.
angros47
Posts: 2323
Joined: Jun 21, 2005 19:04

Re: MultiPut V2.0 :-)

Post by angros47 »

Personally I think MultiPut should be added to the GFX library. Along with some collision detection routine, perhaps, too
wio
Posts: 17
Joined: Feb 05, 2021 4:58

Re: MultiPut V2.0 :-)

Post by wio »

Hi all, old coder, new user here.

I am trying to use MultiPut V2 and am having slightly more success with it than with the first few iterations. It looks like a great tool but I still can't seem to get it to work properly.

When I display my 8x8 sprite on screen using multiput, if the rotation is 0 or 90 degrees the sprite is stretched, if it is at 270 degrees it is moved over to the right by 1 pixel (seemingly), at 180 degrees it looks fine (but upside down though obvs). Should it still work? I am on the latest version of FB, Win10 64bit.

Is there a version of FB that is ideal for using MultiPut and if so will it run in the 64bit version of that release? I have tried a few versions of FB along with most of the iterations of MultiPut that I came across. I could never get MultiPut to even show anything until I found V2, the version with the yellow smiley didn't work and also the version with the white square grid. Nothing would happen.

Thanks in advance for any help.

EDIT: I just tested it by scaling it up to 2 instead of 1. It now shows better but there is a line of pixels missing from the bottom of the sprite at 0 degrees, at 90 it seems stretched or there is an extra row of pixels added at the top and one missing at the bottom again. At 180 and 270 degrees everything looks perfect.

This is my code...

Code: Select all

' FB 1.07.3 Win64
#include "multiput.bi"

screen 18,32
Dim spr_pedehead As Any Ptr  = ImageCreate(8,8)
bload"img\pedehead1.bmp",spr_pedehead

Do       

    MultiPut ,100,100,spr_pedehead,1,1,0,1
    put (120,120),spr_pedehead,trans
    screensync

Loop Until inkey <>""

ImageDestroy spr_pedehead
The second 'put' is there just to draw the sprite as it is meant to look, for comparison

Result of code (cropped) image link https://ibb.co/tpHMdQj
Actual sprite bmp that I am using https://ibb.co/tDY03yX

This is the version of multiput.bi that I am using...

Code: Select all

#ifndef __MULTIPUT_BI__
#define __MULTIPUT_BI__

' Multiput by D.J.Peters (Joshy)
' MultiPut [destination],[xmidpos],[ymidpos], source,[xScale],[yScale],[Trans]

type FP16 ' fixed point 16:16
  union
  type
    as ushort l
    as  short h
  end type
  as integer v
  end union
end type

#define _ADD_ 0 ' increment a value
#define _CMP_ 1 ' compare values
#define _SET_ 2 ' set a value

#define _XScreen_  0
#define _YScreen_  1
#define _UTexture_ 2
#define _VTexture_ 3

#define _LeftIndex_    0
#define _RightIndex_   1

#define _CurrentIndex_ 0
#define _NextIndex_    1

#define _EdgeXStart_ 0
#define _EdgeUStart_ 1
#define _EdgeVStart_ 2
#define _EdgeXStep_  3
#define _EdgeUStep_  4
#define _EdgeVStep_  5

'#define UseRad 'if not then Rotate are in degrees

Sub MultiPut(Byval pTarget As Any Ptr= 0, _
             Byval xMidPos As Integer= 0, _
             Byval yMidPos As Integer= 0, _
             Byval pSource As Any Ptr   , _
             Byval xScale  As Single = 1, _
             Byval yScale  As Single = 1, _
             Byval Rotate  As Single = 0, _
             Byval Transparent As boolean = false)
  Dim As Integer SourceWidth=any,SourceHeight=any,SourceBytes=any,SourcePitch=any
  Dim as Integer TargetWidth=any,TargetHeight=any,TargetBytes=any,TargetPitch=any
  Dim As Integer i=any,yStart=any,yEnd=any,xStart=any,xEnd=any
  Dim As Integer CNS(1,1)=any 'Counters
  Dim As Integer ACS(1,2)=any '_ADD_ compare and _SET_
  Dim As Single fPoints(3,3)=any,fEdges(2,6)=any,fLength=any,fUSlope=any,fVSlope=any
  Dim As FP16 U=any,V=any,US=any,VS=any
  Dim As boolean MustRotate = iif(Rotate<>0,true,false)

  If (ScreenPtr()=0) Or (pSource=0) Then Exit Sub

  If xScale < 0.001 Then xScale=0.001
  If yScale < 0.001 Then yScale=0.001
 
  If pTarget=0 Then
    ScreenInfo     _
    TargetWidth  , _
    TargetHeight,, _
    TargetBytes  , _
    TargetPitch
    pTarget=ScreenPtr()
  Else
    ImageInfo     _
    pTarget     , _
    TargetWidth , _
    TargetHeight, _
    TargetBytes , _
    TargetPitch , _
    pTarget
  End If
  If (TargetWidth<4) Or (TargetHeight<4) Then Exit Sub

  ImageInfo     _
  pSource     , _
  SourceWidth , _
  SourceHeight, _
  SourceBytes , _
  SourcePitch , _
  pSource

  Select Case as const TargetBytes
  case 1    ' TargetPitch shr=0 : SourcePitch shr=0
  case 2    : TargetPitch shr=1 : SourcePitch shr=1
  case 4    : TargetPitch shr=2 : SourcePitch shr=2
  case else : exit sub
  end select

  fPoints(0,_XScreen_)=-SourceWidth/2 * xScale
  fPoints(1,_XScreen_)= SourceWidth/2 * xScale
  fPoints(2,_XScreen_)= fPoints(1,_XScreen_)
  fPoints(3,_XScreen_)= fPoints(0,_XScreen_)

  fPoints(0,_YScreen_)=-SourceHeight/2 * yScale
  fPoints(1,_YScreen_)= fPoints(0,_YScreen_)
  fPoints(2,_YScreen_)= SourceHeight/2 * yScale
  fPoints(3,_YScreen_)= fPoints(2,_YScreen_)

  fPoints(0,_UTexture_)=0
  fPoints(1,_UTexture_)= SourceWidth
  fPoints(2,_UTexture_)= fPoints(1,_UTexture_)
  fPoints(3,_UTexture_)=0
 
  fPoints(0,_VTexture_)=0
  fPoints(1,_VTexture_)=0
  fPoints(2,_VTexture_)= SourceHeight
  fPoints(3,_VTexture_)= fPoints(2,_VTexture_)

  If MustRotate=true Then
    #ifndef UseRad
    Rotate*=0.017453292 'deg 2 rad
    #endif
    var co = cos(rotate)
    var si = sin(rotate)
    For i=0 To 3
      var x = fPoints(i,_XScreen_)*co - fPoints(i,_YScreen_)*si
      var y = fPoints(i,_XScreen_)*si + fPoints(i,_YScreen_)*co
      fPoints(i,_XScreen_) = x
      fPoints(i,_YScreen_) = y
    Next
  End If
  yStart=30^2:yEnd=-yStart:xStart=yStart:xEnd=yEnd
 
  ' get min max
  For i=0 To 3
    fPoints(i,_XScreen_)=Int(fPoints(i,_XScreen_)+xMidPos)
    fPoints(i,_YScreen_)=Int(fPoints(i,_YScreen_)+yMidPos)
    If fPoints(i,_YScreen_)<yStart Then yStart=fPoints(i,_YScreen_):CNS(_LeftIndex_,_CurrentIndex_)=i
    If fPoints(i,_YScreen_)>yEnd   Then yEnd  =fPoints(i,_YScreen_)
    If fPoints(i,_XScreen_)<xStart Then xStart=fPoints(i,_XScreen_)
    If fPoints(i,_XScreen_)>xEnd   Then xEnd  =fPoints(i,_XScreen_)
  Next

  If yStart = yEnd        Then Exit Sub
  If xStart = xEnd        Then Exit Sub
  If yEnd   < 0           Then Exit Sub
  If xEnd   < 0           Then Exit Sub
  If yStart>=TargetHeight Then Exit Sub
  If xStart>=TargetWidth  Then Exit Sub
 
 
  ACS(_LeftIndex_ ,_ADD_)=-1:ACS(_LeftIndex_ ,_CMP_)=-1:ACS(_LeftIndex_ ,_SET_)=3
  ACS(_RightIndex_,_ADD_)= 1:ACS(_RightIndex_,_CMP_)= 4:ACS(_RightIndex_,_SET_)=0

  ' share the same highest point
  CNS(_RightIndex_,_CurrentIndex_)=CNS(_LeftIndex_,_CurrentIndex_)
 
  ' loop from Top to Bottom
  While yStart<yEnd
    'Scan Left and Right edges together
    For i=_LeftIndex_ To _RightIndex_
      ' bad to read but fast and short ;-)
      If yStart=fPoints(CNS(i,_CurrentIndex_),_YScreen_) Then
        CNS(i,_NextIndex_)=CNS(i,_CurrentIndex_)+ACS(i,_ADD_)
        If CNS(i,_NextIndex_)=ACS(i,_CMP_) Then CNS(i,_NextIndex_)=ACS(i,_SET_)
        While fPoints(CNS(i,_CurrentIndex_),_YScreen_) = fPoints(CNS(i,_NextIndex_),_YScreen_)
          CNS(i,_CurrentIndex_)=CNS(i,_NextIndex_)
          CNS(i,_NextIndex_   )=CNS(i,_CurrentIndex_)+ACS(i,_ADD_)
          If CNS(i,_NextIndex_)=ACS(i,_CMP_) Then CNS(i,_NextIndex_)=ACS(i,_SET_)
        Wend
        fEdges(i,_EdgeXStart_) = fPoints(CNS(i,_CurrentIndex_),_XScreen_)
        fEdges(i,_EdgeUStart_) = fPoints(CNS(i,_CurrentIndex_),_UTexture_)
        fEdges(i,_EdgeVStart_) = fPoints(CNS(i,_CurrentIndex_),_VTexture_)
        fLength  = fPoints(CNS(i,_NextIndex_),_YScreen_) - fPoints(CNS(i,_CurrentIndex_),_YScreen_)
        If fLength <> 0.0 Then
          fLength=1/fLength
          fEdges(i,_EdgeXStep_) = fPoints(CNS(i,_NextIndex_),_XScreen_ )-fEdges(i,_EdgeXStart_):fEdges(i,_EdgeXStep_)*=fLength
          fEdges(i,_EdgeUStep_) = fPoints(CNS(i,_NextIndex_),_UTexture_)-fEdges(i,_EdgeUStart_):fEdges(i,_EdgeUStep_)*=fLength
          fEdges(i,_EdgeVStep_) = fPoints(CNS(i,_NextIndex_),_VTexture_)-fEdges(i,_EdgeVStart_):fEdges(i,_EdgeVStep_)*=fLength
        End If
        CNS(i,_CurrentIndex_)=CNS(i,_NextIndex_)
      End If
    Next

    If (yStart<0)                                                   Then Goto NextScanLine
    xStart=fEdges(_LeftIndex_ ,_EdgeXStart_):If xStart>=TargetWidth Then Goto NextScanLine
    xEnd  =fEdges(_RightIndex_,_EdgeXStart_):If xEnd  < 0           Then Goto NextScanLine
    If (xStart=xEnd)                                                Then Goto NextScanLine
    if xEnd  <xStart                                                Then goto NextScanLine

    fLength=1/(xEnd-xStart)
    fUSlope=fEdges(_RightIndex_,_EdgeUStart_)-fEdges(_LeftIndex_,_EdgeUStart_):fUSlope*=fLength
    fVSlope=fEdges(_RightIndex_,_EdgeVStart_)-fEdges(_LeftIndex_,_EdgeVStart_):fVSlope*=fLength
    If xStart<0 Then
      fLength=-xStart
      U.v=(fEdges(_LeftIndex_,_EdgeUStart_)+fUSlope*fLength)*&HFFFF
      V.v=(fEdges(_LeftIndex_,_EdgeVStart_)+fVSlope*fLength)*&HFFFF
      xStart = 0
    Else
      U.v=fEdges(_LeftIndex_,_EdgeUStart_)*&HFFFF
      V.v=fEdges(_LeftIndex_,_EdgeVStart_)*&HFFFF
    End If
    If u.v<0 Then u.v=0
    If v.v<0 Then v.v=0
    US.v=fUSlope*&HFFFF
    VS.v=fVSlope*&HFFFF

    If xEnd>=TargetWidth Then xEnd=TargetWidth-1

    Select Case as const TargetBytes
    Case 1
      var s=cptr(ubyte ptr,pSource)
      var t=cptr(ubyte ptr,pTarget)+yStart*TargetPitch+xStart
      var e=t+(xEnd-xStart)
      If Transparent=false Then
        While t<e
          *t=*(s+V.h*SourcePitch+U.h)
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      Else
        While t<e
          dim as ubyte c=*(s+V.h*SourcePitch+U.h)
          If c Then *t=c
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      End If
    Case 2
      var s=cptr(ushort ptr,pSource)
      var t=cptr(ushort ptr,pTarget)+yStart*TargetPitch+xStart
      var e=t+(xEnd-xStart)
      If Transparent=false Then
        While t<e
          *t=*(s+V.h*SourcePitch+U.h)
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      Else
        While t<e
          dim as ushort c=*(s+V.h*SourcePitch+U.h)
          If c<>&HF81F Then *t=c
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      End If
    Case 4
      var s=cptr(ulong ptr,pSource)
      var t=cptr(ulong ptr,pTarget)+yStart*TargetPitch+xStart
      var e=t+(xEnd-xStart)
      If Transparent=false Then
        While t<e
          *t=*(s+V.h*SourcePitch+U.h)
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      Else
        While t<e
          dim as ulong c=*(s+V.h*SourcePitch+U.h)
          If c<>&HFFFF00FF Then *t=c
          V.v+=VS.v : U.v+=US.v : t+=1
        Wend
      End If
    End Select

  NextScanLine:
    yStart+=1 : If yStart=TargetHeight Then exit while
    fEdges(_LeftIndex_ ,_EdgeXStart_)+=fEdges(_LeftIndex_ ,_EdgeXStep_)
    fEdges(_LeftIndex_ ,_EdgeUStart_)+=fEdges(_LeftIndex_ ,_EdgeUStep_)
    fEdges(_LeftIndex_ ,_EdgeVStart_)+=fEdges(_LeftIndex_ ,_EdgeVStep_)
    fEdges(_RightIndex_,_EdgeXStart_)+=fEdges(_RightIndex_,_EdgeXStep_)
    fEdges(_RightIndex_,_EdgeUStart_)+=fEdges(_RightIndex_,_EdgeUStep_)
    fEdges(_RightIndex_,_EdgeVStart_)+=fEdges(_RightIndex_,_EdgeVStep_)
  Wend
End Sub
#endif ' __MULTIPUT_BI__
Dan.
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: MultiPut V2.0 :-)

Post by Dr_D »

wio wrote:Hi all, old coder, new user here.

I am trying to use MultiPut V2 and am having slightly more success with it than with the first few iterations. It looks like a great tool but I still can't seem to get it to work properly.

When I display my 8x8 sprite on screen using multiput, if the rotation is 0 or 90 degrees the sprite is stretched, if it is at 270 degrees it is moved over to the right by 1 pixel (seemingly), at 180 degrees it looks fine (but upside down though obvs). Should it still work? I am on the latest version of FB, Win10 64bit.

Is there a version of FB that is ideal for using MultiPut and if so will it run in the 64bit version of that release? I have tried a few versions of FB along with most of the iterations of MultiPut that I came across. I could never get MultiPut to even show anything until I found V2, the version with the yellow smiley didn't work and also the version with the white square grid. Nothing would happen.

Thanks in advance for any help.

EDIT: I just tested it by scaling it up to 2 instead of 1. It now shows better but there is a line of pixels missing from the bottom of the sprite at 0 degrees, at 90 it seems stretched or there is an extra row of pixels added at the top and one missing at the bottom again. At 180 and 270 degrees everything looks perfect.

Dan.
Hi, Dan. Welcome! Maybe this is what's wrong?
bcohio2001 wrote:@D.J. Peters

Please specify in either the code or in the first post text that rotating an image with an odd width or height can result in loss of an edge of the image.
All your tests are with images with even dimensions.
wio
Posts: 17
Joined: Feb 05, 2021 4:58

Re: MultiPut V2.0 :-)

Post by wio »

Hi, thanks for the reply :)

I am not sure what you mean by this "Please specify in either the code or in the first post text that rotating an image with an odd width or height can result in loss of an edge of the image. All your tests are with images with even dimensions."

My image has an even amount of pixels, it is 8x8. Also, I don't have to change the rotation for it to 'fail', it does it at 0 rotation / 0 degrees.
sero
Posts: 59
Joined: Mar 06, 2018 13:26
Location: USA

Re: MultiPut V2.0 :-)

Post by sero »

Here is a 2x zoomed in screenshot of my experience of what is happening with this multiput using an 8x8 sprite. The titles 32bit and 64bit refers to how the code was compiled.

* original image removed because host is stupid *

Code: Select all

#include "multiput.bi"

screen 18,32
Dim spr_pedehead As Any Ptr  = ImageCreate(8,8)

line spr_pedehead, (0,0)-(7,7), rgb(255,0,255),b
line spr_pedehead, (1,1)-(6,6), rgb(127,127,127),bf
line spr_pedehead, (1,0)-(6,0), rgb(255,0,0)
line spr_pedehead, (7,1)-(7,6), rgb(0,255,0)
line spr_pedehead, (1,7)-(6,7), rgb(31,31,255)
line spr_pedehead, (0,1)-(0,6), rgb(255,63,127)

'bload"test.bmp",spr_pedehead

dim as long rotate = 0
dim as long yoffset = 102

Do       
 
  screenlock()
    draw string(120,yoffset - 16),"no trans"
    draw string(120,yoffset),"original"
    put (120,yoffset+18),spr_pedehead,pset
   
    line(230,yoffset+8)-(250,yoffset+28),rgb(0,0,0),bf
    draw string(240,yoffset),"rotating"
    MultiPut ,243,yoffset+21,spr_pedehead,1,1,rotate,0
   
    draw string(360,yoffset),"90 multiput"
    MultiPut ,364,yoffset+22,spr_pedehead,1,1,90,0
    draw string(360,yoffset+40),"180 multiput"
    MultiPut ,364,yoffset+62,spr_pedehead,1,1,180,0
    draw string(360,yoffset+80),"270 multiput"
    MultiPut ,364,yoffset+102,spr_pedehead,1,1,270,0
   
    yoffset += 160
    draw string(120,yoffset - 16),"using trans"
    draw string(120,yoffset),"original"
    put (120,yoffset+18),spr_pedehead,trans
   
    line(230,yoffset+8)-(250,yoffset+28),rgb(0,0,0),bf
    draw string(240,yoffset),"rotating"
    MultiPut ,243,yoffset+21,spr_pedehead,1,1,rotate,1
   
    draw string(360,yoffset),"90 multiput"
    MultiPut ,364,yoffset+22,spr_pedehead,1,1,90,1
    draw string(360,yoffset+40),"180 multiput"
    MultiPut ,364,yoffset+62,spr_pedehead,1,1,180,1
    draw string(360,yoffset+80),"270 multiput"
    MultiPut ,364,yoffset+102,spr_pedehead,1,1,270,1
    yoffset -= 160
  screenunlock()
 
  rotate += 3
  if rotate > 360 then rotate -= 360
  sleep 1
Loop Until inkey <>""

ImageDestroy spr_pedehead
Last edited by sero on Feb 12, 2021 3:12, edited 1 time in total.
Dr_D
Posts: 2451
Joined: May 27, 2005 4:59
Contact:

Re: MultiPut V2.0 :-)

Post by Dr_D »

A long time ago, I made a rotozoomer, but the link in the original post is dead. I'm working on putting a new archive up for it. If you're interested, I'll post the link when I'm done.
Post Reply