03-03-2024, 05:56 AM
(This post was last modified: 03-03-2024, 05:57 AM by TerryRitchie.)
I was working on a way to extract individual sprites (or images) from a sprite sheet. Most sprite sheets found on the Internet are not neatly organized in same sized rectangular areas across the sheet.
At first I tried to design a line follower that would trace around sprites to find their area. That was like herding cats.
It then occurred to me that a flood fill like recursive routine may work. It does! The code below is a quick hack to show the concept in action. You'll need the image to see the code in action.
There's still some issues to work out but I thought someone might like to play with the code as is.
At first I tried to design a line follower that would trace around sprites to find their area. That was like herding cats.
It then occurred to me that a flood fill like recursive routine may work. It does! The code below is a quick hack to show the concept in action. You'll need the image to see the code in action.
There's still some issues to work out but I thought someone might like to play with the code as is.
Code: (Select All)
' Parse a sprite sheet concept
'
' Issues to overcome:
' - Individual pixels are seen as separate sprites (the last 5 sprites in image)
' Somehow the code needs to intelligently decide that these pixels belong to a sprite
'
TYPE XY
x AS INTEGER
y AS INTEGER
END TYPE
DIM Min AS XY ' minimum x,y values seen
DIM Max AS XY ' maximum x,y values seen
DIM Background AS _UNSIGNED LONG ' background color to use as border
DIM Pixel AS _UNSIGNED LONG ' pixel color
DIM SourceSheet AS LONG ' source image containing sprites
DIM TargetSheet AS LONG ' target image to write found sprites to
DIM x AS INTEGER ' horizontal coordinate counter
DIM y AS INTEGER ' vertical coordinate counter
SourceSheet = _LOADIMAGE("demon.png", 32) ' load source sprite sheet
TargetSheet = _NEWIMAGE(_WIDTH(SourceSheet), _HEIGHT(SourceSheet), 32) ' create target sprite sheet
SCREEN _NEWIMAGE(781, 720, 32) ' create view screen
CLS
Background = _RGB32(255, 0, 255) ' background border color (bright magenta)
_SOURCE SourceSheet ' get pixel data from source image
y = 0 ' reset vertical counter
DO
x = 0 ' reset horizontal counter
DO
' scan right until a pixel is found
Pixel = POINT(x, y) ' get pixel color
IF Pixel <> Background THEN ' is this pixel part of a sprite?
' A pixel has been found
Min.x = x ' set starting point of min/max x,y values seen
Max.x = x
Min.y = y
Max.y = y
GrabSprite x, y, SourceSheet, TargetSheet, Background ' recursively get sprite
' Now the sprite has been written to the target image and the min/max x,y coordinates are known
' Grab the written sprite as you wish and then remove it from the target sheet
' This nethod would work just as well if for instance the mouse pointer was used to click
' anywhere inside of a sprite to extract it.
' Quick code to show the concept in action
_DEST 0
_PUTIMAGE (0, 0), SourceSheet
_PUTIMAGE (0, 360), TargetSheet
LOCATE 1, 1
PRINT Max.x - Min.x, Max.y - Min.y ' current sprite dimensions
_LIMIT 5 ' slow down to see progress
END IF
x = x + 1
LOOP UNTIL x = _WIDTH(SourceSheet)
y = y + 1
LOOP UNTIL y = _HEIGHT(SourceSheet)
SUB GrabSprite (x AS INTEGER, y AS INTEGER, s AS LONG, t AS LONG, Border AS _UNSIGNED LONG)
' Recursively grabs an image within the border color specified (proof of concept)
' (Based on flood fill)
' x,y - pixel coordinate
' s - source image
' t - target image
' b - border (background) color
SHARED Min AS XY
SHARED Max AS XY
DIM Pixel AS _UNSIGNED LONG
IF x = -1 OR y = -1 OR x = _WIDTH(s) OR y = _HEIGHT(s) THEN EXIT SUB ' leave if x,y outside of source image
_SOURCE s ' get from source image
Pixel = POINT(x, y) ' get pixel color
IF Pixel = Border THEN EXIT SUB ' leave if pixel is border color
_DEST t ' draw on target image
PSET (x, y), Pixel ' copy pixel to target image
_DEST s ' draw on source image
PSET (x, y), Border ' remove pixel from source image
MinMax x, y, Min, Max ' get x and y extremes seen
GrabSprite x - 1, y, s, t, Border ' examine surrounding pixels
GrabSprite x + 1, y, s, t, Border
GrabSprite x, y - 1, s, t, Border
GrabSprite x, y + 1, s, t, Border
GrabSprite x - 1, y - 1, s, t, Border
GrabSprite x - 1, y + 1, s, t, Border
GrabSprite x + 1, y - 1, s, t, Border
GrabSprite x + 1, y + 1, s, t, Border
END SUB
SUB MinMax (x AS INTEGER, y AS INTEGER, min AS XY, max AS XY)
IF x < min.x THEN
min.x = x
ELSEIF x > max.x THEN
max.x = x
END IF
IF y < min.y THEN
min.y = y
ELSEIF y > max.y THEN
max.y = y
END IF
END SUB