/* * ****************************************************************************** * * Copyright 2015 See AUTHORS file. * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ***************************************************************************** */ package com.uwsoft.editor.utils; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.Transparency; import java.awt.image.BufferedImage; import java.awt.image.Raster; import java.util.ArrayList; /** * Created by sargis on 8/29/14. */ public class NinePatchUtils { public static Integer[] findPatches(BufferedImage image) { int width = image.getWidth(); int height = image.getHeight(); int[] row = new int[width]; int[] column = new int[height]; row = getPixels(image, 0, 0, width, 1, row); column = getPixels(image, 0, 0, 1, height, column); boolean[] result = new boolean[1]; //row = getPixels(image, 0, height - 1, width, 1, row); //column = getPixels(image, width - 1, 0, 1, height, column); Pair<java.util.List<Pair<Integer>>> top = getPatches(row, result); Pair<java.util.List<Pair<Integer>>> left = getPatches(column, result); Pair<Integer> topPadding = getPadding(top.first); Pair<Integer> leftPadding = getPadding(left.first); return new Integer[]{topPadding.first, topPadding.second, leftPadding.first, leftPadding.second}; } public static BufferedImage removePatches(BufferedImage image) { BufferedImage buffer = createTranslucentCompatibleImage( image.getWidth() - 2, image.getHeight() - 2); Graphics2D g2 = buffer.createGraphics(); g2.drawImage(image, -1, -1, null); g2.dispose(); return buffer; } public static BufferedImage convertTo9Patch(BufferedImage image, Integer[] patches, float ratio) { BufferedImage buffer = createTranslucentCompatibleImage(image.getWidth() + 2, image.getHeight() + 2); Graphics2D g2 = buffer.createGraphics(); g2.drawImage(image, 1, 1, null); g2.dispose(); draw9Patch(buffer, patches, ratio); return buffer; } private static GraphicsConfiguration getGraphicsConfiguration() { GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); return environment.getDefaultScreenDevice().getDefaultConfiguration(); } private static BufferedImage createTranslucentCompatibleImage(int width, int height) { return getGraphicsConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); } private static Pair<Integer> getPadding(java.util.List<Pair<Integer>> pairs) { if (pairs.size() == 0) { return new Pair<>(0, 0); } else if (pairs.size() == 1) { if (pairs.get(0).first == 1) { return new Pair<>(pairs.get(0).second - pairs.get(0).first, 0); } else { return new Pair<>(0, pairs.get(0).second - pairs.get(0).first); } } else { int index = pairs.size() - 1; return new Pair<>(pairs.get(0).second - pairs.get(0).first, pairs.get(index).second - pairs.get(index).first); } } private static int[] getPixels(BufferedImage img, int x, int y, int w, int h, int[] pixels) { if (w == 0 || h == 0) { return new int[0]; } if (pixels == null) { pixels = new int[w * h]; } else if (pixels.length < w * h) { throw new IllegalArgumentException("Pixels array must have a length >= w * h"); } int imageType = img.getType(); if (imageType == BufferedImage.TYPE_INT_ARGB || imageType == BufferedImage.TYPE_INT_RGB) { Raster raster = img.getRaster(); return (int[]) raster.getDataElements(x, y, w, h, pixels); } // Unmanages the image return img.getRGB(x, y, w, h, pixels, 0, w); } private static Pair<java.util.List<Pair<Integer>>> getPatches(int[] pixels, boolean[] startWithPatch) { int lastIndex = 1; int lastPixel = pixels[1]; boolean first = true; java.util.List<Pair<Integer>> fixed = new ArrayList<>(); java.util.List<Pair<Integer>> patches = new ArrayList<>(); for (int i = 1; i < pixels.length - 1; i++) { int pixel = pixels[i]; if (pixel != lastPixel) { if (lastPixel == 0xFF000000) { if (first) startWithPatch[0] = true; patches.add(new Pair<Integer>(lastIndex, i)); } else { fixed.add(new Pair<Integer>(lastIndex, i)); } first = false; lastIndex = i; lastPixel = pixel; } } if (lastPixel == 0xFF000000) { if (first) startWithPatch[0] = true; patches.add(new Pair<>(lastIndex, pixels.length - 1)); } else { fixed.add(new Pair<>(lastIndex, pixels.length - 1)); } if (patches.size() == 0) { patches.add(new Pair<>(1, pixels.length - 1)); startWithPatch[0] = true; fixed.clear(); } return new Pair<>(fixed, patches); } private static void draw9Patch(BufferedImage image, Integer[] patches, float ratio) { int width = image.getWidth(); int height = image.getHeight(); int wStart = (int) (patches[0] * ratio) + 1; // this number should be rounded UP int wEnd = (int) (width - patches[1] * ratio) - 1; int hStart = (int) (patches[2] * ratio) + 1; // this number should be rounded UP int hEnd = (int) (height - patches[3] * ratio) - 1; for (int i = wStart; i < wEnd; i++) { image.setRGB(i, 0, 0xFF000000); image.setRGB(i, height - 1, 0xFF000000); } for (int i = hStart; i < hEnd; i++) { image.setRGB(0, i, 0xFF000000); image.setRGB(width - 1, i, 0xFF000000); } } static class Pair<E> { E first; E second; Pair(E first, E second) { this.first = first; this.second = second; } @Override public String toString() { return "Pair[" + first + ", " + second + "]"; } } }