Last active
December 11, 2015 23:39
Resizes android xhdpi resources for ldpi, mdpi, and hdpi.
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
/* | |
Usage of droidscale: | |
-interp="Lanzcos3": interpolation to use. NearestNeighbor, Bilinear, Bicubic, MitchellNetravali, Lanzcos2, Lanzcos3. | |
-out="./out": directory to place resized images. | |
-path="": path of xhdpi drawables to process, can point to a single file. | |
Resizes xhdpi resources for ldpi, mdpi, and hdpi. Contents of flag path will | |
be walked and new files written to flag out will be flattened. This means | |
you can organize the contents of flag path with subdirectories to target | |
different interpolations for use on a particular set of images. For example: | |
droidscale -path="xhdpi/L2" -interp="Lanzcos2" | |
droidscale -path="xhdpi/L3" -interp="Lanzcos3" | |
Inspecting the contents of ./out/drawable-mdpi/ and friends will show a flat | |
list of the resized files. | |
*/ | |
package main | |
import ( | |
"flag" | |
"fmt" | |
"github.com/nfnt/resize" | |
"image/png" | |
"os" | |
"path/filepath" | |
"runtime" | |
) | |
var flagPath = flag.String("path", "", "path of xhdpi drawables to process, can point to a single file.") | |
var flagOut = flag.String("out", "./out", "directory to place resized images.") | |
var flagInterp = flag.String("interp", "Lanzcos3", "interpolation to use. NearestNeighbor, Bilinear, Bicubic, MitchellNetravali, Lanzcos2, Lanzcos3.") | |
var interp resize.InterpolationFunction | |
// dpi represents a density by its xhdpi scale factor. | |
type dpi float64 | |
// scale takes an image dimension and makes suitable for pkg resize. | |
func (d dpi) scale(n int) uint { | |
return uint(float64(n) * float64(d)) | |
} | |
const ( | |
ldpi dpi = 0.375 | |
mdpi = 0.5 | |
hdpi = 0.75 | |
xhdpi = 1 | |
) | |
var dpiString = map[dpi]string{ | |
ldpi: "drawable-ldpi", | |
mdpi: "drawable-mdpi", | |
hdpi: "drawable-hdpi", | |
xhdpi: "drawable-xhdpi", | |
} | |
// visit is a filepath.WalkFn that handles finding and resizing png resources. | |
func visit(path string, f os.FileInfo, err error) (e error) { | |
if filepath.Ext(path) != ".png" { | |
return | |
} | |
file, err := os.Open(path) | |
if err != nil { | |
fmt.Printf("Failed to open file %s\n", path) | |
return | |
} | |
defer file.Close() | |
img, err := png.Decode(file) | |
if err != nil { | |
fmt.Printf("Failed to decode png %s\n", path) | |
return | |
} | |
fn := func(factor dpi) { | |
x := factor.scale(img.Bounds().Size().X) | |
m := resize.Resize(x, 0, img, interp) | |
p := filepath.Join(*flagOut, dpiString[factor], f.Name()) | |
d := filepath.Dir(p) | |
os.MkdirAll(d, 0766) | |
out, err := os.Create(p) | |
if err != nil { | |
fmt.Printf("Failed to create new file %s\n", p) | |
return | |
} | |
defer out.Close() | |
if err := png.Encode(out, m); err != nil { | |
fmt.Printf("Failed to encode resized %s\n", f.Name()) | |
return | |
} | |
} | |
fmt.Printf("Resizing %s\n", f.Name()) | |
fn(ldpi) | |
fn(mdpi) | |
fn(hdpi) | |
return | |
} | |
func usage() { | |
fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) | |
flag.PrintDefaults() | |
fmt.Fprintln(os.Stderr, "\n"+`Resizes xhdpi resources for ldpi, mdpi, and hdpi. Contents of flag path will | |
be walked and new files written to flag out will be flattened. This means | |
you can organize the contents of flag path with subdirectories to target | |
different interpolations for use on a particular set of images. For example: | |
droidscale -path="xhdpi/L2" -interp="Lanzcos2" | |
droidscale -path="xhdpi/L3" -interp="Lanzcos3" | |
Inspecting the contents of ./out/drawable-mdpi/ and friends will show a flat | |
list of the resized files.`) | |
} | |
func init() { | |
runtime.GOMAXPROCS(runtime.NumCPU()) | |
flag.Usage = usage | |
flag.Parse() | |
} | |
func main() { | |
if *flagPath == "" { | |
flag.Usage() | |
return | |
} | |
switch *flagInterp { | |
case "NearestNeighbor": | |
interp = resize.NearestNeighbor | |
case "Bilinear": | |
interp = resize.Bilinear | |
case "Bicubic": | |
interp = resize.Bicubic | |
case "MitchellNetravali": | |
interp = resize.MitchellNetravali | |
case "Lanzcos2": | |
interp = resize.Lanczos2 | |
case "Lanzcos3": | |
interp = resize.Lanczos3 | |
default: | |
flag.Usage() | |
fmt.Printf("\nReceived invalid interp: %s\nSee usage above.\n", *flagInterp) | |
return | |
} | |
filepath.Walk(*flagPath, visit) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment