蒙板压缩对比图:(此方法可大幅减小游戏包的大小)
包大小对比:
在游戏开发中,包的大小总是与图片资源的大小密切相关,而图片资源中,大多为带有透明度信息的png图像。
那么,如何精简png图片资源呢?
1、图像压缩是一种方法,然而随着压缩率的增大、图片品质也越来越差。(舍弃)
2、我们另辟蹊径,采用png图像拆分。(近乎无损,资源精简)
一、原理:将png图像转化为两张jpeg图像进行存储
二、使用方法:
1、LibGdx中,通过Pixmap使用
// 如工程目录assets/texture/0_1.jpeg下:
/** 从工程资源路径下获取图像,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */
public static Texture getTexture(String filePath1, String filePath2)
{
try
{
Pixmap pic1 = new Pixmap(Gdx.files.internal(filePath1));
Pixmap pic2 = new Pixmap(Gdx.files.internal(filePath2));
Pixmap pic = Combine(pic1, pic2); // 合并为png图像
return new Texture(pic); // 创建Texture
}
catch (Exception ex)
{
return null;
}
}
/** 从Pic和Mask合成图像 */
public static Pixmap Combine(Pixmap Pic, Pixmap Mask)
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Pixmap image = new Pixmap(closestTwoPower(width), closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂
int color1, color2, color, alpha;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
color1 = Pic.getPixel(i, j); // 原图像像素信息
color2 = Mask.getPixel(i, j); // 原图像透明度信息
alpha = (color2 & 0xff00) >> 8; // 透明度
color = alpha == 0 ? 0 : (color1 & 0xffffff00) | alpha; // 合成像素点
image.drawPixel(i, j, color); // 生成图像
}
}
return image;
}
/** 获取最接近于n的2的幂 */
public static int closestTwoPower(int n)
{
int power = 1;
while (power < n)
power <<= 1;
return power;
}
2、安卓中,通过 Bitmap使用(未调试)
/** 从工程资源路径下获取图像,如:filePath1 = "0_1.jpeg"、filePath2 = "0_2.jpeg" */
public static Bitmap getBitmap(String pathName1, String pathName2)
{
try
{
Bitmap pic1 = BitmapFactory.decodeFile(pathName1);
Bitmap pic2 = BitmapFactory.decodeFile(pathName2);
Bitmap pic = Combine(pic1, pic2); // 合并为png图像
return pic;
}
catch (Exception ex)
{
return null;
}
}
/** 从Pic和Mask创建bitmap图像 */
public static Bitmap Combine(Bitmap Pic, Bitmap Mask)
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Bitmap image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int color1, color2, color;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
color1 = Pic.getPixel(i, j); // 原图像像素信息
color2 = Pic.getPixel(i, j); // 原图像透明度信息
color = (color1 & 0x00ffffff) | ((color2 & 0x00ff0000) << 8); // 合成像素点
image.setPixel(i, j, color); // 生成图像
}
}
return image;
}
附类文件:(测试通过)
Bitmap2.java
/** 2015-5-25上午10:10:15 wangzhongyuan */
package com.hlge.lib.base;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.os.Environment;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.hlge.lib.HlgeActivity;
import com.hlge.lib.tool.Tools;
/** Bitmap2,对Bitmap进行相关图像处理、转化Bitmap的尺寸为2的幂,推荐使用函数getPixmapExt获取图像资源 ----- 2015-5-21 下午2:06:43 wangzhongyuan */
public class Bitmap2
{
/** 临时记录载入图像的尺寸 */
static int sizex, sizey;
/** 标识是否保存至缓存文件 */
private static boolean SaveTmpFile = false;
/** 图片缓存文件拓展名 */
private static String tmpExt = ".png"; // 缓存文件的实际类型
public static final String ReadSaveExt = ".png"; // 缓存文件读取和写入使用的文件拓展名
// -------------------------------------------------------------------------------------------------
/** 此hansh表中的图像资源,直接从内部资源进行载入 */
public static HashMap<String, String> LoadList = new HashMap<String, String>(); // 以 path + name为索引,拓展名为值
/** 此hansh表中的图像资源,从内部资源进行蒙板合成 */
public static ArrayList<String> CombineList = new ArrayList<String>(); // 以 path + name为键值
/** 对path路径下的所有图像按文件名分类, path = "texture/" */
public static void groupPicByName(String path)
{
// 路径有效性判定
FileHandle dir = Gdx.files.internal(path);
if (!dir.exists() || !dir.isDirectory())
Tools.Log(path + "不是有效路径!");
else
{
FileHandle[] files = dir.list();
for (FileHandle file : files)
{
String name = file.name();
if (name.endsWith("_1.jpeg") || name.endsWith("_2.jpeg"))
{
name = name.substring(0, name.lastIndexOf("_"));
if (!CombineList.contains(path + name)) CombineList.add(path + name); // 蒙板合并图像
}
else if (name.endsWith(".png") || name.endsWith(".jpg") || name.endsWith(".jpeg"))
{
name = name.substring(0, name.lastIndexOf("."));
if (!LoadList.containsKey(path + name)) LoadList.put(path + name, "." + file.extension()); // 直接载入图像
}
}
}
}
/** 预加载图像,载入进度 */
public static int loadprocess = 0;
/** 预加载所有蒙板图像,合成外部png缓存文件,在游戏载入时调用该函数,提前处理图像资源*/
public static void loadResources()
{
// 将文件夹中的图像资源按文件名分类存入LoadList和CombineList
groupPicByName("texture/");
groupPicByName("spine/");
// // 判定是否已对所有图像资源进行了缓存载入
// String value = LocalDB.readData("Bitmap2_loadResources");
// if (value.equals("3")) return;
// LocalDB.saveData("Bitmap2_loadResources", "3");
for (int i = 0; i < CombineList.size(); i++)
{
String pathName = CombineList.get(i);
FileHandle file = new FileHandle(getPath() + pathName + ReadSaveExt); // 缓存文件判定
if (!file.exists())
{
Bitmap pic = getBitmap(pathName + "_1.jpeg", pathName + "_2.jpeg"); // 合成图像
int end = pathName.lastIndexOf("/") + 1;
String path = end != -1 ? pathName.substring(0, end) : "";
String name = end != -1 ? pathName.substring(end) : pathName;
Bitmap2.save(path, name, pic); // 保存至文件缓存
pic.recycle(); // 释放资源
}
loadprocess = (int) ((((float) i) / CombineList.size()) * 100);
Tools.Log("蒙板图像载入进度 " + loadprocess + "% ");
}
loadprocess = 100;
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */
public static Pixmap getPixmapExt(String path, String fileName)
{
Pixmap pic = null;
try
{
pic = Pixmap2.read(path, fileName, ReadSaveExt); // 从缓存中读取
if (pic != null) return pic;
String pathName = path + fileName;
if (CombineList.contains(pathName))
// 直接从蒙板合成图像
{
Bitmap tmp = getBitmap(pathName + "_1.jpeg", pathName + "_2.jpeg");
pic = ToPixmap(tmp);
Bitmap2.save(path, fileName, tmp); // 保存至文件缓存
tmp.recycle(); // 释放资源
}
else if (LoadList.containsKey(pathName))
// 直接从内部资源载入图像
{
String Ext = LoadList.get(pathName);
pic = new Pixmap(Gdx.files.internal(pathName + Ext));
// 载入图像尺寸校验,需为2的次幂
int width = pic.getWidth(), height = pic.getHeight();
int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);
if (w != width || h != height)
{
Bitmap tmp = getBitmap(pathName + Ext);
pic = ToPixmap(tmp);
Bitmap2.save(path, fileName, tmp); // 保存至文件缓存
tmp.recycle(); // 释放资源
}
}
else
// 检索所有拓展名载入
{
Bitmap tmp = getBitmapExtProcess(path, fileName); // 从工程内部资源文件生成
Bitmap2.save(path, fileName, tmp); // 保存至文件缓存
pic = ToPixmap(tmp); // 转化为Pixmap
tmp.recycle();
}
return pic;
}
catch (Exception ex)
{
Tools.Log("载入图像" + path + fileName + "出错!");
return null;
}
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic",获取图像后自动缓存至文件 */
public static Bitmap getBitmapExt(String path, String fileName)
{
Bitmap pic = Bitmap2.read(path, fileName); // 优先从本地文件缓存中读取
if (pic != null)
return pic;
else
{
pic = getBitmapExtProcess(path, fileName); // 从工程内部资源文件生成
Bitmap2.save(path, fileName, pic); // 保存至文件缓存
return pic;
}
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */
private static Bitmap getBitmapExtProcess(String path, String fileName)
{
String filePath = path + fileName; // 工程内部资源路径+文件名(无拓展名)
Bitmap pic;
// 载入png或jpg图像
String[] Exts = { ".png", ".jpg", ".jpeg" };
for (String exts : Exts)
{
tmpExt = exts;
pic = getAssetsBitmap(path + fileName + exts);
if (pic != null) return FormatSize(pic);
}
// 从pngSplit工具,导出的蒙板图像载入
tmpExt = ".png";
pic = getBitmap(path + fileName + "_1.jpeg", path + fileName + "_2.jpeg");
if (pic != null) return pic;
Tools.Log(filePath + " Bitmap载入出错!");
return null;
}
// pic = getImageFromAssetsFile("assets/texture/0.png");
/** 从Assets目录中读取图片, fileName = "texture/0_1.jpeg" */
@SuppressWarnings("unused")
public static Bitmap getAssetsBitmap(String fileName)
{
// 判断文件是否存在
FileHandle handle = Gdx.files.internal(fileName);
if (!handle.exists()) return null;
Bitmap image = null;
AssetManager manager = HlgeActivity.$this.getResources().getAssets();
try
{
InputStream is = manager.open(fileName);
image = BitmapFactory.decodeStream(is);
is.close();
}
catch (IOException e)
{
e.printStackTrace();
}
return image;
}
// 如工程目录assets/texture/0_1.jpeg下:
/** 获取工程目录下的图像,如:filePath = "texture/0_1.jpeg" */
public static Bitmap getBitmap(String filePath)
{
Bitmap pic = getAssetsBitmap(filePath); // 从assets获取图像
pic = FormatSize(pic); // 转化为2的n次幂
return pic;
}
// 如工程目录assets/texture/0_1.jpeg下:
/** 从pngSplit工具,导出的两张蒙板图像创建,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */
public static Bitmap getBitmap(String filePath1, String filePath2)
{
try
{
Bitmap pic1 = getAssetsBitmap(filePath1);
Bitmap pic2 = getAssetsBitmap(filePath2);
Bitmap pic = Bitmap2.Combine(pic1, pic2);
pic1.recycle();
pic2.recycle();
return pic;
}
catch (Exception ex)
{
Tools.Log("从蒙板资源创建Bitmap出错!(" + filePath1 + "、" + filePath2 + ")");
return null;
}
}
/** 从两张蒙板图像Pic和Mask,合成图像 */
public static Bitmap Combine(Bitmap Pic, Bitmap Mask)
{
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Bitmap2.sizex = width; // 记录图像原尺寸
Bitmap2.sizey = height;
int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);
Bitmap image = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); // 合成尺寸为2的幂
// image.eraseColor(0xffffffff);
int color1, color2, color;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
color1 = Pic.getPixel(i, j); // 原图像像素信息
color2 = Mask.getPixel(i, j); // 原图像透明度信息
color = (color1 & 0x00ffffff) | ((color2 & 0x00ff0000) << 8); // 合成像素点
image.setPixel(i, j, color); // 生成图像
}
}
SaveTmpFile = true; // 可保存当前图像至缓存
return image;
}
catch (Exception ex)
{
Tools.Log("从蒙板合成图像出错!");
return null;
}
}
/** 将Pic转化为尺寸为2的幂的图像 */
public static Bitmap FormatSize(Bitmap Pic)
{
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Bitmap2.sizex = width; // 记录图像原尺寸
Bitmap2.sizey = height;
int w = Bitmap2.closestTwoPower(width), h = Bitmap2.closestTwoPower(height);
if (w == width && h == height) return Pic; // 若原图像尺寸为2的幂,则直接返回原图像
// 构建2的n次幂图像
Bitmap image = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
Canvas g2d = new Canvas(image);
g2d.drawBitmap(Pic, 0, 0, new Paint());
// Paint p = new Paint();
// p.setColor(Color.WHITE);
// p.setAntiAlias(true);
// p.setFilterBitmap(true);
// int color;
// for (int i = 0; i < width; i++)
// {
// for (int j = 0; j < height; j++)
// {
// color = Pic.getPixel(i, j); // 原图像像素信息
// image.setPixel(i, j, color); // 生成图像
// }
// }
SaveTmpFile = true; // 可保存当前图像至缓存
return image;
}
catch (Exception ex)
{
Tools.Log("Bitmap尺寸转化为2的幂出错!");
return null;
}
}
/** 获取最接近于n的2的幂 */
public static int closestTwoPower(int n)
{
int power = 1;
while (power < n)
power <<= 1;
return power;
}
/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */
public static String getPath()
{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
return Environment.getExternalStorageDirectory().getPath() + "/tmp/";
else
return "/tmp/";
}
/** 从本地缓存文件载入Pixmap, subPath为子文件夹,如:"sub/" */
public static Bitmap read(String subPath, String fileName)
{
try
{
// 从指定路径获取文件
String path = getPath() + subPath, name = fileName + ReadSaveExt;
File file = new File(path, name);
// 创建Bitmap
if (file.exists())
return BitmapFactory.decodeFile(path + name);
else
return null;
}
catch (Exception e)
{
Tools.Log("Bitmap文件读取出错(" + fileName + tmpExt + ") " + e.toString());
return null;
}
}
// /** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/", 不进行条件判断存储 */
// public static void saveOne(String subPath, String fileName, Bitmap bitmap)
// {
// if (bitmap == null) return;
//
// SaveTmpFile = true;
// save(subPath, fileName, bitmap);
//
// bitmap = null;
// }
/** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/" */
public static void save(String subPath, String fileName, Bitmap bitmap)
{
if (bitmap == null) return; // 图像为null
if (SaveTmpFile)
SaveTmpFile = false; // 可保存当前图像至缓存
else
return;
try
{
// 确保路径文件存在
String path = getPath() + subPath, name = fileName + ReadSaveExt;
File dir = new File(path);
if (!dir.exists()) dir.mkdirs();
File file = new File(path, name);
if (!file.exists()) file.delete();
file.createNewFile();
// 压缩格式设置
CompressFormat format = CompressFormat.PNG;
if (tmpExt.equalsIgnoreCase(".jpg") || tmpExt.equalsIgnoreCase(".jpeg")) format = CompressFormat.JPEG;
// 保存图像到文件
Bitmap2.save(bitmap, file, format);
}
catch (Exception e)
{
Tools.Log("Bitmap写入文件出错(" + fileName + ") " + e.toString());
}
}
/** 保存bitmap到file中,按格式format进行压缩 */
public static void save(Bitmap bitmap, File file, CompressFormat format) // CompressFormat.PNG
{
try
{
// 将bitmap,压缩到字节输出流
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(format, format == CompressFormat.JPEG ? 100 : 1, stream); // jpg图像最高质量存储,png图像最低质量存储
// 从文件输出流,写入文件
FileOutputStream fout = new FileOutputStream(file);
fout.write(stream.toByteArray());
fout.flush();
fout.close();
}
catch (Exception e)
{
Tools.Log("保存bitmap到file中出错" + e.toString());
}
}
/** Bitmap向Pixmap的转化 */
public static Pixmap ToPixmap(Bitmap bitmap)
{
if (bitmap == null) return null;
// 从Bitmap创建输出流
int size = bitmap.getWidth() * bitmap.getHeight();
ByteArrayOutputStream outStream = new ByteArrayOutputStream(size);
bitmap.compress(Bitmap.CompressFormat.PNG, 0, outStream);
// 从输出流创建Pixmap
byte[] img = outStream.toByteArray();
return new Pixmap(img, 0, img.length);
}
}
Pixmap2.java
package com.hlge.lib.base;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import android.graphics.Bitmap;
import android.os.Environment;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.PixmapIO;
import com.hlge.lib.tool.LocalDB;
import com.hlge.lib.tool.Tools;
/** Pixmap2,对Pixmap进行相关图像处理、转化Pixmap的尺寸为2的幂, 内部功能实现基于Bitmap2 ----- 2015-5-21 下午2:06:43 wangzhongyuan */
public class Pixmap2
{
/** 临时记录载入图像的尺寸 */
static int sizex, sizey;
/** 临时记录用于存储的Bitmap */
static Bitmap tmpSaveBitmap = null;
// -------------------------------------------------------------------------------------------------
/** 载入路径下path所有图像资源, path = "texture/" */
public static void loadPixmapAll(String path)
{
// 判定是否已对所有图像资源进行了缓存载入
String value = LocalDB.readData("loadPixmapAll");
if (value.equals("2")) return;
LocalDB.saveData("loadPixmapAll", "2");
// FileHandle handle = new FileHandle(getPath() + path);
// if(handle.exists()) return;
// 获取路径下所有文件
FileHandle dir = Gdx.files.internal(path);
if (!dir.exists() || !dir.isDirectory()) return;
// 提取文件名
ArrayList<String> pathNames = new ArrayList<String>();
FileHandle[] files = dir.list();
String tmp; // 获取文件名,不含路径
for (FileHandle file : files)
{
tmp = path.equals("") ? file.path() : file.path().substring(path.length());
pathNames.add(tmp);
}
try
{
String name, name2;
while (pathNames.size() > 0)
{
name = pathNames.remove(0);
boolean b_1 = name.endsWith("_1.jpeg"), b_2 = name.endsWith("_2.jpeg");
if (b_1 || b_2) // 为蒙板导出的图像 "_1.jpeg", "_2.jpeg"合并为一个文件
{
name2 = b_1 ? name.replace("_1.jpeg", "_2.jpeg") : name.replace("_2.jpeg", "_1.jpeg");
if (pathNames.contains(name2))
{
pathNames.remove(name2);
name = name.substring(0, name.lastIndexOf("_"));
}
else
name = name.substring(0, name.lastIndexOf("."));
}
else if (name.contains(".")) name = name.substring(0, name.lastIndexOf("."));
Pixmap pic = getPixmapExt(path, name); // 从工程资源目录下载入所有资源,生成资源缓存文件
pic.dispose(); // 释放纹理
Tools.Log("缓存文件" + path + name + " 剩余未载入个数:" + pathNames.size());
}
}
catch (Exception ex)
{
Tools.Log("载入路径" + path + "下的图像出错,剩余未载入个数:" + pathNames.size());
}
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */
public static Pixmap getPixmapExt(String path, String fileName, String tmpExt)
{
String tmp = Pixmap2.tmpExt;
Pixmap2.tmpExt = tmpExt;
Pixmap pic = getPixmapExt(path, fileName);
Pixmap2.tmpExt = tmp;
return pic;
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic",获取图像后自动缓存至文件 */
public static Pixmap getPixmapExt(String path, String fileName)
{
// Pixmap pic = Pixmap2.read(path, fileName); // 优先从本地文件缓存中读取
Pixmap pic = Pixmap2.read(path, fileName, Bitmap2.ReadSaveExt); // 优先从本地文件缓存中读取
if (pic != null)
return pic;
else
{
pic = getPixmapExtProcess(path, fileName); // 工程内部资源文件生成
// Pixmap2.save(path, fileName, pic); // 保存至文件缓存
Bitmap2.save(path, fileName, tmpSaveBitmap);// 保存至文件缓存
resetSize(pic);
tmpSaveBitmap.recycle(); // 释放资源
tmpSaveBitmap = null;
return pic;
}
}
/** 从目录assets/texture/下获取图像 pic.*,对应参数为:path = "texture/", fileName = "pic" */
private static Pixmap getPixmapExtProcess(String path, String fileName)
{
String filePath = path + fileName; // 工程内部资源路径+文件名(无拓展名)
FileHandle handle, handle2;
// 从png图像载入
handle = Gdx.files.internal(filePath + ".png");
if (handle.exists()) return getPixmap(handle);
// 从jpg图像载入
handle = Gdx.files.internal(filePath + ".jpg");
if (handle.exists()) return getPixmap(handle);
handle = Gdx.files.internal(filePath + ".jpeg");
if (handle.exists()) return getPixmap(handle);
// 从pngSplit工具,导出的蒙板图像载入
handle = Gdx.files.internal(filePath + "_1.jpeg");
handle2 = Gdx.files.internal(filePath + "_2.jpeg");
// if (handle.exists() && handle2.exists()) return Combine(getPixmap(handle), getPixmap(handle2));
if (handle.exists() && handle2.exists()) return getPixmap(filePath + "_1.jpeg", filePath + "_2.jpeg");
Tools.Log(filePath + "Pixmap载入出错!");
return null;
}
/** 设置当前pic的尺寸信息 */
private static void resetSize(Pixmap pic)
{
if (Bitmap2.sizex == 0 || Bitmap2.sizey == 0)
{
if (pic == null)
sizex = sizey = 0;
else
{
sizex = pic.getWidth();
sizey = pic.getHeight();
}
}
else
{
sizex = Bitmap2.sizex;
sizey = Bitmap2.sizey;
}
}
/** 获取工程路径下的图像为Pixmap,如:filePath = "texture/0.png" */
public static Pixmap getPixmap(String filePath)
{
FileHandle handle = Gdx.files.internal(filePath);
if (handle.exists()) // 从给定的路径载入
{
// 从缓存读取
String path = handle.parent().path() + "/", name = handle.nameWithoutExtension();
Pixmap pic = Pixmap2.read(path, name, Bitmap2.ReadSaveExt);
// 从文件载入
if (pic == null) pic = getPixmap(handle);
Bitmap2.save(path, name, tmpSaveBitmap);// 保存至文件缓存
resetSize(pic);
tmpSaveBitmap.recycle(); // 释放资源
tmpSaveBitmap = null;
return pic;
}
else if (filePath.contains("."))// 给定路径文件不存在,尝试其他后缀名载入
{
// 剔除后缀名
int index = filePath.lastIndexOf(".");
String name = filePath.substring(0, index);
// 分割子路径和文件名
index = filePath.lastIndexOf("/");
if (index == -1)
filePath = "";
else
{
filePath = name.substring(0, index + 1); // 子路径
name = name.substring(index + 1); // 文件名
}
return getPixmapExt(filePath, name);
}
else
Tools.Log("从( " + filePath + " )创建Pixmap出错!");
return null;
}
/** 获取handle对应的Pixmap,并转化其尺寸为2的幂 */
public static Pixmap getPixmap(FileHandle handle)
{
try
{
// Pixmap pic = new Pixmap(handle); // 获取对应的图像
// pic = Pixmap2.FormatSize(pic); // 图像尺寸转化为2的幂
Bitmap tmp = Bitmap2.getBitmap(handle.path()); // 从Bitmap载入图像
tmpSaveBitmap = tmp; // 记录该Bitmap,待存储
Pixmap pic = Bitmap2.ToPixmap(tmp); // 转化为Pixmap
return pic;
}
catch (Exception ex)
{
Tools.Log("从FileHandle=" + handle.toString() + "创建Pixmap出错!");
return null;
}
}
// 如工程目录assets/texture/0_1.jpeg下:
/** 从pngSplit工具,导出的两张蒙板图像创建,如:filePath1 = "texture/0_1.jpeg"、filePath2 = "texture/0_2.jpeg" */
public static Pixmap getPixmap(String filePath1, String filePath2)
{
try
{
// 从Pixmap载入像素有差异(舍弃)
// Pixmap pic1 = new Pixmap(Gdx.files.internal(filePath1));
// Pixmap pic2 = new Pixmap(Gdx.files.internal(filePath2));
// return Pixmap2.Combine(pic1, pic2);
// 以Bitmap方式载入,合成为Pixmap
// Bitmap pic1 = Bitmap2.getAssetsBitmap(filePath1);
// Bitmap pic2 = Bitmap2.getAssetsBitmap(filePath2);
//
// return Pixmap2.Combine(pic1, pic2);
// 以Bitmap方式载入,转化为Pixmap
Bitmap pic = Bitmap2.getBitmap(filePath1, filePath2);
tmpSaveBitmap = pic; // 记录该Bitmap,待存储
return Bitmap2.ToPixmap(pic);
}
catch (Exception ex)
{
Tools.Log("从蒙板资源创建Pixmap出错!(" + filePath1 + "、" + filePath2 + ")");
return null;
}
}
/** 从两张蒙板图像Pic和Mask,合成图像 —— 从Pixmap载入图像,获取的像素值与工具导出像素有差异 */
public static Pixmap Combine(Pixmap Pic, Pixmap Mask)
{
// Log.i("Format", Pic.getFormat().name() + " " + Mask.getFormat().name());
// Format f1 = Pic.getFormat(), f2 = Mask.getFormat();
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Pixmap2.sizex = width; // 记录图像原尺寸
Pixmap2.sizey = height;
Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂
int color1, color2, color, alpha = 0;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
color1 = Pic.getPixel(i, j); // 原图像像素信息
color2 = Mask.getPixel(i, j); // 原图像透明度信息
color1 &= 0xffffff00; // 获取RGB0
alpha = ((color2 & 0x0000ff00) >>> 8); // 获取A
color = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBA
image.drawPixel(i, j, color); // 生成图像
}
}
return image;
}
catch (Exception ex)
{
Tools.Log("从蒙板合成图像出错!");
return null;
}
}
/** 从两张Bitmap蒙板图像Pic和Mask,合成Pixmap */
public static Pixmap Combine(Bitmap Pic, Bitmap Mask)
{
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Pixmap2.sizex = width; // 记录图像原尺寸
Pixmap2.sizey = height;
int w = Pixmap2.closestTwoPower(width), h = Pixmap2.closestTwoPower(height);
Pixmap image = new Pixmap(w, h, Format.RGBA8888); // 合成尺寸为2的幂
int color1, color2, color;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
color1 = Pic.getPixel(i, j); // 原图像像素信息, ARGB_8888
color2 = Mask.getPixel(i, j); // 原图像透明度信息, ARGB_8888
color = (color1 << 8) | (color2 & 0x000000ff); // 合成像素点, RGBA8888
image.drawPixel(i, j, color); // 生成图像
}
}
return image;
}
catch (Exception ex)
{
Tools.Log("从蒙板合成图像出错!");
return null;
}
}
/** 从两张蒙板图像Pic和Mask,合成图像 */
public static Pixmap CombineT(Pixmap Pic, Pixmap Mask)
{
// Log.i("Format", Pic.getFormat().name() + " " + Mask.getFormat().name());
// Format f1 = Pic.getFormat(), f2 = Mask.getFormat();
StringBuffer str1 = new StringBuffer(), str2 = new StringBuffer(), str3 = new StringBuffer();
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Pixmap2.sizex = width; // 记录图像原尺寸
Pixmap2.sizey = height;
Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Format.RGBA8888); // 合成尺寸为2的幂
int color1, color2, color, alpha = 0;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
color1 = Pic.getPixel(j, i); // 原图像像素信息
color2 = Mask.getPixel(j, i); // 原图像透明度信息
str1.append(Integer.toHexString(color1) + (j < width - 1 ? "," : ""));
str2.append(Integer.toHexString(color2) + (j < width - 1 ? "," : ""));
color1 &= 0xffffff00; // 获取RGB0
alpha = ((color2 & 0x0000ff00) >>> 8); // 获取A
color = alpha == 0 ? 0 : (color1 | alpha); // 合成RGBA
str3.append(Integer.toHexString(color) + (j < width - 1 ? "," : ""));
image.drawPixel(j, i, color); // 生成图像
}
str1.append(i < height - 1 ? "\r\n" : "");
str2.append(i < height - 1 ? "\r\n" : "");
str3.append(i < height - 1 ? "\r\n" : "");
}
FileHandle handle = Gdx.files.internal(getPath() + "color.txt");
if (!handle.exists()) handle.file().createNewFile();
FileOutputStream fout = new FileOutputStream(new File(getPath(), "color.txt"));
PrintStream ps = new PrintStream(fout);
ps.println("\r\n\r\n\r\n" + str1.toString());
ps.append("\r\n\r\n\r\n" + str2.toString());
ps.append("\r\n\r\n\r\n" + str3.toString());
ps.close();
return image;
}
catch (Exception ex)
{
Tools.Log("从蒙板合成图像出错!");
return null;
}
}
/** 将Pic转化为尺寸为2的幂的图像 */
public static Pixmap FormatSize(Pixmap Pic)
{
// Log.i("Format", Pic.getFormat().name());
try
{
int width = Pic.getWidth(), height = Pic.getHeight(); // 获取图像的尺寸
Pixmap2.sizex = width; // 记录图像原尺寸
Pixmap2.sizey = height;
Pixmap image = new Pixmap(Pixmap2.closestTwoPower(width), Pixmap2.closestTwoPower(height), Pic.getFormat());
if (image.getWidth() == width && image.getHeight() == height) return Pic; // 若原图像尺寸为2的幂,则直接返回原图像
image.drawPixmap(Pic, 0, 0);
// int color;
// for (int i = 0; i < width; i++)
// {
// for (int j = 0; j < height; j++)
// {
// color = Pic.getPixel(i, j); // 原图像像素信息
// image.drawPixel(i, j, color); // 生成图像
// }
// }
return image;
}
catch (Exception ex)
{
Tools.Log("Pixmap尺寸转化为2的幂出错!");
return null;
}
}
/** 获取最接近于n的2的幂 */
public static int closestTwoPower(int n)
{
int power = 1;
while (power < n)
power <<= 1;
return power;
}
/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */
public static String getPath()
{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
return Environment.getExternalStorageDirectory().getPath() + "/tmp/";
else
return "/tmp/";
}
/** 图片缓存文件拓展名 */
private static String tmpExt = ".byte";
/** 保存pixmap到缓存文件fileName, subPath为子文件夹,如:"sub/" */
public static void save(String subPath, String fileName, Pixmap pixmap)
{
try
{
pixmap.setColor(0);
FileHandle file = new FileHandle(getPath() + subPath + fileName + tmpExt);
if (file.exists()) file.delete(); // 若文件已存在,则删除
if (tmpExt.equals(".byte"))
PixmapIO.writeCIM(file, pixmap);
else
PixmapIO.writePNG(file, pixmap); // 将pixmap写入文件中缓存
}
catch (Exception e)
{
Tools.Log("Pixmap写入文件出错(" + fileName + ") " + e.toString());
}
}
/** 从本地缓存文件载入Pixmap, subPath为子文件夹,如:"sub/" */
public static Pixmap read(String subPath, String fileName)
{
return read(subPath, fileName, tmpExt);
}
/** 从本地缓存文件载入Pixmap,拓展名为tmpExt, subPath为子文件夹,如:"sub/" */
public static Pixmap read(String subPath, String fileName, String tmpExt)
{
try
{
FileHandle file = new FileHandle(getPath() + subPath + fileName + tmpExt);
if (tmpExt.equals(".byte"))
return !file.exists() ? null : PixmapIO.readCIM(file);
else
return !file.exists() ? null : new Pixmap(file);
}
catch (Exception e)
{
Tools.Log("Pixmap文件读取出错(" + fileName + tmpExt + ") " + e.toString());
return null;
}
}
}
package com.hlge.lib.tool;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Random;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.ScreenUtils;
import com.hlge.lib.HlgeActivity;
import com.hlge.lib.HlgeConfig;
import com.hlge.lib.HlgeHelper;
import com.hlge.lib.HlgeLauncher;
/** Tools 工具类,封装一些常用功能函数 ----- 2015-5-16 下午3:55:16 wangzhongyuan */
public class Tools
{
// ------------------------------------------------功能函数-----------------------------------------------
/** 控制手机震动 */
public static void shakePhone(short milliseconds)
{
Gdx.input.vibrate(milliseconds);
}
/** 打开url地址页 */
public static void loadUrl(String url)
{
Intent it = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
HlgeActivity.$this.startActivity(it);
}
/** 将字符串转化为数值,默认值为0 */
public static int parseInt(String strNum)
{
int num = 0;
try
{
num = Integer.parseInt(strNum.trim());
}
catch (Exception ex)
{}
;
return num;
}
/** 将字符串转化为数值,默认值为0 */
public static float parseFloat(String strNum)
{
float num = 0;
try
{
num = Float.parseFloat(strNum.trim());
}
catch (Exception ex)
{}
;
return num;
}
// --------------------------------------------------随机数、序列数生成、数组排序------------------------------------------------
// 随机数发生器
public static final Random random = new Random();
/** 生成[0, n)范围的随机整数 */
public static int random(int n)
{
return random.nextInt(n);
}
/** 生成[lower, upper]范围的随机整数 */
public static int random(int lower, int upper)
{
if (lower > upper)
return random(upper, lower);
else
return random.nextInt(upper - lower + 1) + lower;
}
/** 序列数生成算法,生成1到n的随机序列数组,每个数值出现且仅出现一次 */
public static int[] getSerial(int n)
{
Random Rnd = new Random();
int[] tmp = new int[n];
int[] num1 = new int[n];
for (int i0 = 1; i0 <= n; i0++)
num1[i0 - 1] = i0;
for (int i = num1.length; i > 0; i--)
{
Rnd.setSeed(Rnd.nextLong());
int index = Rnd.nextInt(i);
// 随机选中一个数
tmp[i - 1] = num1[index];
// 剔除选中的数值
int[] num2 = new int[i - 1];
for (int j = 0; j < i; j++)
if (j < index)
num2[j] = num1[j];
else if (j > index) num2[j - 1] = num1[j];
num1 = num2;
}
return tmp;
}
/** 数组排序函数 */
public static int[] sort(int[] data)
{
int tmp;
for (int i = 0; i < data.length - 1; i++)
{
for (int j = i + 1; j < data.length; j++)
if (data[i] > data[j])
{
tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
}
return data.clone();
}
// ------------------------------------------------区域颜色填充-----------------------------------------------
/** 用颜色color填充整个界面,Rect为坐标为左下坐标系 */
public static void filledRect(Color color)
{
filledRect(HlgeLauncher.batch, HlgeLauncher.render, color, null);
}
/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */
public static void filledRect(Color color, Rectangle Rect)
{
filledRect(HlgeLauncher.batch, HlgeLauncher.render, color, Rect);
}
/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */
public static void filledRect(SpriteBatch batch, Color color, Rectangle Rect)
{
filledRect(batch, HlgeLauncher.render, color, Rect);
}
/** 在Rect区域用颜色color进行填充,Rect为坐标为左下坐标系 */
public static void filledRect(SpriteBatch batch, ShapeRenderer render, Color color, Rectangle Rect)
{
if (Rect == null) Rect = new Rectangle(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT);
batch.end();
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
render.begin(ShapeRenderer.ShapeType.FilledRectangle);
render.setColor(color);
render.filledRect(Rect.x / HlgeHelper.scalex, Rect.y / HlgeHelper.scaley, Rect.width / HlgeHelper.scalex, Rect.height / HlgeHelper.scaley);
render.end();
batch.begin();
}
// ------------------------------------------------半透阴影的绘制-----------------------------------------------
/** 绘制半透阴影,不透明度alpha */
public static void drawShadow(float alpha)
{
// drawShadow(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT, 0, 0, 0, 0, alpha, 1);
filledRect(new Color(0, 0, 0, alpha));
}
/** 绘制半透阴影, 区域(x,y,w,h)高亮,不透明度alpha */
public static void drawShadow(float x, float y, float w, float h, float alpha)
{
drawShadow(0, 0, HlgeConfig.CONF_SCREEN_WIDTH, HlgeConfig.CONF_SCREEN_HEIGHT, x, y, x + w, y + h, alpha, 20);
}
// 绘制半透阴影,在区域(x1,y1)-(x2,y2)中,除区域范围(x3,y3)-(x4,y4)外绘制阴影,阴影不透明度为alpha,分fade次进行渲染
private static void drawShadow(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float alpha, int fade)
{
HlgeLauncher.batch.end();
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
HlgeLauncher.render.begin(ShapeRenderer.ShapeType.FilledRectangle);
if (fade < 1) fade = 1;
alpha = alpha / fade;
HlgeLauncher.render.setColor(0, 0, 0, alpha);
if (x4 == x3 || y4 == y3)
drawShadow(HlgeLauncher.render, x1, y1, x2, y2, x3, y3, x4, y4);
else
{
float boder = 15f / fade;
fade += 10;
while (fade-- > 10)
{
x3 += boder;
y3 += boder;
x4 -= boder;
y4 -= boder;
drawShadow(HlgeLauncher.render, x1, y1, x2, y2, x3, y3, x4, y4);
}
}
HlgeLauncher.render.end();
HlgeLauncher.batch.begin();
}
// 绘制半透阴影,在区域(x1,y1)-(x2,y2)中,除区域范围(x3,y3)-(x4,y4)外绘制阴影
private static void drawShadow(ShapeRenderer renderer, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4)
{
// 转化为badlogic.gdx坐标系
y3 = HlgeConfig.CONF_SCREEN_HEIGHT - y3;
y4 = HlgeConfig.CONF_SCREEN_HEIGHT - y4;
y1 = HlgeConfig.CONF_SCREEN_HEIGHT - y1;
y2 = HlgeConfig.CONF_SCREEN_HEIGHT - y2;
// 屏幕尺寸缩放,位置变换
x1 /= HlgeHelper.scalex;
y1 /= HlgeHelper.scaley;
x2 /= HlgeHelper.scalex;
y2 /= HlgeHelper.scaley;
x3 /= HlgeHelper.scalex;
y3 /= HlgeHelper.scaley;
x4 /= HlgeHelper.scalex;
y4 /= HlgeHelper.scaley;
if (x4 == x3 || y4 == y3)
renderer.filledRect(x1, y2, x2 - x1, y1 - y2);
else
{
renderer.filledRect(x1, y2, x2 - x1, y4 - y2);
renderer.filledRect(x1, y4, x3 - x1, y3 - y4);
renderer.filledRect(x4, y4, x2 - x4, y3 - y4);
renderer.filledRect(x1, y3, x2 - x1, y1 - y3);
}
}
// --------------------------------------------------文件数据读取,保存------------------------------------------------
/** 从输入流读取数据 */
public static String ReadString(DataInputStream dis)
{
try
{
ArrayList<Byte> stringByte = new ArrayList<Byte>();
while (true)
{
byte data;
data = dis.readByte();
if (data != 0)
stringByte.add(data);
else
break;
}
byte datas[] = new byte[stringByte.size()];
for (int i = 0; i < datas.length; i++)
datas[i] = stringByte.get(i);
return new String(datas, "GBK");
}
catch (IOException e)
{
e.printStackTrace();
}
return null;
}
/** 从字节数组的offset处开始读取len个字节,形成一个int返回 */
public static final int readFromByteArray(byte[] data, int offset, int length)
{
int param = 0;
int mbit = 0;
for (int i = length - 1; i >= 0; i--)
{
mbit = (length - i - 1) << 3;
param |= ((data[offset + i] << mbit) & (0xff << mbit));
}
switch (length)
{
case 1:
param = (byte) param;
break;
case 2:
param = (short) param;
break;
case 4:
param = (int) param;
break;
}
return param;
}
/** 读取乐堂工具导出资源file,读取类型mode */
public static String getTextFile(String file, byte mode)
{
InputStream is = read(file, mode).read();
byte[] buffer;
try
{
buffer = new byte[is.available()];
is.read(buffer);
return new String(buffer);
}
catch (IOException e)
{
e.printStackTrace();
}
return "";
}
/** 文件类型 */
public static final byte FILE_TYPE_ACTOR = 1, FILE_TYPE_RAW = 2, FILE_TYPE_MAP = 3, FILE_TYPE_SCENE = 4, FILE_TYPE_XML = 5, FILE_TYPE_FONT = 6,
FILE_TYPE_PIC = 7, FILE_TYPE_SOUND = 8, FILE_TYPE_CG = 9, FILE_TYPE_QUESTVAR = 10, FILE_TYPE_SCRIPT = 11, FILE_TYPE_ABSOLUTE = 12;
/** 乐堂工具导出资源的路径读取 */
public static FileHandle read(String filename, byte mode)
{
switch (mode)
{
case FILE_TYPE_ACTOR:
FileHandle fh = Gdx.files.internal("actor/" + filename);
return fh.exists() ? fh : Gdx.files.internal("actor/" + LangManager.lang() + "/" + filename);
case FILE_TYPE_QUESTVAR:
return Gdx.files.internal("scene/" + filename);
case FILE_TYPE_MAP:
return Gdx.files.internal("map/" + filename);
case FILE_TYPE_RAW:
return Gdx.files.internal("raw/" + filename);
case FILE_TYPE_SCENE:
return Gdx.files.internal("scene/" + filename);
case FILE_TYPE_XML:
return Gdx.files.internal("xml/" + filename);
case FILE_TYPE_FONT:
return Gdx.files.internal("font/" + filename);
case FILE_TYPE_PIC:
return Gdx.files.internal("texture/" + filename);
case FILE_TYPE_SOUND:
return Gdx.files.internal("snd/" + filename);
case FILE_TYPE_CG:
return Gdx.files.internal("cg/" + filename);
case FILE_TYPE_SCRIPT:
return Gdx.files.internal("scene/sd/" + filename);
case FILE_TYPE_ABSOLUTE:
return new FileHandle(new File(filename));
default:
throw new RuntimeException("文件类型有误,位置read()");
}
}
/** 获取当前屏幕截图 */
public static Bitmap captureScreen(int x, int y, int w, int h, boolean flipy)
{
byte[] arr = ScreenUtils.getFrameBufferPixels(x, y, w, h, flipy);
int[] bitArr = new int[w * h];
for (int i = 0; i < arr.length; i += 4)
{
bitArr[i / 4] = (int) (((arr[i + 3] & 0xFF) << 24) | ((arr[i] & 0xFF) << 16) | ((arr[i + 1] & 0xFF) << 8) | (arr[i + 2] & 0xFF));
}
return Bitmap.createBitmap(bitArr, w, h, Bitmap.Config.ARGB_8888);
}
/** 保存图片filename到路径savePath */
public static void saveImage(Bitmap bitmap, String savePath, String filename)
{
if (getSDCardPath() != null) savePath += getSDCardPath();
try
{
File path = new File(savePath);
String filePath = savePath + "/" + filename;
File file = new File(filePath);
if (!path.exists()) path.mkdirs();
if (!file.exists()) file.createNewFile();
FileOutputStream fos = null;
fos = new FileOutputStream(file);
if (null != fos)
{
if (filename.endsWith(".png"))
bitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
else
{
Log.e("Utils.saveImage()", "filename must be end with .png!!!");
fos.close();
}
fos.flush();
fos.close();
Log.v("tag", filename + "save to" + savePath + "successful!");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
/** 获取SDCard的路径 */
private static String getSDCardPath()
{
File sdcardDir = null;
boolean sdcardExist = Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED);
if (sdcardExist) sdcardDir = Environment.getExternalStorageDirectory(); // 判断SDCard是否存在
return sdcardDir.toString();
}
/** 获取SD卡或内部存储路径,优先选择SD卡 , "/tmp/" */
public static String getTmpPath()
{
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
return Environment.getExternalStorageDirectory().getPath() + "/tmp/";
else
return "/tmp/";
}
/** 将数据data保存至文件file中, Dir = "texture/", fileName = "color.txt" */
public static void WriteStringToFile(String data)
{
WriteStringToFile(data, getTmpPath(), "tmp.txt");
}
/** 将数据data保存至文件file中, Dir = "texture/", fileName = "color.txt" */
public static void WriteStringToFile(String data, String Dir, String fileName)
{
try
{
// 确保文件路径 Dir + fileName 存在,不存在则创建
File dir = new File(Dir);
if (!dir.exists()) dir.mkdirs();
File file = new File((Dir.endsWith("/") ? Dir : Dir + "/") + fileName);
if (!file.exists()) file.createNewFile();
// 将字符串data写入文件
FileOutputStream fout = new FileOutputStream(file);
PrintStream ps = new PrintStream(fout);
ps.println(data);
ps.close();
}
catch (Exception e)
{
Tools.Log("字符串写入文件出错!");
}
}
// --------------------------------------------------坐标变换、点、矩形碰撞检测------------------------------------------------
/** 坐标系变换:左上、左下坐标系,y坐标变换 */
public static float coordinateTrans(float y, float height)
{
return HlgeConfig.CONF_SCREEN_HEIGHT - y - height;
}
/** 二维坐标转化为一维坐标 */
public static int point2indexInArray(int i, int j, int columns)
{
i = i * columns + j;
return i < 0 ? 0 : i;
}
/** 点与矩形碰状,判断点(x,y)是否在矩形区域内 */
public static boolean isPointInRect(float x, float y, Rectangle Rect)
{
if (Rect == null) return false;
return Tools.isPointInRect(x, y, Rect.x, Rect.y, Rect.x + Rect.width, Rect.y + Rect.height);
}
/** 点与矩形碰状,判断点(x,y)是否在矩形区域内 */
public static boolean isPointInRect(float x, float y, float x1, float y1, float x2, float y2)
{
if (x2 > x1)
{
if (x > x2 || x < x1) return false;
}
else
{
if (x < x2 || x > x1) return false;
}
if (y2 > y1)
{
if (y > y2 || y < y1) return false;
}
else
{
if (y < y2 || y > y1) return false;
}
return true;
}
/** 判断点(x,y)是否在矩形rect 范围内 */
public static boolean isPointInRect(int X, int Y, short[] rect)
{
int w = rect[2];
int h = rect[3];
if ((w | h) < 0) return false;
int x = rect[0];
int y = rect[1];
if (X < x || Y < y) return false;
w += x;
h += y;
return ((w < x || w > X) && (h < y || h > Y));
}
/** 2个矩形是否相交 */
public static boolean isRectIntersect(int[] rect0, int[] rect1)
{
if (rect0 == null || rect1 == null) return false;
return !(rect0[0] > rect1[2] || rect1[0] > rect0[2] || rect0[1] > rect1[3] || rect1[1] > rect0[3]);
}
/** 2个矩形是否相交 */
public static boolean isRectIntersect(short[] rect0, short[] rect1)
{
if (rect0 == null || rect1 == null) return false;
return !(rect0[0] > rect1[2] || rect1[0] > rect0[2] || rect0[1] > rect1[3] || rect1[1] > rect0[3]);
}
/** 左下原点坐标系中,获取坐标(x, y)逆时针针旋转degree角度后的坐标 */
public static float[] rotate(float x, float y, float scalex, float scaley, float degree)
{
// 尺寸变化后的相对坐标
x *= scalex;
y *= scaley;
// 逆时针旋转degree角度后的相对坐标
degree %= 360;
if ((x != 0 || y != 0) && degree != 0)
{
float x2 = x, y2 = y;
double degree2 = -Math.PI * degree / 180;
x2 = (float) (x * Math.cos(degree2) + y * Math.sin(degree2));
y2 = (float) (y * Math.cos(degree2) - x * Math.sin(degree2));
return new float[] { x2, y2 };
}
else
return new float[] { x, y };
// Log.e(degree + "度,坐标值:", ""+ x + "," + y);
}
// -------------------------------------------------完整调用树、异常代码位置信息输出------------------------------------------------
/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的完整调用树 */
public static void StackTrace(String info)
{
StackTraceElement[] elem = Thread.currentThread().getStackTrace(); // 从当前位置,获取代码调用堆栈
for (StackTraceElement e : elem)
{
String str = info + " 位置:" + e.getClassName() + " -> " + e.getMethodName() + "() 行:" + e.getLineNumber();
Gdx.app.error(e.getFileName(), str); // 输出调用位置信息和提示信息
// Log.e(info, str);
// System.out.println(info + " " + str);
}
}
// 当try块出错时,给出当前代码位置的,出错提示信息
// try{}catch(Exception e){ Tools.Log("释放资源出错!"); }
/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的调用位置 */
public static void Log(String info)
{
StackTraceElement[] elem = Thread.currentThread().getStackTrace(); // 从当前位置,获取代码的堆栈追踪信息
StackTraceElement e = elem[3]; // 仅获取调用该函数的代码位置,不获取完整调用树
String str = info + " 位置:" + e.getClassName() + " -> " + e.getMethodName() + "() 行:" + e.getLineNumber();
Gdx.app.error(e.getFileName(), str); // 输出调用位置信息和提示信息
// Log.e(info, str);
// System.out.println(info + " " + str);
}
/** 在LogCat中输出提示信息info,并给出输出该信息在代码中的调用位置 */
public static String getClassName()
{
StackTraceElement[] elem = Thread.currentThread().getStackTrace(); // 从当前位置,获取代码的堆栈追踪信息
StackTraceElement e = elem[3]; // 仅获取调用该函数的代码位置,不获取完整调用树
String str = e.getClassName();
Gdx.app.error(e.getFileName(), str); // 输出调用位置信息和提示信息
return str;
// Log.e(info, str);
// System.out.println(info + " " + str);
}
// -------------------------------------------------------------------------------------------------
/** 获取对象e所在类名 */
public static void getClassName(Object e)
{
Log.i("类名:", e.getClass().toString());
// int i = 0;
// Log.i("类型:", ((Object)i).getClass().toString()); ;
// Log.i("类型:", e.getClass().getDeclaredFields()[0].getName());
}
public static void setAllComponentsName(Object e)
{
// 获取f对象对应类中的所有属性域
Field[] fields = e.getClass().getDeclaredFields();
for (int i = 0, len = fields.length; i < len; i++)
{
// 对于每个属性,获取属性名
String varName = fields[i].getName();
try
{
// 获取原来的访问控制权限
boolean accessFlag = fields[i].isAccessible();
// 修改访问控制权限
fields[i].setAccessible(true);
// 获取在对象f中属性fields[i]对应的对象中的变量 .get(e)
Object o = fields[i].get(e);
System.out.println("传入的对象中包含一个如下的变量: " + varName + " = " + o);
// 恢复访问控制权限
fields[i].setAccessible(accessFlag);
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}