我尝试了两种方法,但我发现这些方法在我的情况下花费的时间太长。我仍然分享我用过的东西。
方法 1:适用于 Android 的 LLJTran
从这里获取 LLJTran:
https://github.com/bkhall/AndroidMediaUtil
代码:
public static boolean rotateJpegFileBaseOnExifWithLLJTran(File imageFile, File outFile){
try {
int operation = 0;
int degree = getExifRotateDegree(imageFile.getAbsolutePath());
//int degree = 90;
switch(degree){
case 90:operation = LLJTran.ROT_90;break;
case 180:operation = LLJTran.ROT_180;break;
case 270:operation = LLJTran.ROT_270;break;
}
if (operation == 0){
Log.d(TAG, "Image orientation is already correct");
return false;
}
OutputStream output = null;
LLJTran llj = null;
try {
// Transform image
llj = new LLJTran(imageFile);
llj.read(LLJTran.READ_ALL, false); //don't know why setting second param to true will throw exception...
llj.transform(operation, LLJTran.OPT_DEFAULTS
| LLJTran.OPT_XFORM_ORIENTATION);
// write out file
output = new BufferedOutputStream(new FileOutputStream(outFile));
llj.save(output, LLJTran.OPT_WRITE_ALL);
return true;
} catch(Exception e){
e.printStackTrace();
return false;
}finally {
if(output != null)output.close();
if(llj != null)llj.freeMemory();
}
} catch (Exception e) {
// Unable to rotate image based on EXIF data
e.printStackTrace();
return false;
}
}
public static int getExifRotateDegree(String imagePath){
try {
ExifInterface exif;
exif = new ExifInterface(imagePath);
String orientstring = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientstring != null ? Integer.parseInt(orientstring) : ExifInterface.ORIENTATION_NORMAL;
if(orientation == ExifInterface.ORIENTATION_ROTATE_90)
return 90;
if(orientation == ExifInterface.ORIENTATION_ROTATE_180)
return 180;
if(orientation == ExifInterface.ORIENTATION_ROTATE_270)
return 270;
} catch (IOException e) {
e.printStackTrace();
}
return 0;
}
方法二:使用 libjepg-turbo 的 jpegtran 可执行文件
1 按照此处描述的步骤操作:
https://stackoverflow.com/a/12296343/1099884
除了你不需要ndk-build 上的obj/local/armeabi/libjpeg.a,因为我只想要 jpegtran 可执行文件,但不想用libjepg.a 与 JNI 混淆。
2 将 jpegtran 可执行文件放在资产文件夹中。
代码:
public static boolean rotateJpegFileBaseOnExifWithJpegTran(Context context, File imageFile, File outFile){
try {
int operation = 0;
int degree = getExifRotateDegree(imageFile.getAbsolutePath());
//int degree = 90;
String exe = prepareJpegTranExe(context);
//chmod ,otherwise premission denied
boolean ret = runCommand("chmod 777 "+exe);
if(ret == false){
Log.d(TAG, "chmod jpegTran failed");
return false;
}
//rotate the jpeg with jpegtran
ret = runCommand(exe+
" -rotate "+degree+" -outfile "+outFile.getAbsolutePath()+" "+imageFile.getAbsolutePath());
return ret;
} catch (Exception e) {
// Unable to rotate image based on EXIF data
e.printStackTrace();
return false;
}
}
public static String prepareJpegTranExe(Context context){
File exeDir = context.getDir("JpegTran", 0);
File exe = new File(exeDir, "jpegtran");
if(!exe.exists()){
try {
InputStream is = context.getAssets().open("jpegtran");
FileOutputStream os = new FileOutputStream(exe);
int bufferSize = 16384;
byte[] buffer = new byte[bufferSize];
int count;
while ((count=is.read(buffer, 0, bufferSize))!=-1) {
os.write(buffer, 0, count);
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return exe.getAbsolutePath();
}
public static boolean runCommand(String cmd){
try{
Process process = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
很遗憾,两者都需要很长时间。在我的三星 Galaxy S1 上是 16 秒!!!!但我发现这个应用程序 (https://play.google.com/store/apps/details?id=com.lunohod.jpegtool) 只需要 3-4 秒。一定有办法。