Skip to content

Commit

Permalink
Add concurrency.
Browse files Browse the repository at this point in the history
  • Loading branch information
tardisx committed Jun 20, 2019
1 parent 4cc498a commit e2ee7ae
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 26 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,12 @@ the top left tile.

slicerdicer --help

slicerdicer --filename foo.png --tile-size 256
slicerdicer --filename foo.png --tile-size 256 --concurrency 5

## Notes

It's going to eat some memory.

In my tests on an 32641 x 16471, 8-bit/color RGB PNG, memory usage peaks at
around 2.7GB.

61 changes: 36 additions & 25 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import "image/png"
import "github.com/disintegration/imaging"
import "runtime"
import "flag"


import "fmt"
import "os"

func main() {

filenamePtr := flag.String("filename", "screenshot.png", "filename to open")
tile_size := flag.Int ("tile-size", 512, "tile size, in pixels")
filenamePtr := flag.String("filename", "screenshot.png", "filename to open")
tileSizePtr := flag.Int ("tile-size", 512, "tile size, in pixels")
concurrencyPtr := flag.Int ("concurrency", 5, "how many tiles to generate concurrently (threads)")

flag.Parse()

Expand All @@ -26,20 +25,24 @@ func main() {

size := src.Bounds().Max

tile_size_x := *tile_size
tile_size_y := *tile_size

fmt.Println("starting tiling")
tile_size_x := *tileSizePtr
tile_size_y := *tileSizePtr

z := 0

concurrency := *concurrencyPtr
sem := make(chan bool, concurrency)

fmt.Println("starting tiling with concurrency of", concurrency)

// outer loop for zoom
for {
if (z == 0) {
// do nothing
} else {
// halve image size
src = imaging.Resize(src, size.X/2, 0, imaging.Linear)
src = imaging.Resize(src, size.X/2, 0, imaging.NearestNeighbor)
runtime.GC()
// recalculate size
size = src.Bounds().Max
// we are done if we are now smaller then the tile
Expand All @@ -51,29 +54,37 @@ func main() {
fmt.Print(fmt.Sprintf("zoom level: %d (%d x %d)\n", z, size.X, size.Y))

for y := 0 ; y <= (size.Y / tile_size_y) ; y++ {

for x := 0 ; x <= (size.X / tile_size_x) ; x++ {

output_filename := fmt.Sprintf("tile-%d-%d-%d.png", z, x, y)
cropped := imaging.Crop(src, image.Rect(tile_size_x*x, tile_size_y*y, tile_size_x*x+tile_size_x, tile_size_y*y+tile_size_y));

fmt.Print("writing to: ", output_filename, " ");
fmt.Print("\r")

writer, _ := os.Create(output_filename)
err = png.Encode(writer, cropped)
writer.Close()
runtime.GC()
if err != nil {
fmt.Println(err)
}
sem <- true
go tile(src, z, x, y, tile_size_x, tile_size_y, sem)
}

}

fmt.Print("\r \r")
z++
}

// drain at the end of each zoom level
// since we are about to modify the source image
for i := 0; i < cap(sem); i++ {
sem <- true
}

fmt.Println("done")
}

func tile (src image.Image, z, x, y int, tile_size_x, tile_size_y int, sem chan bool) {
defer func() { <-sem }()
output_filename := fmt.Sprintf("tile-%d-%d-%d.png", z, x, y)
cropped := imaging.Crop(src, image.Rect(tile_size_x*x, tile_size_y*y, tile_size_x*x+tile_size_x, tile_size_y*y+tile_size_y));

writer, _ := os.Create(output_filename)
err := png.Encode(writer, cropped)
if err != nil {
fmt.Println(err)
}
writer.Close()

runtime.GC()
return;
}

0 comments on commit e2ee7ae

Please sign in to comment.