I use Google Maps API to render the maps on my Zelda Parallel Worlds walkthrough, and as a result I needed to generate the necessary tiles for the Maps API to use. My source image was a 4,096x4,096 image, and I needed to generate 256x256 tiles at various zoom levels, starting at fully zoomed out, where the entire map was contained in a single tile, up to however large I could reasonable render (which ended up being a whopping 16,384x16,384). GIMP's script-fu functionality was perfect for the task, but I couldn't find a script that quite did what I wanted, including scaling the map to the various zoom levels, so I made my own. I used the tiles-to-files plugin as my starting point and went from there. The end result gives the following options
Tile size is adjustable (though I've only tested powers of 2, such as 64, 128, and 256)
Max zoom level determines how many zoom levels should be generated. The lowest zoom level is 0, which is a single tile in size.
Output file type is selectable between PNG and JPEG
Interpolation mode can be chosen separately for shrinking and growing. In my case, I didn't want any interpolation when growing, since I was growing a pixel-perfect image by a factor of 2 each zoom level, so I wanted to retain the pixel-perfect aspect and just create "big pixels".
Here's the script:
Interpolation mode can be chosen separately for shrinking and growing. In my case, I didn't want any interpolation when growing, since I was growing a pixel-perfect image by a factor of 2 each zoom level, so I wanted to retain the pixel-perfect aspect and just create "big pixels".
Here's the script:
; Google Maps Tiles, V1.0
;
; Based on the tiles-to-files script by theilr
; http://registry.gimp.org/node/20868
;
; http://www.qwertymodo.com
;
(define (script-fu-google-maps-tiles inImage inDrawable inTileSize inMaxZoom
inFileType inShrinkMethod inGrowMethod outDir)
(gimp-image-undo-group-start inImage)
(let* (
(fullWidth (car (gimp-image-width inImage)))
(fullHeight (car (gimp-image-height inImage)))
(tileWidth inTileSize)
(tileHeight inTileSize)
(zoomWidth tileWidth)
(zoomHeight tileHeight)
(newImage (car (gimp-image-new tileWidth tileHeight RGB)))
(tmpImage)
(tmpLayer)
(selLayer)
(outfname)
(hcnt 0)
(vcnt 0)
(zcnt 0)
)
(set! zcnt 0)
(while (<= zcnt inMaxZoom)
(set! zoomWidth (* tileWidth (expt 2 zcnt)))
(set! zoomHeight (* tileHeight (expt 2 zcnt)))
(gimp-rect-select inImage
0
0
fullWidth
fullHeight
CHANNEL-OP-ADD FALSE 0)
(gimp-edit-copy-visible inImage)
(gimp-selection-none inImage)
(set! tmpImage
(car (gimp-image-new zoomWidth zoomHeight RGB)))
(set! tmpLayer
(car (gimp-layer-new tmpImage fullWidth fullHeight
RGB-IMAGE "Background" 100
NORMAL-MODE)))
(gimp-image-add-layer tmpImage tmpLayer -1)
(set! selLayer
(car (gimp-edit-paste tmpLayer FALSE)))
(gimp-floating-sel-anchor selLayer)
(if (< zoomWidth fullWidth)
(begin
(gimp-context-set-interpolation inShrinkMethod)
(gimp-layer-scale tmpLayer zoomWidth zoomHeight FALSE)
(gimp-image-resize-to-layers tmpImage)
)
)
(if (> zoomWidth fullWidth)
(begin
(gimp-context-set-interpolation inGrowMethod)
(gimp-layer-scale tmpLayer zoomWidth zoomHeight FALSE)
(gimp-image-resize-to-layers tmpImage)
)
)
(set! hcnt 0)
(while (< (* hcnt tileWidth) zoomWidth)
(set! vcnt 0)
(while (< (* vcnt tileHeight) zoomHeight)
(gimp-rect-select tmpImage
(* tileWidth hcnt)
(* tileHeight vcnt)
tileWidth
tileHeight
CHANNEL-OP-ADD FALSE 0)
(gimp-edit-copy-visible tmpImage)
(gimp-selection-none tmpImage)
(set! tmpLayer
(car (gimp-layer-new newImage tileWidth tileHeight
RGB-IMAGE "Background" 100
NORMAL-MODE)))
(gimp-image-add-layer newImage tmpLayer -1)
(set! selLayer
(car (gimp-edit-paste tmpLayer FALSE)))
(gimp-floating-sel-anchor selLayer)
(if (= inFileType 0)
(begin
(set! outfname (string-append outDir
"/"
(number->string zcnt)
"-"
(number->string hcnt)
"-"
(number->string vcnt)
".png"))
(file-png-save RUN-NONINTERACTIVE
newImage
tmpLayer
outfname
outfname
0 9 1 0 0 1 1 )
)
)
(if (= inFileType 1)
(begin
(set! outfname (string-append outDir
"/"
(number->string zcnt)
"-"
(number->string hcnt)
"-"
(number->string vcnt)
".jpg"))
(file-jpeg-save RUN-NONINTERACTIVE
newImage
tmpLayer
outfname
outfname
0.95 ; JPEG compression level
0 ; Smoothing
1 ; Optimize
1 ; Progressive
"" ; Comment
0 ; Subsampling (0-4)
1 ; Baseline
0 ; Restart
0 ; DCT
)
)
)
(set! vcnt (+ vcnt 1))
)
(set! hcnt (+ hcnt 1))
)
(gimp-image-delete tmpImage)
(set! zcnt (+ zcnt 1))
)
(gimp-image-delete newImage)
(gimp-image-undo-group-end inImage)
(gimp-displays-flush)
)
)
(script-fu-register
"script-fu-google-maps-tiles" ; function name
"<Image>/Filters/Tiles/_Google Maps" ; menu label
"Split an image into tiles suitable\ ; description
for use with Google Maps API"
"qwertymodo" ; author
"(c) 2015, qwertymodo" ; copyright notice
"25 May 2015" ; date created
"RGB*" ; image type
SF-IMAGE "Image" 0
SF-DRAWABLE "Drawable" 0
SF-ADJUSTMENT "Tile Size (px)" '(128 8 1024 1 8 0 SF-SPINNER)
SF-ADJUSTMENT "Max Zoom Level" '(4 0 10 1 2 0 SF-SPINNER)
SF-OPTION "Output File Type" '("png" "jpg")
SF-ENUM "Interpolation (Shrink)" '("InterpolationType" "cubic")
SF-ENUM "Interpolation (Grow)" '("InterpolationType" "cubic")
SF-DIRNAME "Output Folder" "tiles"
)