Code archives/Graphics/TileWiper V1.2
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
| This was my first Blitz Basic program... I have used it (successfully) on two commercial products for the Game Boy Color... The program looks at each tile in the image and compares it to all other tiles. If several tiles look alike within a certain threshold, the best tile will be used multiple times, thus reducing the number of tiles. Feel free to make a GUI interface or whatever you like. If you do, please let me know. :) Due to the Game Boy Color's hardware, the program also flips the tiles on X and Y if it can. | |||||
;----------------------------;
; TileWiper V1.2 ;
;----------------------------;
;My first Blitz Basic Program;
; Latest version: ;
; January 8th - 2002 ;
;----------------------------;
; Made by ;
; Laust Palbo Nielsen ;
;----------------------------;
; This program was made to ;
;optimize the amount of tiles;
; used in a tilemap on all ;
; tilebased sytems that can ;
; flip tiles ;
; ;
; If you use this program as ;
;part of the development of a;
; commercial product, please ;
;send a copy of the finished ;
; product to me. ;
; ;
; Current address can be ;
; obtained by mailing me ;
; @ laust@palbo.dk ;
;----------------------------;
AppTitle "TileWiper V1.2"
Global TileOne, TileTwo, Changeflag, TileSizeX, TileSizeY, TileSize, TilesX, TilesY, MapSize, PicWidth, PicHeight, MaxLoss#, Tiles
Global Width, Height, OffSetX, OffSetY, Threshold#, Image$
Global Counter
Global SumRed, SumGreen, SumBlue, Sum#, Percent#
Global SumRedFlipX, SumGreenFlipX, SumBlueFlipX, SumFlipX#, PercentFlipX#
Global SumRedFlipY, SumGreenFlipY, SumBlueFlipY, SumFlipY#, PercentFlipY#
Global SumRedFlipXY, SumGreenFlipXY, SumBlueFlipXY, SumFlipXY#, PercentFlipXY#
Global ColorDifRed, ColorDifGreen, ColorDifBlue
Global ColorDifRedFlipX, ColorDifGreenFlipX, ColorDifBlueFlipX
Global ColorDifRedFlipY, ColorDifGreenFlipY, ColorDifBlueFlipY
Global ColorDifRedFlipXY, ColorDifGreenFlipXY, ColorDifBlueFlipXY
Global ColorTwoGreen, ColorOneBlue, ColorTwoBlue
Global ColorTwoRedFlipX, ColorTwoGreenFlipX, ColorTwoBlueFlipX
Global ColorTwoRedFlipY, ColorTwoGreenFlipY, ColorTwoBlueFlipY
Global ColorTwoRedFlipXY, ColorTwoGreenFlipXY, ColorTwoBlueFlipXY
Global Dist#, DistFlipX#, DistFlipY#, DistFlipXY#
Width=352 : Height=420
Graphics3D Width, Height, 32, 2
ClsColor 128,128,196
Cls
Color 255, 255, 255
;-----------------------------------;
; Start the Program ;
;-----------------------------------;
;Get the user information via inputs
Image$=Input$ ("Source image: ") If Image$="" Then Image$="background.bmp"
Loss#=Input ("Loss (1-100) - Press Enter for 100 : ") If Loss#=0 Then Loss#=100
Thres#=Loss# ;Input ("Threshold (1-100): ") If Thres#=0 Then Thres#=5
TileSizeX=Input ("Tile size X - Press Enter for 8 : ") If TileSizeX=0 Then TileSizeX=8
TileSizeY=Input ("Tile size Y - Press Enter for 8 : ") If TileSizeY=0 Then TileSizeY=8
ImgSize=LoadImage (Image$)
PicWidth=ImageWidth (ImgSize)
PicHeight=ImageHeight (ImgSize)
TileSize=TileSizeX*TileSizeY
FreeImage (ImgSize)
;Now that the user has typed in this information, get the last variables
MaxLoss#=Loss#*195.075*TileSize
Threshold#=Thres#*195.075*(TileSize/20)
;Get the number of tiles on the X and Y Axis
TilesX=PicWidth/TileSizeX
TilesY=PicHeight/TileSizeY
;Get the number of tiles in all
MapSize=(TilesX*TilesY)
;Get the starttime so we can see how long it takes
StartTime=MilliSecs()
;Change the screenmode if the picture is too large
Width=Picwidth+32
Height=PicHeight+260
If Width<352 Then Width=352
If Height<420 Then Height=420
Graphics3D Width, Height, 32 ,2
ClsColor 128,128,196
;Clear the screen and start working
Cls
OptimizedImage=CreateImage (PicWidth, PicHeight)
;Set the offsets so the pictures will be centered on the screen
OffsetX=(Width-PicWidth)/2
OffsetY=(Height-PicHeight)/4
Dim NewMap (MapSize) ;This is where the final map will be stored
Dim FlipMap (MapSize) ;This map stores the data of which way a tile is flipped
Dim PercentMap# (Mapsize) ;This map stores the current % information of each tile
Dim TileSetRed (TileSize, MapSize) ;These three arrays store the standard tile colors
Dim TileSetGreen (TileSize, MapSize)
Dim TileSetBlue (TileSize, MapSize)
Dim TileSetRedFlipX (TileSize, MapSize) ;These three arrays store the tile colors of tiles flipped
Dim TileSetGreenFlipX (TileSize, MapSize) ;on the X-axis
Dim TileSetBlueFlipX (TileSize, MapSize)
Dim TileSetRedFlipY (TileSize, MapSize) ;These three arrays store the tile colors of tiles flipped
Dim TileSetGreenFlipY (TileSize, MapSize) ;on the Y-axis
Dim TileSetBlueFlipY (TileSize, MapSize)
Dim TileSetRedFlipXY (TileSize, MapSize) ;These three arrays store the tile colors of tiles flipped
Dim TileSetGreenFlipXY (TileSize, MapSize) ;on the X and Y-axis
Dim TileSetBlueFlipXY (TileSize, MapSize)
Dim CountArray (MapSize) ;This array is used at the end to count the amount of unique tiles
;Setup the NewMap and PercentMap arrays so all the tiles that aren't changed will still be drawn
Setup ()
;Load the Tilemap
Tiles=LoadAnimImage (Image$, TileSizeX, TileSizeY, 0, MapSize)
PreCalculate ()
SetBuffer FrontBuffer() ;Now that we're done, go to the frontbuffer
Cls ;and clear the screen
PreCalcTimeEnd=MilliSecs()
;DrawSource ()
DrawDestination ()
Color 255, 255, 255
Text Width/2, OffsetY-20, "Precalculation done in "+((PreCalcTimeEnd-StartTime)/1000)+" seconds", 1, 0
;Main Program
;----------------------------
Main ()
;Compare
;--------------------------------
For Count=MapSize-1 To 0 Step -1 ;Go through the entire map backwards
Compare=NewMap(Count) ;Compare gets the tilenumber that has been used in NewMap(Count)
If Compare<>Newmap(Compare) ;If the tile on the position that equals Compare does npt itself equal Compare,
NewMap(Compare)=Compare ;then put it back in its original position
FlipMap(Compare)=0 ;and make sure that it is not flipped.
End If
Next
;Draw the last changes
;--------------------------------
SetBuffer ImageBuffer(OptimizedImage)
FlipTiles ()
SetBuffer FrontBuffer()
DrawImage (OptimizedImage, OffsetX, OffsetY)
;Check to see how many different tiles are left.
;--------------------------------
For Count=0 To MapSize-1
Intermediate=NewMap(Count)
For Reading=Count+1 To MapSize-1
If Intermediate=Newmap(Reading)
CountArray(Reading)=0
End If
Next
Next
;Check to see how many of these tiles are flipped.
;--------------------------------
FinalCount=0
FlipXsum=0
FlipYsum=0
FlipXYsum=0
For Count=0 To MapSize-1
FinalCount=FinalCount+CountArray(Count)
If FlipMap(Count)>0
If FlipMap(Count)=1 Then FlipXsum=FlipXsum+1
If FlipMap(Count)=2 Then FlipYsum=FlipYsum+1
If FlipMap(Count)=3 Then FlipXYsum=FlipXYsum+1
End If
Next
;Prepare a TileSet from NewMap
;--------------------------------
;!!!Note: This is where I should create a binary file to store the map information!!!
TileSet ()
;Print the final results
;--------------------------------
Color 128,128,196 ;Set the color to the background color
Rect (Width/2)-60, 20, 120, 20, 1 ;Remove what we displayed last time
Color 255, 255, 255 ;Set the color to white
StopTime=MilliSecs()
Text Width/2, 20, "Done in "+((StopTime-StartTime)/1000)+" seconds", 1, 0
Text 8, Height-180, " # of Tiles: "+MapSize
Text 8, Height-160, " Unique Tiles: "+FinalCount
Text 8, Height-120, " Tiles Flipped X: "+FlipXsum
Text 8, Height-100, " Tiles Flipped Y: "+FlipYsum
Text 8, Height-80, " Tiles Flipped XY: "+FlipXYsum
Text 8, Height-40, " Press 'S' to save optimized BMP image."
Text 8, Height-20, " Press ESC to quit."
;Wait for the final user interaction
;--------------------------------
Repeat
If KeyDown(1)=1 Then End ;If user presses ESC then end the program
If KeyDown(31)=1 ;If user presses 'S' then save the images and end the program
SaveImage (OptimizedImage, "TW_"+Image$)
End
End If
Forever
End
;!!!!----------------------------------------------------Functions------------------------------------------------------!!!!
Function Setup ()
For Count=0 To MapSize-1
NewMap(Count)=Count
PercentMap#(Count)=MaxLoss#
CountArray(Count)=1
Next
End Function
;------------------------------
Function PreCalculate()
;Store all colors of all tiles in four sets of arrays: TileSet
Text width/2, 0, "Precalculating!", 1, 0 ;Tell the user why 'nothing' is happening
For PreCalc=0 To MapSize-1
SetBuffer BackBuffer() ;Do all the drawing in the backbuffer so it doesn't look weird onscreen
DrawBlock (tiles, 0, 0, PreCalc)
PreCalcCount=0
CounterX=0
CounterY=0
For Y=0 To TileSizeY-1
For X=0 To TileSizeX-1
GetColor X, Y
TileSetRed (PreCalcCount, PreCalc)=ColorRed() ;Store R, G and B values of the source tiles
TileSetGreen (PreCalcCount, PreCalc)=ColorGreen()
TileSetBlue (PreCalcCount, PreCalc)=ColorBlue()
FlipXOne=(TileSizeX-1)-X ;Flip X-values
FlipYOne=(Y) ;Y is normal
FlipX=FlipXOne+(TileSizeX*FlipYOne) ;Calculate the FlipX value
TileSetRedFlipX (FlipX, PreCalc)=ColorRed() ;Store R, G and B values of tiles flipped
TileSetGreenFlipX (FlipX, PreCalc)=ColorGreen() ;on the X-axis
TileSetBlueFlipX (FlipX, PreCalc)=ColorBlue()
FlipXOne=(X) ;X is normal
FlipYOne=(TileSizeY-1)-Y ;Flip Y-values
FlipY=FlipXOne+(TileSizeX*FlipYOne) ;Calculate the FlipX value
TileSetRedFlipY (FlipY, PreCalc)=ColorRed() ;Store R, G and B values of tiles flipped
TileSetGreenFlipY (FlipY, PreCalc)=ColorGreen() ;on the Y-axis
TileSetBlueFlipY (FlipY, PreCalc)=ColorBlue()
FlipXOne=(TileSizeX-1)-X ;Flip X-values
FlipYOne=(TileSizeY-1)-Y ;Flip Y-valus
FlipXY=FlipXOne+(TileSizeX*FlipYOne) ;Calculate the FlipXY value
TileSetRedFlipXY (FlipXY, PreCalc)=ColorRed() ;Store R, G and B values of tiles flipped
TileSetGreenFlipXY (FlipXY, PreCalc)=ColorGreen() ;on the X and Y-axis
TileSetBlueFlipXY (FlipXY, PreCalc)=ColorBlue()
PreCalcCount=PreCalcCount+1
Next
Next
If KeyDown(1)=1 Then End
SetBuffer FrontBuffer() ;Go back to the frontbuffer and show the user that something is actually happening
Color 128,128,196 ;Set the color to the background color
Rect (Width/2)-60, 20, 120, 20, 1 ;Remove what we displayed last time
Color 255, 255, 255 ;Set the color to white
Text Width/2, 20, (PreCalc+1)+"/"+MapSize, 1, 0 ;Show how far we've come
Next
End Function
;------------------------------
Function Main ()
Color 0, 255, 128
RectX=0 : RectY=0
For TileOne=0 To MapSize-1
If RectX=PicWidth
RectX=0
RectY=RectY+TileSizeY
End If
If PercentMap#(TileOne)<>-1 ;Only check if the tile hasn't been locked.
Color 128,128,196 ;Set the color to the background color
Rect (Width/2)-60, 20, 120, 20, 1 ;Remove what we displayed last time
Color 255, 255, 255 ;Set the color to white
Text Width/2, 20, TileOne+"/"+MapSize, 1, 0 ;Show how far we've come
; For TileTwo=TileOne+1 To MapSize-1
For TileTwo=0 To MapSize-1
If PercentMap#(TileTwo)<>-1 And TileTwo<>TileOne
Color 128, 0, 128
Rect OffSetX+RectX, OffSetY+RectY, TileSizeX, TileSizeY, 1
CompareTiles ()
End If
Next
;If there has been any changes to NewMap (ChangeFlag is set to 1) then redraw NewMap
If ChangeFlag=1
DrawDestination ()
ChangeFlag=0
End If
End If
RectX=RectX+TileSizeX
Next
End Function
;------------------------------
Function DrawSource ()
Frame=0
For y=0 To TilesY-1
For x=0 To TilesX-1
DrawBlock (Tiles, (X*TileSizeX)+OffsetX-1, (Y*TileSizeY+OffsetY), Frame)
Frame=Frame+1
Next
Next
End Function
;------------------------------
Function DrawDestination ()
Frame=0
For y=0 To TilesY-1
For x=0 To TilesX-1
DrawBlock (Tiles, (X*TileSizeX)+OffsetX, (Y*TileSizeY+OffsetY), NewMap(Frame))
Frame=Frame+1
Next
Next
End Function
;------------------------------
Function CompareTiles ()
Counter=0
SumRed=0
SumGreen=0
SumBlue=0
Sum#=0
SumRedFlipX=0
SumGreenFlipX=0
SumBlueFlipX=0
SumFlipX#=0
SumRedFlipY=0
SumGreenFlipY=0
SumBlueFlipY=0
SumFlipY#=0
SumRedFlipXY=0
SumGreenFlipXY=0
SumBlueFlipXY=0
SumFlipXY#=0
Dist#=0
DistFlipX#=0
DistFlipY#=0
DistFlipXY#=0
For Counter=0 To TileSize-1
GetRGBValues ()
GetSums ()
Next
;Since most of the time is spent in this loop, the user can exit it here by pressing 'Esc.'
If KeyDown(1)=1 Then End
If Sum#=0 Or Sum#<Threshold# And PercentMap(TileTwo)<>-1
NewMap(TileTwo)=TileOne
PercentMap#(TileTwo)=-1
FlipMap(TileTwo)=0
ChangeFlag=1
End If
If SumFlipX#=0 Or SumFlipX#<Threshold# And PercentMap(TileTwo)<>-1
NewMap(TileTwo)=TileOne
PercentMap#(TileTwo)=-1
FlipMap(TileTwo)=1
ChangeFlag=1
End If
If SumFlipY#=0 Or SumFlipY#<Threshold# And PercentMap(TileTwo)<>-1
NewMap(TileTwo)=TileOne
PercentMap#(TileTwo)=-1
FlipMap(TileTwo)=2
ChangeFlag=1
End If
If SumFlipXY#=0 Or SumFlipXY#<Threshold# And PercentMap(TileTwo)<>-1
NewMap(TileTwo)=TileOne
PercentMap#(TileTwo)=-1
FlipMap(TileTwo)=3
ChangeFlag=1
End If
DoSums ()
End Function
;--------------------------------
Function GetRGBValues ()
;Get the RGB values for tiles that aren't flipped.
ColorOneRed=TileSetRed(Counter, TileOne)
ColorTwoRed=TileSetRed(Counter, TileTwo)
ColorOneGreen=TileSetGreen(Counter, TileOne)
;Get the RGB values for the tiles that we are comparing to.
ColorTwoGreen=TileSetGreen(Counter, TileTwo)
ColorOneBlue=TileSetBlue(Counter, TileOne)
ColorTwoBlue=TileSetBlue(Counter, TileTwo)
;Get the RGB values for tiles that are flipped X.
ColorTwoRedFlipX=TileSetRedFlipX(Counter, TileTwo)
ColorTwoGreenFlipX=TileSetGreenFlipX(Counter, TileTwo)
ColorTwoBlueFlipX=TileSetBlueFlipX(Counter, TileTwo)
;Get the RGB values for tiles that are flipped Y.
ColorTwoRedFlipY=TileSetRedFlipY(Counter, TileTwo)
ColorTwoGreenFlipY=TileSetGreenFlipY(Counter, TileTwo)
ColorTwoBlueFlipY=TileSetBlueFlipY(Counter, TileTwo)
;Get the RGB values for tiles that are flipped X and Y.
ColorTwoRedFlipXY=TileSetRedFlipXY(Counter, TileTwo)
ColorTwoGreenFlipXY=TileSetGreenFlipXY(Counter, TileTwo)
ColorTwoBlueFlipXY=TileSetBlueFlipXY(Counter, TileTwo)
Dist#=Dist#+((ColorOneRed-ColorTwoRed)*(ColorOneRed-ColorTwoRed))+((ColorOneGreen-ColorTwoGreen)*(ColorOneGreen-ColorTwoGreen))+((ColorOneBlue-ColorTwoBlue)*(ColorOneBlue-ColorTwoBlue))
DistFlipX#=DistFlipX#+((ColorOneRed-ColorTwoRedFlipX)*(ColorOneRed-ColorTwoRedFlipX))+((ColorOneGreen-ColorTwoGreenFlipX)*(ColorOneGreen-ColorTwoGreenFlipX))+((ColorOneBlue-ColorTwoBlueFlipX)*(ColorOneBlue-ColorTwoBlueFlipX))
DistFlipY#=DistFlipY#+((ColorOneRed-ColorTwoRedFlipY)*(ColorOneRed-ColorTwoRedFlipY))+((ColorOneGreen-ColorTwoGreenFlipY)*(ColorOneGreen-ColorTwoGreenFlipY))+((ColorOneBlue-ColorTwoBlueFlipY)*(ColorOneBlue-ColorTwoBlueFlipY))
DistFlipXY#=DistFlipXY#+((ColorOneRed-ColorTwoRedFlipXY)*(ColorOneRed-ColorTwoRedFlipXY))+((ColorOneGreen-ColorTwoGreenFlipXY)*(ColorOneGreen-ColorTwoGreenFlipXY))+((ColorOneBlue-ColorTwoBlueFlipXY)*(ColorOneBlue-ColorTwoBlueFlipXY))
End Function
;--------------------------------
Function GetSums ()
;Add it all up and get a final sum for tiles that aren't flipped.
Sum#=Dist#
SumFlipX#=DistFlipX#
SumFlipY#=DistFlipY#
SumFlipXY#=DistFlipXY#
;WaitMouse
End Function
;--------------------------------
Function DoSums()
Percent#=Sum#;/TileSize
PercentFlipX#=SumFlipX#;/TileSize
PercentFlipY#=SumFlipY#;/TileSize
PercentFlipXY#=SumFlipXY#;/TileSize
;--------------------------------
;If this tile looks more like the original than any other, then use this tile instead.
If Percent#<MaxLoss# And Percent#<=PercentMap#(TileTwo)
PercentMap#(TileTwo)=Percent#
NewMap(TileTwo)=TileOne
FlipMap(TileTwo)=0
ChangeFlag=1 ;By setting ChangeFlag to 1, the NewMap will be redrawn
End If
;If this tile, flipped X, looks more like the original than any other, then use this tile instead.
If PercentFlipX#<MaxLoss# And PercentFlipX#<=PercentMap#(TileTwo)
PercentMap#(TileTwo)=PercentFlipX#
NewMap(TileTwo)=TileOne
FlipMap(TileTwo)=1
ChangeFlag=1 ;By setting ChangeFlag to 1, the NewMap will be redrawn
End If
;If this tile, flipped Y, looks more like the original than any other, then use this tile instead.
If PercentFlipY#<MaxLoss# And PercentFlipY#<=PercentMap#(TileTwo)
PercentMap#(TileTwo)=PercentFlipY#
NewMap(TileTwo)=TileOne
FlipMap(TileTwo)=2
ChangeFlag=1 ;By setting ChangeFlag to 1, the NewMap will be redrawn
End If
;If this tile, flipped X and Y, looks more like the original than any other, then use this tile instead.
If PercentFlipXY#<MaxLoss# And PercentFlipXY#<=PercentMap#(TileTwo)
PercentMap#(TileTwo)=PercentFlipXY#
NewMap(TileTwo)=TileOne
FlipMap(TileTwo)=3
ChangeFlag=1 ;By setting ChangeFlag to 1, the NewMap will be redrawn
End If
End Function
;--------------------------------
Function FlipTiles ()
Frame=0
For Y=0 To TilesY-1
For X=0 To TilesX-1
;Draw the NewMap one last time to make sure that the new changes are drawn
If FlipMap(Frame)=0 ;Check the FlipMap to make sure that this tile shouldn't be flipped
DrawBlock (Tiles, (X*TileSizeX), Y*TileSizeY, NewMap(Frame))
End If
;Flip the tiles that need to be flipped
If FlipMap(Frame)>0 ;Check the FlipMap to see if (and how) this tile should be flipped
CountPixel=0
For PY=0 To TilesizeY-1
For PX=0 To TilesizeX-1
If FlipMap(Frame)=1 Then Color TileSetRedFlipX(CountPixel, NewMap(Frame)), TileSetGreenFlipX(CountPixel, NewMap(Frame)), TileSetBlueFlipX(CountPixel, NewMap(Frame))
If FlipMap(Frame)=2 Then Color TileSetRedFlipY(CountPixel, NewMap(Frame)), TileSetGreenFlipY(CountPixel, NewMap(Frame)), TileSetBlueFlipY(CountPixel, NewMap(Frame))
If FlipMap(Frame)=3 Then Color TileSetRedFlipXY(CountPixel, NewMap(Frame)), TileSetGreenFlipXY(CountPixel, NewMap(Frame)), TileSetBlueFlipXY(CountPixel, NewMap(Frame))
Plot (X*TileSizeX)+PX, (Y*TileSizeY)+PY
CountPixel=CountPixel+1
Next
Next
End If
Frame=Frame+1
Next
Next
End Function
;--------------------------------
Function TileSet ()
NewSet=CreateImage (PicWidth, PicHeight)
SetBuffer ImageBuffer(NewSet)
DrawBlock (Tiles, 0, 0, 0)
GetColor 0, 0
ClsColor ColorRed(), ColorGreen(), ColorBlue()
Cls
CounterTwo=0 : X=0 : Y=0
For Count=0 To FinalCount-1
Repeat
If CountArray(CounterTwo)=1
DrawBlock (Tiles, X*TileSizeX, Y*TileSizeY, NewMap(CounterTwo))
Flag=1 : X=X+1
If X=TilesX
Y=Y+1
X=0
End If
End If
CounterTwo=CounterTwo+1
Until Flag=1
Flag=0
Next
SetBuffer FrontBuffer()
End Function |
Comments
None.
Code Archives Forum