/*
* Copyright (C) 2017 Peng fei Pan <sky@xiaopan.me>
*
* 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 me.xiaopan.sketch.feature;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import java.io.IOException;
import java.io.InputStream;
import me.xiaopan.sketch.Identifier;
import me.xiaopan.sketch.cache.BitmapPool;
import me.xiaopan.sketch.decode.DataSource;
import me.xiaopan.sketch.decode.DecodeResult;
import me.xiaopan.sketch.decode.ImageType;
import me.xiaopan.sketch.drawable.ImageAttrs;
import me.xiaopan.sketch.process.RotateImageProcessor;
import me.xiaopan.sketch.util.ExifInterface;
import me.xiaopan.sketch.util.SketchUtils;
/**
* 图片方向纠正器,可让原本被旋转了的图片以正常方向显示
*/
public class ImageOrientationCorrector implements Identifier {
/**
* 根据mimeType判断该类型的图片是否支持通过ExitInterface读取旋转角度
*
* @param mimeType 从图片文件中取出的图片的mimeTye
*/
public boolean support(String mimeType) {
return ImageType.JPEG.getMimeType().equalsIgnoreCase(mimeType);
}
/**
* 读取图片旋转角度
*
* @param inputStream 文件输入流
* @return 图片旋转度数
*/
public int readImageRotateDegrees(InputStream inputStream) throws IOException {
ExifInterface exifInterface = new ExifInterface(inputStream);
int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return 90;
case ExifInterface.ORIENTATION_ROTATE_180:
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
return 180;
case ExifInterface.ORIENTATION_ROTATE_270:
return 270;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
case ExifInterface.ORIENTATION_TRANSPOSE:
case ExifInterface.ORIENTATION_TRANSVERSE:
case ExifInterface.ORIENTATION_UNDEFINED:
case ExifInterface.ORIENTATION_NORMAL:
default:
return 0;
}
}
/**
* 读取图片旋转角度
*
* @param mimeType 图片的类型,某些类型不支持读取旋转角度,需要过滤掉,免得浪费精力
* @param inputStream 输入流
* @return 图片旋转角度
*/
@SuppressWarnings("unused")
public int readImageRotateDegrees(String mimeType, InputStream inputStream) throws IOException {
if (!support(mimeType)) {
return 0;
}
return readImageRotateDegrees(inputStream);
}
/**
* 读取图片旋转角度
*
* @param mimeType 图片的类型,某些类型不支持读取旋转角度,需要过滤掉,免得浪费精力
* @param dataSource DataSource
* @return 图片旋转角度
*/
public int readImageRotateDegrees(String mimeType, DataSource dataSource) {
if (!support(mimeType)) {
return 0;
}
InputStream inputStream = null;
try {
inputStream = dataSource.getInputStream();
return readImageRotateDegrees(inputStream);
} catch (IOException e) {
e.printStackTrace();
return 0;
} finally {
SketchUtils.close(inputStream);
}
}
public Bitmap rotate(Bitmap bitmap, int rotateDegrees, BitmapPool bitmapPool) {
return RotateImageProcessor.rotate(bitmap, rotateDegrees, bitmapPool);
}
public void rotateSize(DecodeResult result, int rotateDegrees) {
ImageAttrs imageAttrs = result.getImageAttrs();
Matrix matrix = new Matrix();
matrix.setRotate(rotateDegrees);
RectF dstR = new RectF(0, 0, imageAttrs.getOriginWidth(), imageAttrs.getOriginHeight());
RectF deviceR = new RectF();
matrix.mapRect(deviceR, dstR);
imageAttrs.resetSize((int) deviceR.width(), (int) deviceR.height());
}
public void rotateSize(Point size, int rotateDegrees) {
Matrix matrix = new Matrix();
matrix.setRotate(rotateDegrees);
RectF dstR = new RectF(0, 0, size.x, size.y);
RectF deviceR = new RectF();
matrix.mapRect(deviceR, dstR);
size.x = (int) deviceR.width();
size.y = (int) deviceR.height();
}
/**
* @param rotateDegrees 顺时针方向将图片旋转多少度能回正
*/
@SuppressWarnings("SuspiciousNameCombination")
public void reverseRotate(Rect srcRect, Point imageSize, int rotateDegrees) {
rotateDegrees = 360 - rotateDegrees;
if (rotateDegrees == 90) {
int top = srcRect.top;
srcRect.top = srcRect.left;
srcRect.left = imageSize.y - srcRect.bottom;
srcRect.bottom = srcRect.right;
srcRect.right = imageSize.y - top;
} else if (rotateDegrees == 180) {
int left = srcRect.left, top = srcRect.top;
srcRect.left = imageSize.x - srcRect.right;
srcRect.right = imageSize.x - left;
srcRect.top = imageSize.y - srcRect.bottom;
srcRect.bottom = imageSize.y - top;
} else if (rotateDegrees == 270) {
int left = srcRect.left;
srcRect.left = srcRect.top;
srcRect.top = imageSize.x - srcRect.right;
srcRect.right = srcRect.bottom;
srcRect.bottom = imageSize.x - left;
}
}
@Override
public String getKey() {
return "ImageOrientationCorrector";
}
}