118 lines
3.7 KiB
Go
118 lines
3.7 KiB
Go
package external
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
"math"
|
|
"os"
|
|
|
|
"github.com/inkyblackness/hacked/ss1/content/audio"
|
|
"github.com/inkyblackness/hacked/ss1/content/audio/wav"
|
|
"github.com/inkyblackness/hacked/ss1/content/bitmap"
|
|
"github.com/inkyblackness/hacked/ui/gui"
|
|
)
|
|
|
|
// Import starts an import dialog series, calling the given callback with a file name.
|
|
func Import(machine gui.ModalStateMachine, info string, types []TypeInfo, callback func(string), lastFailed bool) {
|
|
machine.SetState(&importStartState{
|
|
machine: machine,
|
|
callback: callback,
|
|
info: info,
|
|
typeInfo: types,
|
|
withError: lastFailed,
|
|
})
|
|
}
|
|
|
|
// ImportAudio is a helper to handle audio file import. The callback is called with the loaded audio.
|
|
func ImportAudio(machine gui.ModalStateMachine, callback func(l8 audio.L8)) {
|
|
info := "File must be a WAV file, 22050 Hz, 8-bit or 16-bit, uncompressed."
|
|
types := []TypeInfo{{Title: "Audio files (*.wav)", Extensions: []string{"wav"}}}
|
|
var fileHandler func(string)
|
|
|
|
fileHandler = func(filename string) {
|
|
reader, err := os.Open(filename)
|
|
if err != nil {
|
|
Import(machine, info, types, fileHandler, true)
|
|
return
|
|
}
|
|
defer func() { _ = reader.Close() }()
|
|
sound, err := wav.Load(reader)
|
|
if err != nil {
|
|
Import(machine, info, types, fileHandler, true)
|
|
return
|
|
}
|
|
callback(sound)
|
|
}
|
|
|
|
Import(machine, info, types, fileHandler, false)
|
|
}
|
|
|
|
// ImportImage is a helper to handle image file import. The callback is called with the loaded image.
|
|
func ImportImage(machine gui.ModalStateMachine, paletteRetriever func() (bitmap.Palette, error), callback func(bitmap.Bitmap)) {
|
|
info := "File should be either a BMP, GIF, or a PNG file.\nPaletted images matching game palette are taken 1:1,\nothers are mapped closest fitting."
|
|
types := []TypeInfo{{Title: "Image files (*.bmp, *.gif, *.png)", Extensions: []string{"bmp", "gif", "png"}}}
|
|
var fileHandler func(string)
|
|
|
|
fileHandler = func(filename string) {
|
|
reader, err := os.Open(filename)
|
|
if err != nil {
|
|
Import(machine, "Could not open file.\n"+info, types, fileHandler, true)
|
|
return
|
|
}
|
|
defer func() { _ = reader.Close() }()
|
|
img, _, err := image.Decode(reader)
|
|
if err != nil {
|
|
Import(machine, "File not recognized as image.\n"+info, types, fileHandler, true)
|
|
return
|
|
}
|
|
|
|
var bmp bitmap.Bitmap
|
|
importMapped := true
|
|
rawPalette, err := paletteRetriever()
|
|
if err != nil {
|
|
Import(machine, "Can not import image without having a palette loaded.\n"+info, types, fileHandler, true)
|
|
return
|
|
}
|
|
if palettedImg, isPaletted := img.(image.PalettedImage); isPaletted {
|
|
imgPalette, hasPalette := palettedImg.ColorModel().(color.Palette)
|
|
if hasPalette && paletteMatches(imgPalette, rawPalette.ColorPalette(false)) {
|
|
bounds := img.Bounds()
|
|
|
|
bmp.Header.Width = int16(math.Max(0, math.Min(float64(bounds.Dx()), math.MaxInt16)))
|
|
bmp.Header.Height = int16(math.Max(0, math.Min(float64(bounds.Dy()), math.MaxInt16)))
|
|
bmp.Pixels = make([]byte, int(bmp.Header.Width)*int(bmp.Header.Height))
|
|
for row := 0; row < int(bmp.Header.Height); row++ {
|
|
for column := 0; column < int(bmp.Header.Width); column++ {
|
|
bmp.Pixels[row*int(bmp.Header.Width)+column] = palettedImg.ColorIndexAt(column, row)
|
|
}
|
|
}
|
|
importMapped = false
|
|
}
|
|
}
|
|
if importMapped {
|
|
bitmapper := bitmap.NewBitmapper(&rawPalette)
|
|
bmp = bitmapper.Map(img)
|
|
}
|
|
callback(bmp)
|
|
}
|
|
|
|
Import(machine, info, types, fileHandler, false)
|
|
}
|
|
|
|
func paletteMatches(imgPalette color.Palette, rawPalette color.Palette) bool {
|
|
if len(imgPalette) > len(rawPalette) {
|
|
return false
|
|
}
|
|
|
|
for index, clr := range imgPalette {
|
|
imgR, imgG, imgB, _ := clr.RGBA()
|
|
rawR, rawG, rawB, _ := rawPalette[index].RGBA()
|
|
|
|
if (imgR != rawR) || (imgG != rawG) || (imgB != rawB) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|