├── README.md
├── assets
├── actionbar_tag.svg
├── app_icon.svg
└── tag.9.svg
├── gen9patch.py
├── process_assets
└── res
├── drawable-hdpi
├── actionbar_tag.png
├── app_icon.png
└── tag.9.png
├── drawable-ldpi
├── actionbar_tag.png
├── app_icon.png
└── tag.9.png
├── drawable-mdpi
├── actionbar_tag.png
├── app_icon.png
└── tag.9.png
└── drawable-xhdpi
├── actionbar_tag.png
├── app_icon.png
└── tag.9.png
/README.md:
--------------------------------------------------------------------------------
1 | SVG -> drawable-xhdpi, drawable-hdpi, drawable-mdpi, drawable-ldpi
2 |
3 | Android SVG Asset Generator
4 | ----
5 | Future proof your assets and save time!
6 |
7 | Create / find once and don't worry about DPI buckets.
8 |
9 | This tool allows you to use SVG files for your Android apps image resources.
10 |
11 | SVG images are scaled and put into appropriate folders for android and the 9 patch is applied.
12 |
13 | Iconograpy for apps can be quickly generated from content from sites like those below:
14 | http://www.fileformat.info/info/unicode/char/search.htm
15 |
16 | Generating Images
17 | ----
18 | Example:
19 |
20 | ./process_assets ./assets/ ./
21 |
22 | The asset generator code can be kept in a sub folder and called from there. This makes it really easy to include in your project as a git submodule.
23 |
24 | ./asset_generator/process_assets ./source_images/ ./AndroidProjectFolder/
25 |
26 | Source Image Info
27 | ----
28 | The document size on your SVG files should reflect the image size at 72dpi.
29 |
30 | Ex: an app icon should be 27x27 px at 72dpi so that when scaled up to 240dpi (HDPI) it is 72x72 px.
31 |
32 | To add a 9patch to generated images, add a hidden layer called 9patch see tag.svg for an example
33 |
34 | Requirements
35 | ----
36 | * Linux, OS X, (Cygwin? requires inkscape to be on your path.)
37 | * Inkscape
38 | * Python
39 | * PIL
--------------------------------------------------------------------------------
/assets/actionbar_tag.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
72 |
--------------------------------------------------------------------------------
/assets/app_icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
118 |
--------------------------------------------------------------------------------
/assets/tag.9.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
106 |
--------------------------------------------------------------------------------
/gen9patch.py:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | import os
4 | import sys
5 | from xml.etree.ElementTree import ElementTree
6 | import subprocess
7 | from PIL import Image
8 | import platform
9 |
10 | document = ElementTree()
11 |
12 | def toBlackOrTransparent(color):
13 | if color[3] == 0:
14 | return (0,0,0,0)
15 | else:
16 | return (0,0,0,255)
17 |
18 | def create9PatchSvg(file):
19 | document.parse(file)
20 | root = document.getroot()
21 | for elem in root.iter("{http://www.w3.org/2000/svg}g"):
22 | layerName = elem.get("{http://www.inkscape.org/namespaces/inkscape}label")
23 | layerId = elem.get("id")
24 | if layerName == "9patch" or layerId == "_x39_patch":
25 | elem.set('style', '')
26 | elem.set('display', '')
27 | else:
28 | elem.set('style', 'display:none')
29 | elem.set('display', 'none')
30 |
31 | document.write('./temp/9patch.svg')
32 |
33 | def create9PatchForDpi(file, dpi, name, resourceLocation):
34 |
35 | if platform.system() == "Darwin":
36 | inkscapePath = "/Applications/Inkscape.app/Contents/Resources/bin/inkscape"
37 | else:
38 | inkscapePath = "inkscape"
39 |
40 | subprocess.check_output([inkscapePath,"-d", str(dpi), "-e", "./temp/out.png", "./temp/9patch.svg"])
41 |
42 | im = Image.open("./temp/out.png")
43 | pix = im.load()
44 | newSize = (im.size[0] +2 , im.size[1] +2)
45 | nim = Image.new("RGBA", newSize, (255, 255, 255, 0))
46 | npix = nim.load()
47 |
48 | for x in range(0, im.size[0]):
49 | data = toBlackOrTransparent(pix[x,0])
50 | npix[x+1, 0] = data
51 | data = toBlackOrTransparent(pix[x, im.size[1]-1])
52 | npix[x+1, newSize[1]-1] = data
53 |
54 | for y in range(0, im.size[1]):
55 | data = toBlackOrTransparent(pix[0, y])
56 | npix[0, y+1] = data
57 | data = toBlackOrTransparent(pix[im.size[0]-1, y])
58 | npix[newSize[0]-1, y+1] = data
59 |
60 | subprocess.check_output([inkscapePath,"-d", str(dpi), "-e", "./temp/out.png", file])
61 |
62 | im = Image.open("./temp/out.png")
63 | nim.paste(im, (1,1))
64 |
65 | filename = os.path.split(file)[1]
66 | filename = filename.replace(".svg", ".png")
67 |
68 | nim.save(resourceLocation + "/res/drawable-" + name + "/" + filename)
69 |
70 | dir = "./temp"
71 | if not os.path.exists(dir):
72 | os.makedirs(dir)
73 |
74 | create9PatchSvg(sys.argv[1]);
75 | for (dpi, name) in [(320, "xhdpi"), (240, "hdpi"), (160, "mdpi"), (120, "ldpi")]:
76 | create9PatchForDpi(sys.argv[1], dpi, name, sys.argv[2])
77 |
78 |
--------------------------------------------------------------------------------
/process_assets:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | #Requires Inkscape to be installed.
4 |
5 | #This script scales and creates images at the correct dpi level for Android.
6 | #When creating svg files set the image size to the size that you want your mdpi images to be.
7 |
8 |
9 | function processImage {
10 | file=$(basename $1)
11 |
12 | case $OSTYPE in
13 | darwin*)
14 | inkscape="/Applications/Inkscape.app/Contents/Resources/bin/inkscape"
15 | ;;
16 | *)
17 | inkscape="inkscape"
18 | ;;
19 | esac
20 |
21 | mkdir -p $2/res/drawable-xxxhdpi
22 | mkdir -p $2/res/drawable-xxhdpi
23 | mkdir -p $2/res/drawable-xhdpi
24 | mkdir -p $2/res/drawable-hdpi
25 | mkdir -p $2/res/drawable-mdpi
26 | mkdir -p $2/res/drawable-ldpi
27 |
28 | $inkscape -d 640 -e $2/res/drawable-xxxhdpi/${file/.svg}.png $1 >& /dev/null
29 | $inkscape -d 480 -e $2/res/drawable-xxhdpi/${file/.svg}.png $1 >& /dev/null
30 | $inkscape -d 320 -e $2/res/drawable-xhdpi/${file/.svg}.png $1 >& /dev/null
31 | $inkscape -d 240 -e $2/res/drawable-hdpi/${file/.svg}.png $1 >& /dev/null
32 | $inkscape -d 160 -e $2/res/drawable-mdpi/${file/.svg}.png $1 >& /dev/null
33 | $inkscape -d 120 -e $2/res/drawable-ldpi/${file/.svg}.png $1 >& /dev/null
34 | }
35 |
36 | function displayHelp {
37 |
38 | echo "-h Help"
39 | echo "-f Force processing of all files"
40 | echo "process_assets ./source_image_folder/ ./output_folder"
41 | exit
42 | }
43 |
44 | while getopts ":fh" opt; do
45 | case $opt in
46 | f)
47 | rm ./lastprocess
48 | ;;
49 | h)
50 | displayHelp
51 | ;;
52 | \?)
53 | echo "Invalid option: -$OPTARG" >&2
54 | displayHelp
55 | exit
56 | ;;
57 | esac
58 | done
59 |
60 | if [ $# -ne 2 ]
61 | then
62 | echo "Incorrect number of args." >&2
63 | displayHelp
64 | exit
65 | fi
66 |
67 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
68 |
69 | if [ ! -e ./lastprocess ]
70 | then
71 | touch -t 197001010100.00 ./lastprocess
72 | fi
73 |
74 | for f in $(find $1 -name *.svg -type f -newer ./lastprocess) ;
75 | do
76 | echo "Processing $f"
77 | if [[ "$f" == *.9.svg* ]]; then
78 | $DIR/gen9patch.py $f $2
79 | else
80 | processImage $f $2
81 | fi
82 | done
83 |
84 | touch -t $(date +%Y%m%d%H%M.%S) ./lastprocess
85 |
86 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/actionbar_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-hdpi/actionbar_tag.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-hdpi/app_icon.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/tag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-hdpi/tag.9.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/actionbar_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-ldpi/actionbar_tag.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-ldpi/app_icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/tag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-ldpi/tag.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/actionbar_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-mdpi/actionbar_tag.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-mdpi/app_icon.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/tag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-mdpi/tag.9.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/actionbar_tag.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-xhdpi/actionbar_tag.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/app_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-xhdpi/app_icon.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/tag.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DDRBoxman/Android-SVG-Asset-Generator/30ffa7f62f7af1dc2d12ddcb3f082c26e2501d0a/res/drawable-xhdpi/tag.9.png
--------------------------------------------------------------------------------