/* * Copyright (C) 2016 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.large; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Point; import android.graphics.Rect; import android.os.Build; import java.io.IOException; import java.io.InputStream; import me.xiaopan.sketch.Configuration; import me.xiaopan.sketch.Sketch; import me.xiaopan.sketch.decode.DataSource; import me.xiaopan.sketch.decode.DataSourceFactory; import me.xiaopan.sketch.decode.DecodeException; import me.xiaopan.sketch.decode.DefaultImageDecoder; import me.xiaopan.sketch.decode.ImageType; import me.xiaopan.sketch.feature.ImageOrientationCorrector; import me.xiaopan.sketch.request.UriScheme; import me.xiaopan.sketch.util.SketchUtils; /** * 图片碎片解码器,支持纠正图片方向 */ public class ImageRegionDecoder { private final int imageOrientation; // 顺时针方向将图片旋转多少度能回正 private Point imageSize; private String imageUri; private ImageType imageType; private BitmapRegionDecoder regionDecoder; ImageRegionDecoder(String imageUri, Point imageSize, ImageType imageType, int imageOrientation, BitmapRegionDecoder regionDecoder) { this.imageUri = imageUri; this.imageSize = imageSize; this.imageType = imageType; this.imageOrientation = imageOrientation; this.regionDecoder = regionDecoder; } public static ImageRegionDecoder build(Context context, final String imageUri, final boolean correctImageOrientation) throws DecodeException, IOException { UriScheme uriScheme = UriScheme.valueOfUri(imageUri); if (uriScheme == null) { throw new IllegalArgumentException("Unknown scheme uri: " + imageUri); } DataSource dataSource = DataSourceFactory.makeDataSource(context, imageUri, uriScheme, uriScheme.crop(imageUri), null, "ImageRegionDecoder"); // 读取图片尺寸和类型 BitmapFactory.Options boundOptions = new BitmapFactory.Options(); boundOptions.inJustDecodeBounds = true; DefaultImageDecoder.decodeBitmap(dataSource, boundOptions); Point imageSize = new Point(boundOptions.outWidth, boundOptions.outHeight); // 读取图片方向并根据方向改变尺寸 Configuration configuration = Sketch.with(context).getConfiguration(); int imageOrientation = 0; ImageOrientationCorrector orientationCorrector = configuration.getImageOrientationCorrector(); if (correctImageOrientation) { imageOrientation = orientationCorrector.readImageRotateDegrees(boundOptions.outMimeType, dataSource); } if (imageOrientation != 0) { orientationCorrector.rotateSize(imageSize, imageOrientation); } InputStream inputStream = null; BitmapRegionDecoder regionDecoder; try { inputStream = dataSource.getInputStream(); regionDecoder = BitmapRegionDecoder.newInstance(inputStream, false); } finally { SketchUtils.close(inputStream); } ImageType imageType = ImageType.valueOfMimeType(boundOptions.outMimeType); return new ImageRegionDecoder(imageUri, imageSize, imageType, imageOrientation, regionDecoder); } @SuppressWarnings("unused") public Point getImageSize() { return imageSize; } public ImageType getImageType() { return imageType; } @SuppressWarnings("unused") public String getImageUri() { return imageUri; } public int getImageOrientation() { return imageOrientation; } @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) public boolean isReady() { return regionDecoder != null && !regionDecoder.isRecycled(); } @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) public void recycle() { if (isReady()) { regionDecoder.recycle(); regionDecoder = null; } } @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1) public Bitmap decodeRegion(Rect srcRect, BitmapFactory.Options options) { if (isReady()) { return regionDecoder.decodeRegion(srcRect, options); } else { return null; } } }