Code archives/Graphics/Texture Popper

This code has been declared by its author to be Public Domain code.

Download source code

Texture Popper by Shagwana2005
This tool lets users define a quad on there own image, then lets the user export the contence to a .bmp image.

Its usefull for making quick and dirty textures!.

Controls..

LMB = drag points
RMB = drag screen
;
;  Program : Texture popper
;
;  Author : Stephen Greener (aka Shagwana)
;           www.sublimegames.com
;
;  Short description :
;
;  Load in a source image
;  Set the 4 points to the area you wish to grab
;  Save the region from the menu
;  Select the size of the area you wish to export
;  Computer will now convert the contence of the region into a nice rectange of your chossing (bmp)
;___________________________________________________________________________________________________________________________________

Const DEBUG_BUILD=False 

Const TESTFILENAME$=""

Const START_WINDOW_WIDTH=700
Const START_WINDOW_HEIGHT=400

Const START_ROI_INSTEP = 3

Const GRAB_SNAP = 250

;__/ Varibles \_____________________________________________________________________________________________________________________

;Data

Global pSourceImage=0
Global iViewXPos=0,iViewYPos=0
Global QuitProgram=False

;What the user is doing
Global bEditing=False         ;User is doing something at the moment?
Global bDraggingScreen=False  ;User is either dragging the screen or dragging a point  
Global iPointEdit=0

Global iSaveWidth=512
Global iSaveHeight=512

Global iMouseXStart=0
Global iMouseYStart=0


;Gadgets
Global pMainWindow=0
Global pMainWindowMenu=0
Global pPanelView=0
Global pMainViewCanvas=0
Global pHorzSlider=0
Global pVertSlider=0
Global pDisplayTimer=0

Global pFileMenu=0



;Vertex on image
Global bVertexValid[4]
Global iVertexXPos[4]
Global iVertexYPos[4]

For n=0 To 3
  bVertexValid[n]=False   ;Clear all the verts
  Next





;__/ Functions \____________________________________________________________________________________________________________________

Function SetupProgram()  ;Setup the gadgets and other gui objects

  ;Setup the main window
  pMainWindow=CreateWindow("Texture popper",(GraphicsWidth()-START_WINDOW_WIDTH)/2,(GraphicsHeight()-START_WINDOW_HEIGHT)/3,START_WINDOW_WIDTH,START_WINDOW_HEIGHT,0,%101111)   ;Main window
  SetMinWindowSize pMainWindow,200,200
  pMainWindowMenu=WindowMenu(pMainWindow)

  pPanelView=CreatePanel(2,2,GadgetWidth(pMainWindow)-30,GadgetHeight(pMainWindow)-88,pMainWindow)
  SetGadgetLayout pPanelView,1,1,1,1

  pMainViewCanvas=CreateCanvas(0,0,GraphicsWidth(),GraphicsHeight(),pPanelView,0)
  SetGadgetLayout pMainViewCanvas,1,0,1,0    ;Clamp the canvas to the top left corner

  pHorzSlider=CreateSlider(0,GadgetHeight(pMainWindow)-84,START_WINDOW_WIDTH-18,18,pMainWindow,1)
  SetGadgetLayout pHorzSlider,1,1,0,1
  pVertSlider=CreateSlider(GadgetWidth(pMainWindow)-26,0,18,START_WINDOW_HEIGHT-18,pMainWindow,0)
  SetGadgetLayout pVertSlider,0,1,1,1

  pDisplayTimer=CreateTimer(10)

  ;Menu...
  pFileMenu=CreateMenu("File",0,pMainWindowMenu)
  CreateMenu "Load Image",1,pFileMenu
  CreateMenu "",2,pFileMenu
  CreateMenu "Save Region",3,pFileMenu

  UpdateWindowMenu pMainWindow

  End Function 

Function InitSourceImage()    ;Load in a source image

  pSourceImage=CreateImage(800,600)   ;Blank usless image!
  SetStatusText(pMainWindow,"www.sublimegames.com")
  iViewXPos=0
  iViewYPos=0

  ;Make the ROI fit inside the image
  iVertexXPos[0]=(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[0]=(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[1]=ImageWidth(pSourceImage)-(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[1]=(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[2]=ImageWidth(pSourceImage)-(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[2]=ImageHeight(pSourceImage)-(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[3]=(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[3]=ImageHeight(pSourceImage)-(ImageHeight(pSourceImage)/START_ROI_INSTEP)

  DrawDisplay()
  End Function 

Function LoadSourceImage(Filename$)    ;Load in a source image
  If pSourceImage<>0
    FreeImage pSourceImage
    EndIf

  pSourceImage=LoadImage(Filename$)
  SetStatusText(pMainWindow,"Loaded source image : "+Filename$)
  iViewXPos=0
  iViewYPos=0

  ;Make the ROI fit inside the image
  iVertexXPos[0]=(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[0]=(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[1]=ImageWidth(pSourceImage)-(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[1]=(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[2]=ImageWidth(pSourceImage)-(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[2]=ImageHeight(pSourceImage)-(ImageHeight(pSourceImage)/START_ROI_INSTEP)
  iVertexXPos[3]=(ImageWidth(pSourceImage)/START_ROI_INSTEP)
  iVertexYPos[3]=ImageHeight(pSourceImage)-(ImageHeight(pSourceImage)/START_ROI_INSTEP)

  DrawDisplay()
  End Function 

Function DrawDisplay()                 ;update the display where needed
 SetBuffer CanvasBuffer(pMainViewCanvas)

 If pSourceImage<>0


    If GadgetWidth(pPanelView)>ImageWidth(pSourceImage) Then iViewXPos=0
    If GadgetHeight(pPanelView)>ImageHeight(pSourceImage) Then iViewYPos=0


   ;Ensure the view is valid  
    If 0-iViewXPos>0
      iViewXPos=0    ;Should never happen!
      Else
      If (iViewXPos+GadgetWidth(pPanelView))>ImageWidth(pSourceImage)
        iViewXPos=ImageWidth(pSourceImage)-GadgetWidth(pPanelView)
        EndIf
      EndIf

    If 0-iViewYPos>0
      iViewYPos=0    ;Should never happen!
      Else
      If (iViewYPos+GadgetHeight(pPanelView))>ImageHeight(pSourceImage)
        iViewYPos=ImageHeight(pSourceImage)-GadgetHeight(pPanelView)
        EndIf
      EndIf

    ;Redraw the screen
    ClsColor 0,100,0
    Cls
    DrawBlock pSourceImage,0-iViewXPos,0-iViewYPos

    ;Update the slider bars (just in case of window resize)
    SetSliderRange pHorzSlider,GadgetWidth(pPanelView),ImageWidth(pSourceImage)
    SetSliderValue pHorzSlider,iViewXPos
    SetSliderRange pVertSlider,GadgetHeight(pPanelView),ImageHeight(pSourceImage)
    SetSliderValue pVertSlider,iViewYPos

    OverLayArea()

    EndIf

 FlipCanvas pMainViewCanvas 
 End Function

Function OverLayArea()                 ;Draw the ROI (region of intrest)

  ;Check to see if all 4 verts are on screen, before drawing
  For N=0 To 3
    If iVertexXPos[N]<0 Then iVertexXPos[N]=0
    If iVertexYPos[N]<0 Then iVertexYPos[N]=0
    If iVertexXPos[N]>ImageWidth(pSourceImage) Then iVertexXPos[N]=ImageWidth(pSourceImage)
    If iVertexYPos[N]>ImageHeight(pSourceImage) Then iVertexYPos[N]=ImageHeight(pSourceImage)
    Next


  b=False
  If ((MilliSecs()/140) Mod 4)>2 Then b=True


  ;Draw the lines inbetween
  If b=True
    Color 255,0,255
    Else
    Color 0,255,0
    EndIf
  Line iVertexXPos[0]-iViewXPos,iVertexYPos[0]-iViewYPos,iVertexXPos[1]-iViewXPos,iVertexYPos[1]-iViewYPos
  Line iVertexXPos[1]-iViewXPos,iVertexYPos[1]-iViewYPos,iVertexXPos[2]-iViewXPos,iVertexYPos[2]-iViewYPos
  Line iVertexXPos[2]-iViewXPos,iVertexYPos[2]-iViewYPos,iVertexXPos[3]-iViewXPos,iVertexYPos[3]-iViewYPos
  Line iVertexXPos[3]-iViewXPos,iVertexYPos[3]-iViewYPos,iVertexXPos[0]-iViewXPos,iVertexYPos[0]-iViewYPos


  For N=0 To 3
    iX=iVertexXPos[N]-iViewXPos
    iY=iVertexYPos[N]-iViewYPos

    ;Draw the Point
    If b=True
      Color 255,255,255
      Rect iX-1,iY-1,3,3,False
      Color 0,0,0
      Rect iX-3,iY-3,7,7,False
      Else
      Color 0,0,0
      Rect iX-1,iY-1,3,3,False
      Color 255,255,255
      Rect iX-3,iY-3,7,7,False
      EndIf

    Next

  

  End Function

;__/ Main program \_________________________________________________________________________________________________________________
.MainProgram:


  iSaveWidth=512
  iSaveHeight=512

  SetupProgram()
  If DEBUG_BUILD=True
    LoadSourceImage(TESTFILENAME$)
    Else
    InitSourceImage()
    EndIf

  Repeat

    DrawDisplay()

    Ev=WaitEvent()
    Es=EventSource()

    Select Es

      Case pHorzSlider
      Select Ev
        Case $401
        iViewXPos=SliderValue(pHorzSlider)
        End Select

      Case pVertSlider
      Select Ev
        Case $401
        iViewYPos=SliderValue(pVertSlider)
        End Select


      Case pMainViewCanvas
      DoCanvas(Ev)

      Case pMainWindow
      Select Ev
        Case $803
        ;Window close
        QuitProgram=True
        End Select

      Default
      Select Ev
        Case $1001

        Select EventData()
          Case 1
          ;Load
          fn$=RequestFile$("Load source image")
          If fn$<>""
            LoadSourceImage(fn$)
            EndIf
          Case 3
          ;Save

          ;If sfn$<>""
          SaveRegion()
          ;  EndIf

          End Select


        End Select
      End Select


    Until QuitProgram=True

   End

;Calc distance of a line
Function Calc_Distance(XD%,YD%)
  XDelta%=Abs(XD%)
  YDelta%=Abs(YD%)
  Return Sqr((XDelta*XDelta)+(YDelta*YDelta))
  End Function

;Do the magical work on the canvas here
Function DoCanvas(Ev)


  If bEditing=False
    ;Not doing anything at the moment, free to do something...
    
    Select Ev

      Case $201     ;Mouse down in the canvas
      Select EventData()
        Case 1 ;LMB (drag point)
        ;If over point, drag it

        iCloses=(GRAB_SNAP+1)
        bFound=False

        For N=0 To 3
          dist=Calc_Distance(iVertexXPos[N]-(MouseX(pMainViewCanvas)+iViewXPos),iVertexYPos[N]-(MouseY(pMainViewCanvas)+iViewYPos))
          If dist<iCloses
            iCloses=dist
            bFound=True
            iPointEdit=N
            EndIf
          Next


        If bFound=True
          bEditing=True
          bDraggingScreen=False
          n=MouseXSpeed(pMainViewCanvas)  ;First one contains rubbish!
          n=MouseYSpeed(pMainViewCanvas)
          EndIf

        Case 2 ;RMB (move view)
        ;Move screen!
        bEditing=True
        bDraggingScreen=True

        n=MouseXSpeed(pMainViewCanvas)  ;First one contains rubbish!
        n=MouseYSpeed(pMainViewCanvas)

        End Select
      End Select     


    Else
    ;Working on something at the moment
    If bDraggingScreen=False
      ;Moving the screen

      Select Ev

        Case $203

        Select iPointEdit
          Case 0
          SetStatusText(pMainWindow,"Moving top-left point")
          Case 1
          SetStatusText(pMainWindow,"Moving top-right point")
          Case 2
          SetStatusText(pMainWindow,"Moving bottom-right point")
          Case 3
          SetStatusText(pMainWindow,"Moving bottom-left point")
          End Select

        iVertexXPos[iPointEdit]=iVertexXPos[iPointEdit]+MouseXSpeed(pMainViewCanvas)
        iVertexYPos[iPointEdit]=iVertexYPos[iPointEdit]+MouseYSpeed(pMainViewCanvas)

        Case $202
        Select EventData()
          Case 1 ;RMB (move view)
          ;Move screen!
          bEditing=False
            
          End Select

        End Select

      Else
      ;Moving a point


      Select Ev

        Case $203
        iViewXPos=iViewXPos-MouseXSpeed(pMainViewCanvas)
        iViewYPos=iViewYPos-MouseYSpeed(pMainViewCanvas)

        Case $202
        Select EventData()
          Case 2 ;RMB (move view)
          ;Move screen!
          bEditing=False
            
          End Select

        End Select


      EndIf

    EndIf


  End Function

;Pop up window asking for the size of the region to export to, with proceed button
Function SaveRegion()


  ;Get size of the image to save from the user by putting up a new window
  pToolWin=CreateWindow("Save region",GadgetX(pMainWindow)+40,GadgetY(pMainWindow)+40,300,50,pMainWindow,%010001)

  p1=CreateLabel("Width ",10,7,40,20,pToolWin)
  p2=CreateLabel("Height ",120,7,40,20,pToolWin)

  pWGad=CreateTextField(50,4,60,20,pToolWin)
  pHGad=CreateTextField(160,4,60,20,pToolWin)

  pProceed=CreateButton("Save",228,4,60,20,pToolWin)


  SetGadgetText(pWGad,iSaveWidth)
  SetGadgetText(pHGad,iSaveHeight)

  bDone=False
  bDoSave=False
  Repeat
    Ev=WaitEvent()
    Es=EventSource()

    Select Es
   
      Case pProceed

      ;Ensure numbers are valid
      FlushEvents()

      num=TextFieldText(pWGad)

      If num<10 Then num=10
      iSaveWidth=num
      SetGadgetText(pWGad,iSaveWidth)

      ;Ensure numbers are valid
      num=TextFieldText(pHGad)
      If num<10 Then num=10
      iSaveHeight=num
      SetGadgetText(pHGad,iSaveHeight)





      bDoSave=True
      bDone=True
 
      Case pToolWin
      Select Ev
        Case $803    ;Exit save thing
        bDone=True
        End Select


      Case pMainWindow
      ;Quit on the main window!
      Select Ev
        Case $803
        QuitProgram=True
        bDone=True
        End Select
      End Select



    Until bDone=True

  FreeGadget pProceed
  FreeGadget p1
  FreeGadget p2
  FreeGadget pWGad
  FreeGadget pHGad

  FreeGadget pToolWin

  If bDoSave=True

    If DEBUG_BUILD=True
      sfn$=Int(MilliSecs())+".bmp"
      Else
      sfn$=RequestFile$("Save region to","",True)
      EndIf

    SaveRegionAsBMP(sfn$,iSaveWidth,iSaveHeight)   ;Do the needed magic
    EndIf

  End Function

;Convert the area of intrest into another bitmap and save
Function SaveRegionAsBMP(filename$,iSaveWidth,iSaveHeight)

  pSaveImage=CreateImage(iSaveWidth,iSaveHeight,1,2)
  SetBuffer ImageBuffer(pSaveImage)

  ;Do the funcky magic - wip


  ;Top lines maths (top left to top right)
  fstart_xstep#=Float(iVertexXPos[1]-iVertexXPos[0])/Float(iSaveWidth)   ;How much to step every x
  fstart_ystep#=Float(iVertexYPos[1]-iVertexYPos[0])/Float(iSaveWidth)  ;How much to step every y 

  ;Bottom lines maths (bottom left to bottom right)
  fend_xstep#=Float(iVertexXPos[2]-iVertexXPos[3])/Float(iSaveWidth)   ;How much to step every x
  fend_ystep#=Float(iVertexYPos[2]-iVertexYPos[3])/Float(iSaveWidth)  ;How much to step every y 

  
  top_xcoord#=iVertexXPos[0]
  top_ycoord#=iVertexYPos[0]
  bottom_xcoord#=iVertexXPos[3]
  bottom_ycoord#=iVertexYPos[3]


  For xstep=0 To iSaveWidth-1
    ;Step through each pixel that needs saving in the x

    fdown_xstep#=Float(bottom_xcoord#-top_xcoord#)/Float(iSaveHeight)
    fdown_ystep#=Float(bottom_ycoord#-top_ycoord#)/Float(iSaveHeight)

    fdown_xcoord#=top_xcoord#
    fdown_ycoord#=top_ycoord#

    For ystep=0 To iSaveHeight-1

      ;Pull the pixel we want
      SetBuffer ImageBuffer(pSourceImage)
      GetColor(Int(fdown_xcoord),Int(fdown_ycoord))

      ;Set color works per buffer. not global
      r=ColorRed()
      g=ColorGreen()
      b=ColorBlue()

      SetBuffer ImageBuffer(pSaveImage)

      Color r,g,b
      Plot(xstep,ystep)

      fdown_xcoord#=fdown_xcoord#+fdown_xstep#
      fdown_ycoord#=fdown_ycoord#+fdown_ystep#

      Next

    ;Step to the next point of intrest
    top_xcoord#=top_xcoord#+fstart_xstep#
    top_ycoord#=top_ycoord#+fstart_ystep#
    bottom_xcoord#=bottom_xcoord#+fend_xstep#
    bottom_ycoord#=bottom_ycoord#+fend_ystep#

    Next

  FlushEvents()

  ;Working 
  SetStatusText(pMainWindow,"Save region :"+filename$)
  SaveImage(pSaveImage,filename$)
  FreeImage pSaveImage

  End Function

Comments

Beaker2005
Very nice basis for a full on texture tool.

You can also do this with the Crop tool in Photoshop 6(?) or above.


Tom2005
Very cool! :)


Rob Farley2005
Looks cool, also looks blitz+ so that's no good for me... Just as an exercise I might have a go at doing this in b3d looks like a good mind tester!


erbbysam2005
anybody fell like compling this to give us less B+ fortounte a test?


Shagwana2005
You can find a compiled version *file no longer available*.

LMB = adjust points
RMB = drags screen around

It saves as a .bmp file (and you will need to add the ".bmp" part yourself)

I dont know what happens when you mix up the points order, its not been tested!


erbbysam2005
thanks


WolRon2005
I dont know what happens when you mix up the points order, its not been tested!
It all acts as expected.

Moving the bottom points to top, and top to bottom, flips the image upside down.

Swapping lefts and rights mirrors the image.

Making a bow-tie shape flips half the image and stretches it in the middle.


Matty2005
Thanks for this, reasonably useful.


Techlord2005
Heres a Blitz3D compatible version of Shagwana's TexturePopper. Most of the original code retained, Blitz+ GUI commands removed.

Load your image, Adjust Points, and F5 to save to as Bitmap.


Code Archives Forum