我在许多项目中都使用了这段代码,总是能够得到良好的结果。我记得如果我选择一个大小为5-7MB(来自12/13 MP相机)的图像,这段代码会返回一个大小为1MB或小于2MB的图像。
public static boolean validateUri(Uri uri) {
if (uri == null)
return false;
else {
String path = uri.getPath();
return !(uri.equals(Uri.EMPTY) || path == null || path.equals("null"));
}
}
首先我们需要一张完整的图片,如果需要则旋转。
public static Bitmap getFullSizeImage(Context context, Uri uri) {
String filePath;
if (validateUri(uri) && uri.toString().contains("file"))
filePath = uri.getPath();
else
filePath = getRealPathFromURI(context, uri, MediaStore.Images.Media.DATA);
if (filePath == null)
return null;
try {
int rotation = 0;
ExifInterface exifInterface = new ExifInterface(filePath);
int exifRotation = exifInterface.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED);
if (exifRotation != ExifInterface.ORIENTATION_UNDEFINED) {
switch (exifRotation) {
case ExifInterface.ORIENTATION_ROTATE_180:
rotation = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotation = 270;
break;
case ExifInterface.ORIENTATION_ROTATE_90:
rotation = 90;
break;
}
}
Matrix matrix = new Matrix();
matrix.setRotate(rotation);
Bitmap sourceBitmap = getBitmapFromPath(400, filePath);
if (sourceBitmap == null)
return null;
return Bitmap.createBitmap(sourceBitmap, 0, 0, sourceBitmap.getWidth(),
sourceBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
现在我们需要从URI获取真实路径。
public static String getRealPathFromURI(Context context, Uri contentUri, String type) {
Cursor cursor = null;
String path = null;
try {
String[] projection = {type};
cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor == null)
return null;
int columnIndex = cursor.getColumnIndexOrThrow(type);
cursor.moveToFirst();
path = cursor.getString(columnIndex);
if (path == null)
path = getDocumentRealPathFromUri(context, contentUri);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return path;
}
如果我们从Drive等地方选择一张图片,仍然需要给定URI的真实路径。
public static String getDocumentRealPathFromUri(Context context, Uri contentUri) {
Cursor cursor = context.getContentResolver().query(contentUri, null,
null, null, null);
if (cursor == null)
return null;
cursor.moveToFirst();
String documentId = cursor.getString(0);
documentId = documentId.substring(documentId.lastIndexOf(":") + 1);
cursor.close();
cursor = context.getContentResolver().query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
null, MediaStore.Images.Media._ID + " = ? ",
new String[]{documentId}, null);
if (cursor == null)
return null;
cursor.moveToFirst();
String path = cursor.getString(cursor
.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
return path;
}
现在我们有了所选图像的真实路径,因此我们可以使用样本大小从该路径获取位图。
public static Bitmap getBitmapFromPath(int size, String realPathFromURI) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(realPathFromURI, options);
options.inSampleSize = calculateInSampleSizeUsingPower2(options, size, size);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(realPathFromURI, options);
}
public static int calculateInSampleSizeUsingPower2(BitmapFactory.Options options, int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth)
inSampleSize *= 2;
}
return inSampleSize;
}
在此时,我们拥有一个压缩位图,如果对给定的位图执行Base64操作,我们可以再次压缩该位图。
public static String convertToBase64(Bitmap bitmap) {
if (bitmap == null)
return null;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
if (bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream)) {
String base64 = encodeToString(byteArrayOutputStream.toByteArray(), DEFAULT);
try {
byteArrayOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return base64;
}
return null;
}
在您的服务器端,您可以解码Base64并将其转换回文件流以保存您的图像。
示例。
Bitmap bitmap = getFullSizeImage(context, selectedPhotoUri);
if(bitmap != null){
String base64Image = convertToBase64(bitmap);
if (base64Image != null) {
RequestParams params = new RequestParams();
try {
params.put("title", "your_image_name");
params.put("profile_picture", base64Image);
} catch(FileNotFoundException e) {
Log.d("error", "error catch");
}
}
}
注意
如果您不想执行Base64,可以使用位图将其转换为流并将其发送到服务器。