version:
bugfixes: update:去掉ocr目录
This commit is contained in:
@@ -147,14 +147,14 @@ public class SelectToSpeakService extends AccessibilityService {
|
||||
if (mCurrentStep != Step.FIND_CONTACT) {
|
||||
mCurrentStep = Step.CLICK_CONTACT;
|
||||
}
|
||||
break;
|
||||
case "com.tencent.mm.plugin.label.ui.ContactLabelManagerUI":
|
||||
|
||||
break;
|
||||
case "com.tencent.mm.plugin.account.ui.WelcomeActivity":
|
||||
case "com.tencent.mm.plugin.account.ui.LoginPasswordUI":
|
||||
Toaster.showLong("请先登录微信");
|
||||
mCurrentStep = Step.WAITING;
|
||||
break;
|
||||
case "com.tencent.mm.plugin.label.ui.ContactLabelManagerUI":
|
||||
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
@@ -137,6 +137,7 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
|
||||
// } else {
|
||||
startService(intent);
|
||||
// }
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +152,7 @@ public class CallWechatActivity extends BaseMvvmActivity<CallWechatViewModel, Ac
|
||||
intent.putExtra("WechatInfo", mContact);
|
||||
intent.putExtra("call_type", SelectToSpeakService.TYPE_VOICE);
|
||||
startService(intent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.vscool.os.ocr.paddle;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class OCRPredictorNative {
|
||||
|
||||
private static final AtomicBoolean isSOLoaded = new AtomicBoolean();
|
||||
|
||||
public static void loadLibrary() throws RuntimeException {
|
||||
if (!isSOLoaded.get() && isSOLoaded.compareAndSet(false, true)) {
|
||||
try {
|
||||
System.loadLibrary("Native");
|
||||
} catch (Throwable e) {
|
||||
RuntimeException exception = new RuntimeException(
|
||||
"Load libNative.so failed, please check it exists in apk file.", e);
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Config config;
|
||||
|
||||
private long nativePointer = 0;
|
||||
|
||||
public OCRPredictorNative(Config config) {
|
||||
this.config = config;
|
||||
loadLibrary();
|
||||
nativePointer = init(config.detModelFilename, config.recModelFilename, config.clsModelFilename, config.useOpencl,
|
||||
config.cpuThreadNum, config.cpuPower);
|
||||
Log.i("OCRPredictorNative", "load success " + nativePointer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ArrayList<OcrResultModel> runImage(Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec) {
|
||||
Log.i("OCRPredictorNative", "begin to run image ");
|
||||
float[] rawResults = forward(nativePointer, originalImage, max_size_len, run_det, run_cls, run_rec);
|
||||
ArrayList<OcrResultModel> results = postprocess(rawResults);
|
||||
return results;
|
||||
}
|
||||
|
||||
public static class Config {
|
||||
public int useOpencl;
|
||||
public int cpuThreadNum;
|
||||
public String cpuPower;
|
||||
public String detModelFilename;
|
||||
public String recModelFilename;
|
||||
public String clsModelFilename;
|
||||
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if (nativePointer != 0) {
|
||||
release(nativePointer);
|
||||
nativePointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected native long init(String detModelPath, String recModelPath, String clsModelPath, int useOpencl, int threadNum, String cpuMode);
|
||||
|
||||
protected native float[] forward(long pointer, Bitmap originalImage, int max_size_len, int run_det, int run_cls, int run_rec);
|
||||
|
||||
protected native void release(long pointer);
|
||||
|
||||
private ArrayList<OcrResultModel> postprocess(float[] raw) {
|
||||
ArrayList<OcrResultModel> results = new ArrayList<OcrResultModel>();
|
||||
int begin = 0;
|
||||
|
||||
while (begin < raw.length) {
|
||||
int point_num = Math.round(raw[begin]);
|
||||
int word_num = Math.round(raw[begin + 1]);
|
||||
OcrResultModel res = parse(raw, begin + 2, point_num, word_num);
|
||||
begin += 2 + 1 + point_num * 2 + word_num + 2;
|
||||
results.add(res);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private OcrResultModel parse(float[] raw, int begin, int pointNum, int wordNum) {
|
||||
int current = begin;
|
||||
OcrResultModel res = new OcrResultModel();
|
||||
res.setConfidence(raw[current]);
|
||||
current++;
|
||||
for (int i = 0; i < pointNum; i++) {
|
||||
res.addPoints(Math.round(raw[current + i * 2]), Math.round(raw[current + i * 2 + 1]));
|
||||
}
|
||||
current += (pointNum * 2);
|
||||
for (int i = 0; i < wordNum; i++) {
|
||||
int index = Math.round(raw[current + i]);
|
||||
res.addWordIndex(index);
|
||||
}
|
||||
current += wordNum;
|
||||
res.setClsIdx(raw[current]);
|
||||
res.setClsConfidence(raw[current + 1]);
|
||||
Log.i("OCRPredictorNative", "word finished " + wordNum);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package com.vscool.os.ocr.paddle;
|
||||
|
||||
import android.graphics.Point;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class OcrResultModel {
|
||||
private List<Point> points;
|
||||
private List<Integer> wordIndex;
|
||||
private String label;
|
||||
private float confidence;
|
||||
private float cls_idx;
|
||||
private String cls_label;
|
||||
private float cls_confidence;
|
||||
|
||||
public OcrResultModel() {
|
||||
super();
|
||||
points = new ArrayList<>();
|
||||
wordIndex = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addPoints(int x, int y) {
|
||||
Point point = new Point(x, y);
|
||||
points.add(point);
|
||||
}
|
||||
|
||||
public void addWordIndex(int index) {
|
||||
wordIndex.add(index);
|
||||
}
|
||||
|
||||
public List<Point> getPoints() {
|
||||
return points;
|
||||
}
|
||||
|
||||
public List<Integer> getWordIndex() {
|
||||
return wordIndex;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public float getConfidence() {
|
||||
return confidence;
|
||||
}
|
||||
|
||||
public void setConfidence(float confidence) {
|
||||
this.confidence = confidence;
|
||||
}
|
||||
|
||||
public float getClsIdx() {
|
||||
return cls_idx;
|
||||
}
|
||||
|
||||
public void setClsIdx(float idx) {
|
||||
this.cls_idx = idx;
|
||||
}
|
||||
|
||||
public String getClsLabel() {
|
||||
return cls_label;
|
||||
}
|
||||
|
||||
public void setClsLabel(String label) {
|
||||
this.cls_label = label;
|
||||
}
|
||||
|
||||
public float getClsConfidence() {
|
||||
return cls_confidence;
|
||||
}
|
||||
|
||||
public void setClsConfidence(float confidence) {
|
||||
this.cls_confidence = confidence;
|
||||
}
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
package com.vscool.os.ocr.paddle;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
public class Predictor {
|
||||
private static final String TAG = Predictor.class.getSimpleName();
|
||||
public boolean isLoaded = false;
|
||||
public int warmupIterNum = 1;
|
||||
public int inferIterNum = 1;
|
||||
public int cpuThreadNum = 6;
|
||||
public String cpuPowerMode = "LITE_POWER_HIGH";
|
||||
public String modelPath = "";
|
||||
public String modelName = "";
|
||||
protected OCRPredictorNative paddlePredictor = null;
|
||||
protected float inferenceTime = 0;
|
||||
// Only for object detection
|
||||
protected Vector<String> wordLabels = new Vector<String>();
|
||||
protected int detLongSize = 960;
|
||||
protected float scoreThreshold = 0.1f;
|
||||
protected Bitmap inputImage = null;
|
||||
protected Bitmap outputImage = null;
|
||||
protected volatile String outputResult = "";
|
||||
protected float postprocessTime = 0;
|
||||
protected ArrayList<OcrResultModel> mOcrResultModels;
|
||||
|
||||
public Predictor() {
|
||||
}
|
||||
|
||||
public boolean init(Context appCtx, String modelPath, String labelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode) {
|
||||
isLoaded = loadModel(appCtx, modelPath, useOpencl, cpuThreadNum, cpuPowerMode);
|
||||
if (!isLoaded) {
|
||||
return false;
|
||||
}
|
||||
isLoaded = loadLabel(appCtx, labelPath);
|
||||
return isLoaded;
|
||||
}
|
||||
|
||||
|
||||
public boolean init(Context appCtx, String modelPath, String labelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode,
|
||||
int detLongSize, float scoreThreshold) {
|
||||
boolean isLoaded = init(appCtx, modelPath, labelPath, useOpencl, cpuThreadNum, cpuPowerMode);
|
||||
if (!isLoaded) {
|
||||
return false;
|
||||
}
|
||||
this.detLongSize = detLongSize;
|
||||
this.scoreThreshold = scoreThreshold;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean loadModel(Context appCtx, String modelPath, int useOpencl, int cpuThreadNum, String cpuPowerMode) {
|
||||
// Release model if exists
|
||||
releaseModel();
|
||||
|
||||
// Load model
|
||||
if (modelPath.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String realPath = modelPath;
|
||||
if (!modelPath.substring(0, 1).equals("/")) {
|
||||
// Read model files from custom path if the first character of mode path is '/'
|
||||
// otherwise copy model to cache from assets
|
||||
realPath = appCtx.getCacheDir() + "/" + modelPath;
|
||||
Utils.copyDirectoryFromAssets(appCtx, modelPath, realPath);
|
||||
}
|
||||
if (realPath.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OCRPredictorNative.Config config = new OCRPredictorNative.Config();
|
||||
config.useOpencl = useOpencl;
|
||||
config.cpuThreadNum = cpuThreadNum;
|
||||
config.cpuPower = cpuPowerMode;
|
||||
config.detModelFilename = realPath + File.separator + "det_db.nb";
|
||||
config.recModelFilename = realPath + File.separator + "rec_crnn.nb";
|
||||
config.clsModelFilename = realPath + File.separator + "cls.nb";
|
||||
Log.i("Predictor", "model path" + config.detModelFilename + " ; " + config.recModelFilename + ";" + config.clsModelFilename);
|
||||
paddlePredictor = new OCRPredictorNative(config);
|
||||
|
||||
this.cpuThreadNum = cpuThreadNum;
|
||||
this.cpuPowerMode = cpuPowerMode;
|
||||
this.modelPath = realPath;
|
||||
this.modelName = realPath.substring(realPath.lastIndexOf("/") + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void releaseModel() {
|
||||
if (paddlePredictor != null) {
|
||||
paddlePredictor.destroy();
|
||||
paddlePredictor = null;
|
||||
}
|
||||
isLoaded = false;
|
||||
cpuThreadNum = 1;
|
||||
cpuPowerMode = "LITE_POWER_HIGH";
|
||||
modelPath = "";
|
||||
modelName = "";
|
||||
}
|
||||
|
||||
protected boolean loadLabel(Context appCtx, String labelPath) {
|
||||
wordLabels.clear();
|
||||
wordLabels.add("black");
|
||||
// Load word labels from file
|
||||
try {
|
||||
InputStream assetsInputStream = appCtx.getAssets().open(labelPath);
|
||||
int available = assetsInputStream.available();
|
||||
byte[] lines = new byte[available];
|
||||
assetsInputStream.read(lines);
|
||||
assetsInputStream.close();
|
||||
String words = new String(lines);
|
||||
String[] contents = words.split("\n");
|
||||
for (String content : contents) {
|
||||
wordLabels.add(content);
|
||||
}
|
||||
wordLabels.add(" ");
|
||||
Log.i(TAG, "Word label size: " + wordLabels.size());
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean runModel(int run_det, int run_cls, int run_rec) {
|
||||
if (inputImage == null || !isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
Log.d(TAG, "runModel: " + inputImage.getWidth() + "x" + inputImage.getHeight());
|
||||
// Warm up
|
||||
for (int i = 0; i < warmupIterNum; i++) {
|
||||
paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec);
|
||||
}
|
||||
warmupIterNum = 0; // do not need warm
|
||||
// Run inference
|
||||
Date start = new Date();
|
||||
ArrayList<OcrResultModel> results = paddlePredictor.runImage(inputImage, detLongSize, run_det, run_cls, run_rec);
|
||||
Date end = new Date();
|
||||
inferenceTime = (end.getTime() - start.getTime()) / (float) inferIterNum;
|
||||
|
||||
results = postprocess(results);
|
||||
mOcrResultModels = results;
|
||||
Log.i(TAG, "[stat] Inference Time: " + inferenceTime + " ;Box Size " + results.size());
|
||||
drawResults(results);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public ArrayList<OcrResultModel> getOcrResultModels() {
|
||||
return mOcrResultModels;
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return paddlePredictor != null && isLoaded;
|
||||
}
|
||||
|
||||
public String modelPath() {
|
||||
return modelPath;
|
||||
}
|
||||
|
||||
public String modelName() {
|
||||
return modelName;
|
||||
}
|
||||
|
||||
public int cpuThreadNum() {
|
||||
return cpuThreadNum;
|
||||
}
|
||||
|
||||
public String cpuPowerMode() {
|
||||
return cpuPowerMode;
|
||||
}
|
||||
|
||||
public float inferenceTime() {
|
||||
return inferenceTime;
|
||||
}
|
||||
|
||||
public Bitmap inputImage() {
|
||||
return inputImage;
|
||||
}
|
||||
|
||||
public Bitmap outputImage() {
|
||||
return outputImage;
|
||||
}
|
||||
|
||||
public String outputResult() {
|
||||
return outputResult;
|
||||
}
|
||||
|
||||
public float postprocessTime() {
|
||||
return postprocessTime;
|
||||
}
|
||||
|
||||
|
||||
public void setInputImage(Bitmap image) {
|
||||
if (image == null) {
|
||||
return;
|
||||
}
|
||||
this.inputImage = image.copy(Bitmap.Config.ARGB_8888, true);
|
||||
}
|
||||
|
||||
private ArrayList<OcrResultModel> postprocess(ArrayList<OcrResultModel> results) {
|
||||
for (OcrResultModel r : results) {
|
||||
StringBuffer word = new StringBuffer();
|
||||
for (int index : r.getWordIndex()) {
|
||||
if (index >= 0 && index < wordLabels.size()) {
|
||||
word.append(wordLabels.get(index));
|
||||
} else {
|
||||
Log.e(TAG, "Word index is not in label list:" + index);
|
||||
word.append("×");
|
||||
}
|
||||
}
|
||||
r.setLabel(word.toString());
|
||||
r.setClsLabel(r.getClsIdx() == 1 ? "180" : "0");
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private void drawResults(ArrayList<OcrResultModel> results) {
|
||||
StringBuffer outputResultSb = new StringBuffer("");
|
||||
for (int i = 0; i < results.size(); i++) {
|
||||
OcrResultModel result = results.get(i);
|
||||
StringBuilder sb = new StringBuilder("");
|
||||
if (result.getPoints().size() > 0) {
|
||||
sb.append("Det: ");
|
||||
for (Point p : result.getPoints()) {
|
||||
sb.append("(").append(p.x).append(",").append(p.y).append(") ");
|
||||
}
|
||||
}
|
||||
if (result.getLabel().length() > 0) {
|
||||
sb.append("\n Rec: ").append(result.getLabel());
|
||||
sb.append(",").append(result.getConfidence());
|
||||
}
|
||||
if (result.getClsIdx() != -1) {
|
||||
sb.append(" Cls: ").append(result.getClsLabel());
|
||||
sb.append(",").append(result.getClsConfidence());
|
||||
}
|
||||
Log.i(TAG, sb.toString()); // show LOG in Logcat panel
|
||||
outputResultSb.append(i + 1).append(": ").append(sb.toString()).append("\n");
|
||||
}
|
||||
outputResult = outputResultSb.toString();
|
||||
outputImage = inputImage;
|
||||
Canvas canvas = new Canvas(outputImage);
|
||||
Paint paintFillAlpha = new Paint();
|
||||
paintFillAlpha.setStyle(Paint.Style.FILL);
|
||||
paintFillAlpha.setColor(Color.parseColor("#3B85F5"));
|
||||
paintFillAlpha.setAlpha(50);
|
||||
|
||||
Paint paint = new Paint();
|
||||
paint.setColor(Color.parseColor("#3B85F5"));
|
||||
paint.setStrokeWidth(5);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
|
||||
for (OcrResultModel result : results) {
|
||||
Path path = new Path();
|
||||
List<Point> points = result.getPoints();
|
||||
if (points.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
path.moveTo(points.get(0).x, points.get(0).y);
|
||||
for (int i = points.size() - 1; i >= 0; i--) {
|
||||
Point p = points.get(i);
|
||||
path.lineTo(p.x, p.y);
|
||||
}
|
||||
canvas.drawPath(path, paint);
|
||||
canvas.drawPath(path, paintFillAlpha);
|
||||
}
|
||||
Log.d(TAG, "drawResults: " + outputImage.getWidth() + "x" + outputImage.getHeight());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
package com.vscool.os.ocr.paddle;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.media.ExifInterface;
|
||||
import android.os.Environment;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Utils {
|
||||
private static final String TAG = Utils.class.getSimpleName();
|
||||
|
||||
public static void copyFileFromAssets(Context appCtx, String srcPath, String dstPath) {
|
||||
if (srcPath.isEmpty() || dstPath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
is = new BufferedInputStream(appCtx.getAssets().open(srcPath));
|
||||
os = new BufferedOutputStream(new FileOutputStream(new File(dstPath)));
|
||||
byte[] buffer = new byte[1024];
|
||||
int length = 0;
|
||||
while ((length = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, length);
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
os.close();
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyDirectoryFromAssets(Context appCtx, String srcDir, String dstDir) {
|
||||
if (srcDir.isEmpty() || dstDir.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (!new File(dstDir).exists()) {
|
||||
new File(dstDir).mkdirs();
|
||||
}
|
||||
for (String fileName : appCtx.getAssets().list(srcDir)) {
|
||||
String srcSubPath = srcDir + File.separator + fileName;
|
||||
String dstSubPath = dstDir + File.separator + fileName;
|
||||
if (new File(srcSubPath).isDirectory()) {
|
||||
copyDirectoryFromAssets(appCtx, srcSubPath, dstSubPath);
|
||||
} else {
|
||||
copyFileFromAssets(appCtx, srcSubPath, dstSubPath);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static float[] parseFloatsFromString(String string, String delimiter) {
|
||||
String[] pieces = string.trim().toLowerCase().split(delimiter);
|
||||
float[] floats = new float[pieces.length];
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
floats[i] = Float.parseFloat(pieces[i].trim());
|
||||
}
|
||||
return floats;
|
||||
}
|
||||
|
||||
public static long[] parseLongsFromString(String string, String delimiter) {
|
||||
String[] pieces = string.trim().toLowerCase().split(delimiter);
|
||||
long[] longs = new long[pieces.length];
|
||||
for (int i = 0; i < pieces.length; i++) {
|
||||
longs[i] = Long.parseLong(pieces[i].trim());
|
||||
}
|
||||
return longs;
|
||||
}
|
||||
|
||||
public static String getSDCardDirectory() {
|
||||
return Environment.getExternalStorageDirectory().getAbsolutePath();
|
||||
}
|
||||
|
||||
public static boolean isSupportedNPU() {
|
||||
return false;
|
||||
// String hardware = android.os.Build.HARDWARE;
|
||||
// return hardware.equalsIgnoreCase("kirin810") || hardware.equalsIgnoreCase("kirin990");
|
||||
}
|
||||
|
||||
public static Bitmap resizeWithStep(Bitmap bitmap, int maxLength, int step) {
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
int maxWH = Math.max(width, height);
|
||||
float ratio = 1;
|
||||
int newWidth = width;
|
||||
int newHeight = height;
|
||||
if (maxWH > maxLength) {
|
||||
ratio = maxLength * 1.0f / maxWH;
|
||||
newWidth = (int) Math.floor(ratio * width);
|
||||
newHeight = (int) Math.floor(ratio * height);
|
||||
}
|
||||
|
||||
newWidth = newWidth - newWidth % step;
|
||||
if (newWidth == 0) {
|
||||
newWidth = step;
|
||||
}
|
||||
newHeight = newHeight - newHeight % step;
|
||||
if (newHeight == 0) {
|
||||
newHeight = step;
|
||||
}
|
||||
return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true);
|
||||
}
|
||||
|
||||
public static Bitmap rotateBitmap(Bitmap bitmap, int orientation) {
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
switch (orientation) {
|
||||
case ExifInterface.ORIENTATION_NORMAL:
|
||||
return bitmap;
|
||||
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
|
||||
matrix.setScale(-1, 1);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_180:
|
||||
matrix.setRotate(180);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
|
||||
matrix.setRotate(180);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_TRANSPOSE:
|
||||
matrix.setRotate(90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_90:
|
||||
matrix.setRotate(90);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_TRANSVERSE:
|
||||
matrix.setRotate(-90);
|
||||
matrix.postScale(-1, 1);
|
||||
break;
|
||||
case ExifInterface.ORIENTATION_ROTATE_270:
|
||||
matrix.setRotate(-90);
|
||||
break;
|
||||
default:
|
||||
return bitmap;
|
||||
}
|
||||
try {
|
||||
Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
bitmap.recycle();
|
||||
return bmRotated;
|
||||
} catch (OutOfMemoryError e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user