package cn.sharesdk.onekeyshare.res;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.NinePatch;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
/** 一个简易的9 patch图片解码工具 */
public class NinePatchTool {
private final static int NO_COLOR = 0x00000001;
// private final static int TRANSPARENT_COLOR = 0x00000000;
private NinePatchTool() {
}
public static Drawable decodeDrawableFromAsset(Context context,
String assetPath) throws Exception {
Bitmap bm = decodeFromAsset(context, assetPath);
if (null == bm.getNinePatchChunk()) {
BitmapDrawable bitmapDrawable = new BitmapDrawable(bm);
return bitmapDrawable;
} else {
Rect padding = new Rect();
readPaddingFromChunk(bm.getNinePatchChunk(), padding);
NinePatchDrawable d = new NinePatchDrawable(context.getResources(),
bm, bm.getNinePatchChunk(), padding, null);
return d;
}
}
public static Bitmap decodeFromStream(InputStream in) throws Exception {
Bitmap srcBm = BitmapFactory.decodeStream(in);
byte[] chunk = readChunk(srcBm);
boolean isNinePatchChunk = NinePatch.isNinePatchChunk(chunk);
if (isNinePatchChunk) {
Bitmap tgtBm = Bitmap.createBitmap(srcBm, 1, 1,
srcBm.getWidth() - 2, srcBm.getHeight() - 2);
srcBm.recycle();
Field f = tgtBm.getClass().getDeclaredField("mNinePatchChunk");
f.setAccessible(true);
f.set(tgtBm, chunk);
return tgtBm;
} else {
return srcBm;
}
}
public static Bitmap decodeFromFile(String path) throws Exception {
InputStream in = new FileInputStream(path);
Bitmap bm = decodeFromStream(in);
in.close();
return bm;
}
public static Bitmap decodeFromAsset(Context context,
String ninePatchPngPath) throws Exception {
InputStream is = context.getAssets().open(ninePatchPngPath);
Bitmap bm = decodeFromStream(is);
is.close();
return bm;
}
public static void readPaddingFromChunk(byte[] chunk, Rect paddingRect) {
paddingRect.left = getInt(chunk, 12);
paddingRect.right = getInt(chunk, 16);
paddingRect.top = getInt(chunk, 20);
paddingRect.bottom = getInt(chunk, 24);
}
public static byte[] readChunk(Bitmap yuantuBmp) throws IOException {
final int BM_W = yuantuBmp.getWidth();
final int BM_H = yuantuBmp.getHeight();
int xPointCount = 0;
int yPointCount = 0;
int xBlockCount = 0;
int yBlockCount = 0;
ByteArrayOutputStream ooo = new ByteArrayOutputStream();
for (int i = 0; i < 32; i++) {
ooo.write(0);
}
{ // x
int[] pixelsTop = new int[BM_W - 2];
yuantuBmp.getPixels(pixelsTop, 0, BM_W, 1, 0, BM_W - 2, 1);
boolean topFirstPixelIsBlack = pixelsTop[0] == Color.BLACK;
boolean topLastPixelIsBlack = pixelsTop[pixelsTop.length - 1] == Color.BLACK;
int tmpLastColor = Color.TRANSPARENT;
for (int i = 0, len = pixelsTop.length; i < len; i++) {
if (tmpLastColor != pixelsTop[i]) {
xPointCount++;
writeInt(ooo, i);
tmpLastColor = pixelsTop[i];
}
}
if (topLastPixelIsBlack) {
xPointCount++;
writeInt(ooo, pixelsTop.length);
}
xBlockCount = xPointCount + 1;
if (topFirstPixelIsBlack) {
xBlockCount--;
}
if (topLastPixelIsBlack) {
xBlockCount--;
}
}
{ // y
int[] pixelsLeft = new int[BM_H - 2];
yuantuBmp.getPixels(pixelsLeft, 0, 1, 0, 1, 1, BM_H - 2);
boolean firstPixelIsBlack = pixelsLeft[0] == Color.BLACK;
boolean lastPixelIsBlack = pixelsLeft[pixelsLeft.length - 1] == Color.BLACK;
int tmpLastColor = Color.TRANSPARENT;
for (int i = 0, len = pixelsLeft.length; i < len; i++) {
if (tmpLastColor != pixelsLeft[i]) {
yPointCount++;
writeInt(ooo, i);
tmpLastColor = pixelsLeft[i];
}
}
if (lastPixelIsBlack) {
yPointCount++;
writeInt(ooo, pixelsLeft.length);
}
yBlockCount = yPointCount + 1;
if (firstPixelIsBlack) {
yBlockCount--;
}
if (lastPixelIsBlack) {
yBlockCount--;
}
}
{// color
for (int i = 0; i < xBlockCount * yBlockCount; i++) {
writeInt(ooo, NO_COLOR);
}
}
byte[] data = ooo.toByteArray();
data[0] = 1;
data[1] = (byte) xPointCount;
data[2] = (byte) yPointCount;
data[3] = (byte) (xBlockCount * yBlockCount);
dealPaddingInfo(yuantuBmp, data);
return data;
}
private static void dealPaddingInfo(Bitmap bm, byte[] data) {
{ // padding left & padding right
int[] bottomPixels = new int[bm.getWidth() - 2];
bm.getPixels(bottomPixels, 0, bottomPixels.length, 1,
bm.getHeight() - 1, bottomPixels.length, 1);
for (int i = 0; i < bottomPixels.length; i++) {
if (Color.BLACK == bottomPixels[i]) { // padding left
writeInt(data, 12, i);
break;
}
}
for (int i = bottomPixels.length - 1; i >= 0; i--) {
if (Color.BLACK == bottomPixels[i]) { // padding right
writeInt(data, 16, bottomPixels.length - i - 2);
break;
}
}
}
{ // padding top & padding bottom
int[] rightPixels = new int[bm.getHeight() - 2];
bm.getPixels(rightPixels, 0, 1, bm.getWidth() - 1, 0, 1,
rightPixels.length);
for (int i = 0; i < rightPixels.length; i++) {
if (Color.BLACK == rightPixels[i]) { // padding top
writeInt(data, 20, i);
break;
}
}
for (int i = rightPixels.length - 1; i >= 0; i--) {
if (Color.BLACK == rightPixels[i]) { // padding bottom
writeInt(data, 24, rightPixels.length - i - 2);
break;
}
}
}
}
private static void writeInt(OutputStream out, int v) throws IOException {
out.write((v >> 0) & 0xFF);
out.write((v >> 8) & 0xFF);
out.write((v >> 16) & 0xFF);
out.write((v >> 24) & 0xFF);
}
private static void writeInt(byte[] b, int offset, int v) {
b[offset + 0] = (byte) (v >> 0);
b[offset + 1] = (byte) (v >> 8);
b[offset + 2] = (byte) (v >> 16);
b[offset + 3] = (byte) (v >> 24);
}
private static int getInt(byte[] bs, int from) {
int b1 = bs[from + 0];
int b2 = bs[from + 1];
int b3 = bs[from + 2];
int b4 = bs[from + 3];
int i = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
return i;
}
/** print chunk info from bitmap */
public static void printChunkInfo(Bitmap bm) {
byte[] chunk = bm.getNinePatchChunk();
if (null == chunk) {
System.out.println("can't find chunk info from this bitmap(" + bm
+ ")");
return;
}
int xLen = chunk[1];
int yLen = chunk[2];
int cLen = chunk[3];
StringBuilder sb = new StringBuilder();
int peddingLeft = getInt(chunk, 12);
int paddingRight = getInt(chunk, 16);
int paddingTop = getInt(chunk, 20);
int paddingBottom = getInt(chunk, 24);
sb.append("peddingLeft=" + peddingLeft);
sb.append("\r\n");
sb.append("paddingRight=" + paddingRight);
sb.append("\r\n");
sb.append("paddingTop=" + paddingTop);
sb.append("\r\n");
sb.append("paddingBottom=" + paddingBottom);
sb.append("\r\n");
sb.append("x info=");
for (int i = 0; i < xLen; i++) {
int vv = getInt(chunk, 32 + i * 4);
sb.append("," + vv);
}
sb.append("\r\n");
sb.append("y info=");
for (int i = 0; i < yLen; i++) {
int vv = getInt(chunk, xLen * 4 + 32 + i * 4);
sb.append("," + vv);
}
sb.append("\r\n");
sb.append("color info=");
for (int i = 0; i < cLen; i++) {
int vv = getInt(chunk, xLen * 4 + yLen * 4 + 32 + i * 4);
sb.append("," + vv);
}
System.err.println("" + sb);
}
}
一个简易的9 patch图片解码工具
最新推荐文章于 2024-01-04 08:37:52 发布