我有一个函数将文件(来自相机或图库的图片)发送到WebService。
我希望在发布之前减少fileUri
的图像大小(每个示例50%)。
该文件是图库或相机图像。
这是我的postFile
功能:
public static void postFile(Context context, String url, String fileUri, AsyncHttpResponseHandler responseHandler) {
if (myCookieStore == null)
{
myCookieStore = new PersistentCookieStore(context);
client.setCookieStore(myCookieStore);
}
File myFile = new File(Uri.parse(fileUri).getPath());
RequestParams params = new RequestParams();
try {
params.put("profile_picture", myFile);
} catch(FileNotFoundException e) {
Log.d("error", "error catch");
}
Log.d("absolute url", "" + "*" + getAbsoluteUrl(url) + "*");
client.post(context, getAbsoluteUrl(url), params, responseHandler);
}
我该怎么做?
答案 0 :(得分:5)
有这个库,可以将你的图像从mb压缩到kb,它非常强大,我已经使用了很多次,它的工作文件上传是超高速的。 link
代码段:compressedImageFile = Compressor.getDefault(this).compressToFile(actualImageFile);
它内部使用google webp格式,WebP是一种现代图像格式,可为网络上的图像提供卓越的无损和有损压缩。使用WebP,网站管理员和网络开发人员可以创建更小,更丰富的图像,使网络更快。
该库非常适合大小压缩,它做得非常好,基于我的观察的大型文件,如2mb up,但是有一些内存泄漏需要解决,我通过使用泄漏解决了我的问题金丝雀,虽然每个开发人员都应该使用它。总的来说,它非常棒,可以随心所欲地使用它。
答案 1 :(得分:1)
我在很多项目中都使用了这个代码,并且它总能给我带来好的结果,我记得如果我选择尺寸为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);
// you can use other than 400 as required width/height
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[] proj = { MediaStore.Images.Media.DATA };
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);
// we choose image from drive etc.
if (path == null)
path = getDocumentRealPathFromUri(context, contentUri);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return path;
}
如果我们从驱动器等选择图片,我们仍然需要一个给定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) {
// raw height and width of image
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;
// calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
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,可以使用位图转换为流并将其发送到您的服务器。
答案 2 :(得分:0)
尝试此功能。如果位图的宽度或高度大于512,它会将位图的大小减小到512
public static Bitmap resizeBitmap(Bitmap bm) {
if (bm.getWidth() > maxSize || bm.getHeight() > maxSize) {
if (bm.getWidth() > bm.getHeight()) {
newWidth = maxSize;
newHeight = (bm.getHeight() * maxSize) / bm.getWidth();
bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
return bm;
} else {
newHeight = maxSize;
newWidth = (bm.getWidth() * maxSize) / bm.getHeight();
bm = Bitmap.createScaledBitmap(bm, newHeight, newWidth, true);
return bm;
}
}
return bm;
}
您只需将位图传递给此方法。
从URI获取位图的方法是
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
bitmap = BitmapFactory.decodeFile(fileUri.getPath(),
options);
答案 3 :(得分:0)
使用此图片更改图像宽度和高度
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}
你可以用这个来改变大小...这是最好的例子......
private Bitmap decodeFile(File f){
try {
//Decode image size
BitmapFactory.Options o = new BitmapFactory.Options();
o.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(f),null,o);
//The new size we want to scale to
final int REQUIRED_SIZE=70;
//Find the correct scale value. It should be the power of 2.
int scale=1;
while(o.outWidth/scale/2>=REQUIRED_SIZE && o.outHeight/scale/2>=REQUIRED_SIZE)
scale*=2;
//Decode with inSampleSize
BitmapFactory.Options o2 = new BitmapFactory.Options();
o2.inSampleSize=scale;
return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
} catch (FileNotFoundException e) {}
return null;
}
答案 4 :(得分:0)
如果摄像机图像是JPEG,则可以使用位图压缩方法,如:
Bitmap bitmap = BitmapFactory.decodeStream(...uri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
int compression_factor = 50; // represents 50% compression
bitmap.compress(Bitmap.CompressFormat.JPEG, compression_factor, baos);
byte[] image = baos.toByteArray();
// now update web service asynchronously...
...
} finally {
baos.close();
}
答案 5 :(得分:0)
将图像转换为位图,然后使用以下方法
public static Bitmap scaleBitmap(Bitmap bitmap, int newWidth, int newHeight) {
Bitmap scaledBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
float scaleX = newWidth / (float) bitmap.getWidth();
float scaleY = newHeight / (float) bitmap.getHeight();
float pivotX = 0;
float pivotY = 0;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(scaleX, scaleY, pivotX, pivotY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bitmap, 0, 0, new Paint(Paint.FILTER_BITMAP_FLAG));
return scaledBitmap;
}