mirror of
https://github.com/Dadido3/noita-mapcap.git
synced 2024-11-18 17:17:31 +00:00
Remove pre-render mode from stitcher & Cleanup
This commit is contained in:
parent
cd1428706e
commit
7d250d6405
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -14,9 +14,11 @@
|
|||||||
"gridify",
|
"gridify",
|
||||||
"hacky",
|
"hacky",
|
||||||
"hilbertify",
|
"hilbertify",
|
||||||
|
"Hitbox",
|
||||||
"ipairs",
|
"ipairs",
|
||||||
"kbinani",
|
"kbinani",
|
||||||
"Lanczos",
|
"Lanczos",
|
||||||
|
"lann",
|
||||||
"ldflags",
|
"ldflags",
|
||||||
"linearize",
|
"linearize",
|
||||||
"lowram",
|
"lowram",
|
||||||
@ -25,7 +27,6 @@
|
|||||||
"nfnt",
|
"nfnt",
|
||||||
"noita",
|
"noita",
|
||||||
"polymorphed",
|
"polymorphed",
|
||||||
"prerender",
|
|
||||||
"promptui",
|
"promptui",
|
||||||
"rasterizer",
|
"rasterizer",
|
||||||
"savegames",
|
"savegames",
|
||||||
|
@ -46,8 +46,6 @@ example list of files:
|
|||||||
Lower bound of the output rectangle. This coordinate is not included in the output.
|
Lower bound of the output rectangle. This coordinate is not included in the output.
|
||||||
- `ymin int`
|
- `ymin int`
|
||||||
Upper bound of the output rectangle. This coordinate is included in the output.
|
Upper bound of the output rectangle. This coordinate is included in the output.
|
||||||
- `prerender`
|
|
||||||
Pre renders the image in RAM before saving. Can speed things up if you have enough RAM.
|
|
||||||
- `cleanup float`
|
- `cleanup float`
|
||||||
Enables cleanup mode with the given float as threshold. This will **DELETE** images from the input folder; no stitching will be done in this mode. A good value to start with is `0.999`, which deletes images where the sum of the min-max difference of each sub-pixel overlapping with other images is less than 99.9%% of the maximum possible sum of pixel differences.
|
Enables cleanup mode with the given float as threshold. This will **DELETE** images from the input folder; no stitching will be done in this mode. A good value to start with is `0.999`, which deletes images where the sum of the min-max difference of each sub-pixel overlapping with other images is less than 99.9%% of the maximum possible sum of pixel differences.
|
||||||
|
|
||||||
|
@ -8,14 +8,13 @@ package main
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"image/color"
|
"image/color"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tdewolff/canvas"
|
"github.com/tdewolff/canvas"
|
||||||
)
|
)
|
||||||
|
|
||||||
var entityDisplayFontFamily = canvas.NewFontFamily("times")
|
//var entityDisplayFontFamily = canvas.NewFontFamily("times")
|
||||||
var entityDisplayFontFace *canvas.FontFace
|
//var entityDisplayFontFace *canvas.FontFace
|
||||||
|
|
||||||
var entityDisplayAreaDamageStyle = canvas.Style{
|
var entityDisplayAreaDamageStyle = canvas.Style{
|
||||||
FillColor: color.RGBA{100, 0, 0, 100},
|
FillColor: color.RGBA{100, 0, 0, 100},
|
||||||
@ -73,13 +72,13 @@ var entityDisplayCollisionTriggerStyle = canvas.Style{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
fontName := "NimbusRoman-Regular"
|
//fontName := "NimbusRoman-Regular"
|
||||||
|
|
||||||
if err := entityDisplayFontFamily.LoadLocalFont(fontName, canvas.FontRegular); err != nil {
|
//if err := entityDisplayFontFamily.LoadLocalFont(fontName, canvas.FontRegular); err != nil {
|
||||||
log.Printf("Couldn't load font %q: %v", fontName, err)
|
// log.Printf("Couldn't load font %q: %v", fontName, err)
|
||||||
}
|
//}
|
||||||
|
|
||||||
entityDisplayFontFace = entityDisplayFontFamily.Face(48.0, canvas.White, canvas.FontRegular, canvas.FontNormal)
|
//entityDisplayFontFace = entityDisplayFontFamily.Face(48.0, canvas.White, canvas.FontRegular, canvas.FontNormal)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entity struct {
|
type Entity struct {
|
||||||
@ -146,6 +145,7 @@ func (e Entity) Draw(c *canvas.Context) {
|
|||||||
if member, ok := component.Members["circle_radius"]; ok {
|
if member, ok := component.Members["circle_radius"]; ok {
|
||||||
if radius, ok := member.(float64); ok && radius > 0 {
|
if radius, ok := member.(float64); ok && radius > 0 {
|
||||||
// Theoretically we need to clip the damage area to the intersection of the AABB and the circle, but meh.
|
// Theoretically we need to clip the damage area to the intersection of the AABB and the circle, but meh.
|
||||||
|
// TODO: Clip the area to the intersection of the box and the circle
|
||||||
cx, cy := (aabbMinX+aabbMaxX)/2, (aabbMinY+aabbMaxY)/2
|
cx, cy := (aabbMinX+aabbMaxX)/2, (aabbMinY+aabbMaxY)/2
|
||||||
c.Style = entityDisplayAreaDamageStyle
|
c.Style = entityDisplayAreaDamageStyle
|
||||||
c.DrawPath(x+cx, y+cy, canvas.Circle(radius))
|
c.DrawPath(x+cx, y+cy, canvas.Circle(radius))
|
||||||
@ -201,7 +201,7 @@ func (e Entity) Draw(c *canvas.Context) {
|
|||||||
c.DrawPath(x+aabbMinX, y+aabbMinY, canvas.Rectangle(aabbMaxX-aabbMinX, aabbMaxY-aabbMinY))
|
c.DrawPath(x+aabbMinX, y+aabbMinY, canvas.Rectangle(aabbMaxX-aabbMinX, aabbMaxY-aabbMinY))
|
||||||
}
|
}
|
||||||
|
|
||||||
case "CollisionTriggerComponent": // Checks if another entity is inside the box with the given width and height.
|
case "CollisionTriggerComponent": // Checks if another entity is inside the given radius and box with the given width and height.
|
||||||
var width, height float64
|
var width, height float64
|
||||||
path := &canvas.Path{}
|
path := &canvas.Path{}
|
||||||
if member, ok := component.Members["width"]; ok {
|
if member, ok := component.Members["width"]; ok {
|
||||||
@ -213,6 +213,8 @@ func (e Entity) Draw(c *canvas.Context) {
|
|||||||
if width > 0 && height > 0 {
|
if width > 0 && height > 0 {
|
||||||
path = canvas.Rectangle(width, height).Translate(-width/2, -height/2)
|
path = canvas.Rectangle(width, height).Translate(-width/2, -height/2)
|
||||||
}
|
}
|
||||||
|
// Theoretically we need to clip the area to the intersection of the box and the circle, but meh.
|
||||||
|
// TODO: Clip the area to the intersection of the box and the circle
|
||||||
//if member, ok := component.Members["radius"]; ok {
|
//if member, ok := component.Members["radius"]; ok {
|
||||||
// if radius, ok := member.(float64); ok && radius > 0 {
|
// if radius, ok := member.(float64); ok && radius > 0 {
|
||||||
// path = path.Append(canvas.Circle(radius))
|
// path = path.Append(canvas.Circle(radius))
|
||||||
|
@ -76,7 +76,7 @@ func (mbi *MedianBlendedImage) At(x, y int) color.Color {
|
|||||||
|
|
||||||
// Opaque returns whether the image is fully opaque.
|
// Opaque returns whether the image is fully opaque.
|
||||||
//
|
//
|
||||||
// For more speed and smaller filesizes, MedianBlendedImage will be marked as non-transparent.
|
// For more speed and smaller file size, MedianBlendedImage will be marked as non-transparent.
|
||||||
// This will speed up image saving by 2x, as there is no need to iterate over the whole image to find a single non opaque pixel.
|
// This will speed up image saving by 2x, as there is no need to iterate over the whole image to find a single non opaque pixel.
|
||||||
func (mbi *MedianBlendedImage) Opaque() bool {
|
func (mbi *MedianBlendedImage) Opaque() bool {
|
||||||
return true
|
return true
|
||||||
|
@ -21,15 +21,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var flagInputPath = flag.String("input", filepath.Join(".", "..", "..", "output"), "The source path of the image tiles to be stitched.")
|
var flagInputPath = flag.String("input", filepath.Join(".", "..", "..", "output"), "The source path of the image tiles to be stitched.")
|
||||||
var flagEntitiesInputPath = flag.String("entities", filepath.Join(".", "..", "..", "output", "entities.json"), "The source path of the entities.json file.")
|
var flagEntitiesInputPath = flag.String("entities", filepath.Join(".", "..", "..", "output", "entities.json"), "The path to the entities.json file.")
|
||||||
var flagPlayerPathInputPath = flag.String("player-path", filepath.Join(".", "..", "..", "output", "player-path.json"), "The source path of the player-path.json file.")
|
var flagPlayerPathInputPath = flag.String("player-path", filepath.Join(".", "..", "..", "output", "player-path.json"), "The path to the player-path.json file.")
|
||||||
var flagOutputPath = flag.String("output", filepath.Join(".", "output.png"), "The path and filename of the resulting stitched image.")
|
var flagOutputPath = flag.String("output", filepath.Join(".", "output.png"), "The path and filename of the resulting stitched image.")
|
||||||
var flagScaleDivider = flag.Int("divide", 1, "A downscaling factor. 2 will produce an image with half the side lengths.")
|
var flagScaleDivider = flag.Int("divide", 1, "A downscaling factor. 2 will produce an image with half the side lengths.")
|
||||||
var flagXMin = flag.Int("xmin", 0, "Left bound of the output rectangle. This coordinate is included in the output.")
|
var flagXMin = flag.Int("xmin", 0, "Left bound of the output rectangle. This coordinate is included in the output.")
|
||||||
var flagYMin = flag.Int("ymin", 0, "Upper bound of the output rectangle. This coordinate is included in the output.")
|
var flagYMin = flag.Int("ymin", 0, "Upper bound of the output rectangle. This coordinate is included in the output.")
|
||||||
var flagXMax = flag.Int("xmax", 0, "Right bound of the output rectangle. This coordinate is not included in the output.")
|
var flagXMax = flag.Int("xmax", 0, "Right bound of the output rectangle. This coordinate is not included in the output.")
|
||||||
var flagYMax = flag.Int("ymax", 0, "Lower bound of the output rectangle. This coordinate is not included in the output.")
|
var flagYMax = flag.Int("ymax", 0, "Lower bound of the output rectangle. This coordinate is not included in the output.")
|
||||||
var flagPrerender = flag.Bool("prerender", false, "Pre renders the image in RAM before saving. Can speed things up if you have enough RAM.")
|
|
||||||
var flagCleanupThreshold = flag.Float64("cleanup", 0, "Enable cleanup mode with the given threshold. This will DELETE images from the input folder, no stitching will be done in this mode. A good value to start with is 0.999, which deletes images where the sum of the min-max difference of each sub-pixel overlapping with other images is less than 99.9%% of the maximum possible sum of pixel differences.")
|
var flagCleanupThreshold = flag.Float64("cleanup", 0, "Enable cleanup mode with the given threshold. This will DELETE images from the input folder, no stitching will be done in this mode. A good value to start with is 0.999, which deletes images where the sum of the min-max difference of each sub-pixel overlapping with other images is less than 99.9%% of the maximum possible sum of pixel differences.")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -272,43 +271,30 @@ func main() {
|
|||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
done := make(chan bool)
|
done := make(chan bool)
|
||||||
|
|
||||||
if *flagPrerender {
|
tempImage := NewMedianBlendedImage(tiles, outputRect)
|
||||||
log.Printf("Creating output image with a size of %v", outputRect.Size())
|
_, max := tempImage.Progress()
|
||||||
tempImage := image.NewRGBA(outputRect)
|
bar.SetTotal(int64(max)).Start().SetRefreshRate(1 * time.Second)
|
||||||
|
|
||||||
log.Printf("Stitching %v tiles into an image at %v", len(tiles), tempImage.Bounds())
|
wg.Add(1)
|
||||||
if err := StitchGrid(tiles, tempImage, 512, bar); err != nil {
|
go func() {
|
||||||
log.Panic(err)
|
defer wg.Done()
|
||||||
}
|
|
||||||
bar.Finish()
|
|
||||||
|
|
||||||
outputImage = tempImage
|
ticker := time.NewTicker(1 * time.Second)
|
||||||
} else {
|
for {
|
||||||
tempImage := NewMedianBlendedImage(tiles, outputRect)
|
select {
|
||||||
_, max := tempImage.Progress()
|
case <-done:
|
||||||
bar.SetTotal(int64(max)).Start().SetRefreshRate(1 * time.Second)
|
value, _ := tempImage.Progress()
|
||||||
|
bar.SetCurrent(int64(value))
|
||||||
wg.Add(1)
|
bar.Finish()
|
||||||
go func() {
|
return
|
||||||
defer wg.Done()
|
case <-ticker.C:
|
||||||
|
value, _ := tempImage.Progress()
|
||||||
ticker := time.NewTicker(1 * time.Second)
|
bar.SetCurrent(int64(value))
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
value, _ := tempImage.Progress()
|
|
||||||
bar.SetCurrent(int64(value))
|
|
||||||
bar.Finish()
|
|
||||||
return
|
|
||||||
case <-ticker.C:
|
|
||||||
value, _ := tempImage.Progress()
|
|
||||||
bar.SetCurrent(int64(value))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
outputImage = tempImage
|
outputImage = tempImage
|
||||||
}
|
|
||||||
|
|
||||||
log.Printf("Creating output file \"%v\"", *flagOutputPath)
|
log.Printf("Creating output file \"%v\"", *flagOutputPath)
|
||||||
f, err := os.Create(*flagOutputPath)
|
f, err := os.Create(*flagOutputPath)
|
||||||
@ -321,10 +307,8 @@ func main() {
|
|||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !*flagPrerender {
|
done <- true
|
||||||
done <- true
|
wg.Wait()
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := f.Close(); err != nil {
|
if err := f.Close(); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
|
@ -8,15 +8,10 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"golang.org/x/image/font"
|
|
||||||
"golang.org/x/image/font/basicfont"
|
|
||||||
"golang.org/x/image/math/fixed"
|
|
||||||
|
|
||||||
"github.com/google/hilbert"
|
"github.com/google/hilbert"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,36 +98,6 @@ func hilbertifyRectangle(rect image.Rectangle, gridSize int) ([]image.Rectangle,
|
|||||||
return grid, nil
|
return grid, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawLabel(img *image.RGBA, x, y int, label string) {
|
|
||||||
col := color.RGBA{200, 100, 0, 255}
|
|
||||||
point := fixed.Point26_6{X: fixed.Int26_6(x * 64), Y: fixed.Int26_6(y * 64)}
|
|
||||||
|
|
||||||
d := &font.Drawer{
|
|
||||||
Dst: img,
|
|
||||||
Src: image.NewUniform(col),
|
|
||||||
Face: basicfont.Face7x13,
|
|
||||||
Dot: point,
|
|
||||||
}
|
|
||||||
d.DrawString(label)
|
|
||||||
}
|
|
||||||
|
|
||||||
func intAbs(x int) int {
|
|
||||||
if x < 0 {
|
|
||||||
return -x
|
|
||||||
}
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
func pointAbs(p image.Point) image.Point {
|
|
||||||
if p.X < 0 {
|
|
||||||
p.X = -p.X
|
|
||||||
}
|
|
||||||
if p.Y < 0 {
|
|
||||||
p.Y = -p.Y
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integer division that rounds to the next integer towards negative infinity.
|
// Integer division that rounds to the next integer towards negative infinity.
|
||||||
func divideFloor(a, b int) int {
|
func divideFloor(a, b int) int {
|
||||||
temp := a / b
|
temp := a / b
|
||||||
@ -154,10 +119,3 @@ func divideCeil(a, b int) int {
|
|||||||
|
|
||||||
return temp
|
return temp
|
||||||
}
|
}
|
||||||
|
|
||||||
func maxInt(x, y int) int {
|
|
||||||
if x > y {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
return y
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user