Created
May 30, 2021 22:52
-
-
Save magical/6c7772a3a071866fa4ce353c1dcf5f91 to your computer and use it in GitHub Desktop.
convert TW small format to MSCC (44x44)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"flag" | |
"fmt" | |
"image" | |
"image/color" | |
"io" | |
"os" | |
"golang.org/x/image/bmp" | |
"golang.org/x/image/draw" | |
_ "image/png" | |
) | |
const ( | |
tileWidth = 44 | |
tileHeight = 44 | |
height = tileHeight * 16 | |
width = tileWidth * 7 | |
widthMasked = tileWidth * 13 | |
crStart = tileWidth * 4 | |
crWidth = tileWidth * 3 | |
) | |
func main() { | |
flag.Parse() | |
filename := flag.Arg(0) | |
outname := flag.Arg(1) | |
if filename == "" || outname == "" { | |
fmt.Fprintln(os.Stderr, "usage: makemasked input output.bmp") | |
os.Exit(1) | |
} | |
var confBuf bytes.Buffer | |
origfp, err := os.Open(filename) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
os.Exit(1) | |
} | |
defer origfp.Close() | |
conf, _, err := image.DecodeConfig(io.TeeReader(origfp, &confBuf)) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
os.Exit(1) | |
} | |
if conf.Width != width || conf.Height != height { | |
fmt.Fprintf(os.Stderr, "image is %dx%d, must be %dx%d\n", conf.Width, conf.Height, width, height) | |
os.Exit(1) | |
} | |
origImage, _, err := image.Decode(io.MultiReader(&confBuf, origfp)) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
os.Exit(1) | |
} | |
maskedImage := makeMasked(origImage) | |
if !maskedImage.Opaque() { | |
fmt.Fprintln(os.Stderr, "warning: result is not fully opaque") | |
} | |
outfp, err := os.Create(outname) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
os.Exit(1) | |
} | |
bmp.Encode(outfp, maskedImage) | |
} | |
// Column returns a rectangle with the given x coordinates and a fixed height. | |
func column(x0, x1 int) image.Rectangle { | |
return image.Rect(x0, 0, x1, height) | |
} | |
func sameColor(c0, c1 color.Color) bool { | |
if c0 == c1 { | |
return true | |
} | |
r0, g0, b0, a0 := c0.RGBA() | |
r1, g1, b1, a1 := c1.RGBA() | |
return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1 | |
} | |
func makeMasked(src image.Image) *image.RGBA { | |
var magenta = color.RGBA{0xff, 0, 0xff, 0xff} | |
cr := image.NewRGBA(column(0, crWidth)) | |
p := image.NewRGBA(column(0, widthMasked)) | |
// Copy normal tiles to p | |
draw.Src.Draw(p, column(0, crStart), src, image.ZP) | |
// Copy creatures to cr | |
draw.Src.Draw(cr, column(0, crStart), src, image.Pt(crStart, 0)) | |
// Make creatures transparent | |
for y := 0; y < cr.Rect.Dy(); y++ { | |
for x := 0; x < cr.Rect.Dx(); x++ { | |
c := cr.RGBAAt(x, y) | |
if sameColor(c, magenta) { | |
cr.Set(x, y, color.Transparent) | |
} | |
} | |
} | |
// Draw creatures on top of floors | |
floors := tiled{src, image.Rect(0, 0, tileHeight, tileWidth)} | |
draw.Src.Draw(p, column(crStart, width), &floors, image.ZP) | |
draw.Over.Draw(p, column(crStart, width), cr, image.ZP) | |
// Draw creatures on top of white | |
draw.Src.Draw(p, column(width, width+crWidth), image.White, image.ZP) | |
draw.Over.Draw(p, column(width, width+crWidth), cr, image.ZP) | |
// Draw creature masks | |
draw.Src.Draw(p, column(width+crWidth, width+2*crWidth), &masked{cr}, image.ZP) | |
return p | |
} | |
// tiled repeats a portion of m infinitely in all directions | |
type tiled struct { | |
m image.Image | |
r image.Rectangle | |
} | |
func (t *tiled) ColorModel() color.Model { return t.m.ColorModel() } | |
func (t *tiled) Bounds() image.Rectangle { return image.Rect(-1e9, -1e9, 1e9, 1e9) } | |
func (t *tiled) At(x, y int) color.Color { | |
p := image.Pt(x, y).Mod(t.r) | |
return t.m.At(p.X, p.Y) | |
} | |
type masked struct { | |
m image.Image | |
} | |
func (m *masked) ColorModel() color.Model { return m.m.ColorModel() } | |
func (m *masked) Bounds() image.Rectangle { return m.m.Bounds() } | |
func (m *masked) At(x, y int) color.Color { | |
c := m.m.At(x, y) | |
if _, _, _, a := c.RGBA(); a > 0x7fff { | |
return color.White | |
} | |
return color.Black | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment