Skip to content

Instantly share code, notes, and snippets.

@9re
Forked from Layzie/to9patch.jsx
Created November 16, 2011 11:53
Show Gist options
  • Save 9re/1369912 to your computer and use it in GitHub Desktop.
Save 9re/1369912 to your computer and use it in GitHub Desktop.
make 9patch file using PhotoShop
// rulerはpx指定にしておく
// 指定したフォルダ内にあるxhdpiのサイズのpng,jpgを
// mdpi, hdpi, xhdpiそれぞれにサイズを適宜縮小して入れる。
// .9.pngという名前の付いたpngファイルは一度9patchの線の枠を取ってから
// 再び9patchの枠を付け直す。
// vim:set ft=javascript:
#target photoshop
var MIDDLE = "mdpi", HIGH = "hdpi", XTRA_HIGH = "xhdpi";
var extensions = ["png", "jpg", "jpeg"];
var SIZE = {};
SIZE[MIDDLE] = 0.5;
SIZE[HIGH] = 0.75;
SIZE[XTRA_HIGH] = 1.0;
var doc;
openDirectory();
function openDirectory() {
var dir = new Folder(Folder.selectDialog("xhdpi用素材のフォルダを指定してください"));
if (dir.exists) {
var files = getFiles(dir);
var len = files.length;
for (var i = 0; i < len; ++i) {
makeResources(files[i]);
}
}
}
function getFiles(dir) {
var result = [];
var len = extensions.length;
for (var i = 0; i < len; ++i) {
result = result.concat(dir.getFiles("*." + extensions[i]));
}
return result;
}
function makeResources(file) {
if (!file) {
return;
}
for (var size in SIZE) {
app.open(file);
doc = app.activeDocument;
makeResource(size);
}
}
function makeResource(scale) {
var fileName = doc.name,
filePath = doc.path,
dirPath = filePath.fsName,
patchDir = '/drawable-' + scale,
fileObj, is9Patch;
makeDirIfNotExists(dirPath, patchDir);
is9Patch = fileName.indexOf(".9.png") > -1;
fileObj = new File(filePath + patchDir +'/' + fileName);
doc.saveAs(fileObj, getSaveOptions(fileName), true, Extension.LOWERCASE);
//元ファイルを保存せずに閉じる
doc.close(SaveOptions.DONOTSAVECHANGES);
app.open(fileObj);
doc = app.activeDocument;
var s = SIZE[scale];
if (is9Patch) {
make9PatchResource(scale, s);
} else {
makeNormalResource(s);
}
doc.close(SaveOptions.SAVECHANGES);
}
function getSaveOptions(fileName) {
var isPng = fileName.match(/\.png/i) != null;
var options;
if (isPng) {
options = new PNGSaveOptions();
options.interlaced = false;
} else {
options = new JPEGSaveOptions();
options.quality = 10;
}
return options;
}
function makeNormalResource(s) {
var w = doc.width.value;
var h = doc.height.value;
w = Math.round(w * s);
h = Math.round(h * s);
doc.resizeImage(w, h);
}
function make9PatchResource(scale, s) {
var ninePatchRegions = find9PatchRegions(s);
if (scale !== XTRA_HIGH) {
var w = doc.width.value;
var h = doc.height.value;
clear9PatchRegion(ninePatchRegions);
doc.resizeCanvas(w - 2, h - 2);
doc.trim();
w = Math.round(w * s);
h = Math.round(h * s);
doc.resizeImage(w, h, 1, ResampleMethod.NEARESTNEIGHBOR);
doc.resizeCanvas(w + 2, h + 2);
draw9PatchRegion(ninePatchRegions, s);
}
}
function makeDirIfNotExists(base, path) {
var paths = path.split('/');
var len = paths.length;
var dir;
for (var i = 1; i <= len; ++i) {
dir = new Folder(base + '/' + paths.slice(0, i).join('/'));
if (!dir.exists) {
dir.create();
}
}
}
function clear9PatchRegion(regions) {
var arrRegions = calcClearRegions(regions);
var len = arrRegions.length;
for (var i = 0; i < len; ++i) {
selectRegion.apply(null, arrRegions[i]);
doc.selection.clear();
}
}
function draw9PatchRegion(regions, s) {
var arrRegions = calcDrawRegions(regions, s);
var len = arrRegions.length, color;
for (var i = 0; i < len; ++i) {
selectRegion.apply(null, arrRegions[i]);
color = new SolidColor();
color.rgb.red = 0;
color.rgb.green = 0;
color.rgb.blue = 0;
doc.selection.fill(color);
}
}
function calcDrawRegions(regions, s) {
var arr = [], pair;
if (regions.left) {
pair = scalePair(regions.left, s);
pair.unshift(0, 1);
arr.push(pair);
}
if (regions.right) {
var w = doc.width.value;
pair = scalePair(regions.right, s);
pair.unshift(w - 1, w);
arr.push(pair);
}
if (regions.top) {
pair = scalePair(regions.top, s);
pair.push(0, 1);
arr.push(pair);
}
if (regions.bottom) {
var h = doc.height.value;
pair = scalePair(regions.bottom, s);
pair.push(h - 1, h);
arr.push(pair);
}
return arr;
}
function calcClearRegions(regions) {
var arr = [], pair;
if ((pair = regions.left)) {
pair = pair.slice();
pair.unshift(0, 1);
arr.push(pair);
}
if ((pair = regions.right)) {
var w = doc.width.value;
pair = pair.slice();
pair.unshift(w - 1, w);
arr.push(pair);
}
if ((pair = regions.top)) {
pair = pair.slice();
pair.push(0, 1);
arr.push(pair);
}
if ((pair = regions.bottom)) {
var h = doc.height.value;
pair = pair.slice();
pair.push(h - 1, h);
arr.push(pair);
}
return arr;
}
function selectRegion(x0, x1, y0, y1) {
doc.selection.select([[x0, y0], [x0, y1], [x1, y1], [x1, y0], [x0, y0]]);
}
function scalePair(pair, scale) {
var x = Math.round((pair[0] - 1) * scale) + 1,
y = Math.round((pair[1] - 1) * scale) + 1;
if (x == y) {
++y;
}
return [x, y];
}
function find9PatchRegions() {
var w = doc.width.value,
h = doc.height.value;
var regions = {
left : findRegion(0, h, 0, verticalCounter),
right : findRegion(0, h, w - 1, verticalCounter),
top : findRegion(0, w, 0, horizontalCounter),
bottom : findRegion(0, w, h -1, horizontalCounter)
};
for (var area in regions) {
if (!regions[area]) {
delete regions[area];
}
}
return regions;
}
function findRegion(a, b, x, counter) {
var i, j, count, n;
count = counter(a, b, x);
if (count == 0) {
return null;
}
for (;;) {
i = a; j = (a + b) >> 1;
n = counter(i, j, x);
if (i == j) {
return null;
}
if (n == count) {
if (j - i == n) { // exactly match!!
return [i,j];
} else {
b = j;
}
} else if (n == 0){
a = j;
} else { // 0 < n < count
return [j - n, j + count - n];
}
}
}
function verticalCounter(a, b, x) {
doc.selection.select([[x,a], [x + 1,a], [x + 1,b], [x,b], [x,a]]);
return doc.histogram[0];
}
function horizontalCounter(a, b, y) {
doc.selection.select([[a,y], [b,y], [b,y + 1], [a, y + 1], [a, y]]);
return doc.histogram[0];
}
function findTopBottom(x) {
var h = doc.height.value;
return findRegion(0, h, x, verticalCounter);
}
function findLeftRight(y) {
var w = doc.width.value;
return findRegion(0, w, y, horizontalCounter);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment