/*
* Copyright (c) 2014-2015 Sean Liu.
*
* 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 com.github.baoti.pioneer.misc.util;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.CheckResult;
import com.github.baoti.pioneer.data.DataConstants;
import java.io.File;
import java.io.IOException;
import timber.log.Timber;
/**
* 图片相关
*
* Created by liuyedong on 15-1-6.
*/
public class ImageActions {
@CheckResult
public static Intent actionPickImage() {
return new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
@CheckResult
public static Intent actionPickImageFromInternal() {
return new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
}
@CheckResult
public static Uri pickedImage(int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || data == null) {
return null;
}
return data.getData();
}
private static boolean hasResolvedActivity(Context context, Intent intent) {
PackageManager packageManager = context.getPackageManager();
return intent.resolveActivity(packageManager) != null;
}
public static boolean isImageCaptureAvailable(Context context) {
return hasResolvedActivity(context, CaptureCompat.baseAction());
}
public static boolean isImageCropAvailable(Context context) {
return hasResolvedActivity(context, Crop.baseAction());
}
@CheckResult
public static File generateImageFile(Context context, String suffix) {
File imagesDir = IoUtils.fromPublicPath(context, DataConstants.Files.IMAGES);
return IoUtils.generateDatedFile(imagesDir, suffix, true);
}
@CheckResult
public static Intent actionCapture(Context context) throws IOException {
File outputImage = generateImageFile(context, ".jpg");
return CaptureCompat.actionCaptureImage(Uri.fromFile(outputImage));
}
@CheckResult
public static Uri capturedImage(Context context, ActivityRequestState requestState, int resultCode, Intent data) {
return CaptureCompat.getCapturedImage(context, requestState.getRequestIntent(), resultCode, data);
}
@CheckResult
public static Intent actionCrop(Context context, Uri image, int size) {
return actionCrop(context, image, 1, 1, size, size);
}
@CheckResult
public static Intent actionCrop(Context context, Uri image,
int aspectX, int aspectY, int outputX, int outputY) {
return Crop.actionCropImage(context, image, aspectX, aspectY, outputX, outputY);
}
@CheckResult
public static Uri croppedImage(Context context, ActivityRequestState requestState, int resultCode, Intent data) {
return Crop.getCroppedImage(context, requestState.getRequestIntent(), resultCode, data);
}
private static class Crop {
private static final String ACTION_CROP = "com.android.camera.action.CROP";
private static final String MIME_TYPE = "image/*";
private static final String RETURN_DATA = "return-data";
private static Intent baseAction() {
return new Intent(ACTION_CROP).setType(MIME_TYPE);
}
private static Intent actionCropImage(Context context, Uri image,
int aspectX, int aspectY, int outputX, int outputY) {
Intent intent = baseAction();
if (image != null) {
intent.setDataAndType(image, MIME_TYPE);
} else {
// NOT SUPPORTED!!!
intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MIME_TYPE);
}
intent.putExtra("crop", "true");
// aspectX aspectY 是宽高的比例
intent.putExtra("aspectX", aspectX);
intent.putExtra("aspectY", aspectY);
// outputX,outputY 是剪裁图片的宽高
intent.putExtra("outputX", outputX);
intent.putExtra("outputY", outputY);
intent.putExtra("noFaceDetection", true);
intent.putExtra("scale", true);
intent.putExtra("scaleUpIfNeeded", true); //剪裁区域太小去除黑边
intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(generateImageFile(context, ".jpg")));
intent.putExtra("return-data", false);
// intent.putExtra(RETURN_DATA, true);
return intent;
}
private static Uri getCroppedImage(Context context, Intent requestIntent, int resultCode, Intent data) {
if (resultCode != Activity.RESULT_OK || requestIntent == null) {
return null;
}
boolean returnData = requestIntent.getBooleanExtra(RETURN_DATA, false);
if (returnData && data == null) {
return null;
}
Uri output = requestIntent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
if (output != null) {
return output;
}
Bitmap bm = data.getParcelableExtra("data");
if (bm == null) {
return null;
}
try {
File dst = generateImageFile(context, ".jpg");
if (!IoUtils.saveBitmap(dst, bm, Bitmap.CompressFormat.JPEG, 80)) {
return null;
}
return Uri.fromFile(dst);
} finally {
bm.recycle();
}
}
}
private static class CaptureCompat {
private static Intent baseAction() {
return new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
}
private static Intent actionCaptureImage(Uri output) {
return baseAction().putExtra(MediaStore.EXTRA_OUTPUT, output);
}
private static Uri getCapturedImage(Context context, Intent requestIntent, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
Uri output = requestIntent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
Timber.d("getCapturedImage - [%s]", output);
File file = IoUtils.toFile(output);
if (file == null) {
return output;
}
if (file.length() == 0) {
Timber.w("Image file is empty");
return null;
}
return output;
// try {
// Timber.v("Image file's length: %s", file.length());
// Uri capturedUri = insertToMediaImages(context, file);
// if (capturedUri == null) {
// capturedUri = insertToMediaImagesCompat(context, file);
// }
// return capturedUri;
// } finally {
// if (!file.delete()) {
// Timber.w("Could not delete tmp image file: %s", file);
// }
// }
}
return null;
}
private static Uri insertToMediaImages(Context context, File file) {
Bitmap bm = null;
try {
// FIXME: process exif
bm = BitmapFactory.decodeFile(file.getAbsolutePath());
if (bm == null) {
Timber.w("Could not decode image: %s", file);
return null;
}
return Uri.parse(MediaStore.Images.Media.insertImage(
context.getContentResolver(),
bm,
"",
""));
} catch (Throwable e) {
Timber.w("Could not insert to media: %s", file);
return null;
} finally {
if (bm != null) {
bm.recycle();
}
}
}
private static Uri insertToMediaImagesCompat(Context context, File file) {
File cameraDirectory = IoUtils.getDCIMDirectory("Camera");
File dst = IoUtils.generateDatedFile(cameraDirectory, ".jpg");
if (IoUtils.copyFile(file, dst)) {
Uri uri = Uri.fromFile(dst);
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
mediaScanIntent.setData(uri);
context.sendBroadcast(mediaScanIntent);
return uri;
}
return null;
}
}
}