Android 如何生成适当的缩放位图以更快地将其上载到服务器?
目前我正在使用Android 如何生成适当的缩放位图以更快地将其上载到服务器?,android,image-uploading,android-bitmap,Android,Image Uploading,Android Bitmap,目前我正在使用mulitpart/formdata将图像上传到服务器。在node.js服务器端,图像的存储没有任何问题。但是把照片上传到服务器上要花很多时间。我试图在上传位图之前重新缩放位图,但在大多数情况下,图片上传的大小都比原始图片的大小大,比如ex-200kb的图片会变成400kb的大小。所以,我想知道如何正确缩放位图,并以高效的速度将它们以高质量上传到服务器? 位图缩放代码: bmp = MediaStore.Images.Media.getBitmap(ctx.getContentRe
mulitpart/formdata
将图像上传到服务器。在node.js服务器端,图像的存储没有任何问题。但是把照片上传到服务器上要花很多时间。我试图在上传位图之前重新缩放位图,但在大多数情况下,图片上传的大小都比原始图片的大小大,比如ex-200kb的图片会变成400kb的大小。所以,我想知道如何正确缩放位图,并以高效的速度将它们以高质量上传到服务器?
位图缩放代码:
bmp = MediaStore.Images.Media.getBitmap(ctx.getContentResolver(), uri);
int maxSize=700;
int outWidth;
int outHeight;
int inWidth = bmp.getWidth();
int inHeight = bmp.getHeight();
if(inWidth > inHeight){
outWidth = maxSize;
outHeight = (inHeight * maxSize) / inWidth;
} else {
outHeight = maxSize;
outWidth = (inWidth * maxSize) / inHeight;
}
final Bitmap new_bitmap = Bitmap.createScaledBitmap(bmp, outWidth, outHeight, false);
正在将位图保存到存储器:
void saveImage(String imgName, Bitmap bm) throws IOException {
//Create Path to save Image
File file_path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + "/Infinity"); //Creates app specific folder
file_path.mkdirs();
File imageFile = new File(file_path, imgName + ".png"); // Imagename.png
FileOutputStream out = new FileOutputStream(imageFile);
try {
bm.compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image
out.flush();
out.close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.scanFile(ctx, new String[]{imageFile.getAbsolutePath()}, null, new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String pathi, Uri uri) {
Log.i("ExternalStorage", "Scanned " + file_path + ":");
Log.i("ExternalStorage", "-> uri=" + uri);
parts.add(prepareFilePart("photo", pathi));
RequestBody description = createPartFromString(obji.toString());
FileUploadService service = ServiceGenerator.createService(FileUploadService.class);
Call<ResponseBody> call = service.uploadMultipleFilesDynamic(description, parts);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call,
Response<ResponseBody> response) {
Log.v("Upload", "success");
Intent i=new Intent(ctx,Home_Screen.class);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NO_ANIMATION);
startActivity(i);
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if(t.getMessage()!=null) {
Log.e("Upload error:", t.getMessage());
Toast.makeText(ctx, t.getMessage(), Toast.LENGTH_LONG).show();
//Don't toast t.getMessage it would show the ip address which is bad
}
}
});
//Toast.makeText(ctx, "Downloaded Successfully", Toast.LENGTH_SHORT).show();
}
});
} catch (Exception e) {
throw new IOException();
}
}
void saveImage(字符串imgName,位图bm)引发IOException{
//创建保存图像的路径
File File_path=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+“/Infinity”);//创建特定于应用程序的文件夹
文件_path.mkdirs();
File imageFile=新文件(文件路径,imgName+“.png”);//Imagename.png
FileOutputStream out=新的FileOutputStream(imageFile);
试一试{
bm.compress(Bitmap.CompressFormat.PNG,100,out);//压缩图像
out.flush();
out.close();
//告诉媒体扫描程序有关新文件的信息,以便
//用户可立即使用。
MediaScannerConnection.scanFile(ctx,新字符串[]{imageFile.getAbsolutePath()},null,新MediaScannerConnection.OnScanCompletedListener(){
已完成的公共void(字符串路径,Uri){
Log.i(“外部存储”,“扫描”+文件路径+”:”;
Log.i(“外部存储”,“->uri=“+uri”);
添加(准备部分(“照片”,路径i));
RequestBody description=createPartFromString(obji.toString());
FileUploadService=ServiceGenerator.createService(FileUploadService.class);
Call Call=service.uploadMultipleFileDynamic(描述,部分);
call.enqueue(新回调(){
@凌驾
公共void onResponse(调用,
回应(回应){
Log.v(“上传”、“成功”);
意向i=新意向(ctx,主屏幕类);
i、 setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NO_动画);
星触觉(i);
}
@凌驾
失败时公共无效(调用调用,可丢弃的t){
如果(t.getMessage()!=null){
Log.e(“上传错误:,t.getMessage());
Toast.makeText(ctx,t.getMessage(),Toast.LENGTH_LONG.show();
//不要toast t.getMessage它将显示坏的ip地址
}
}
});
//Toast.makeText(ctx,“下载成功”,Toast.LENGTH_SHORT.show();
}
});
}捕获(例外e){
抛出新IOException();
}
}
这里有一种压缩图像的方法。首先将要压缩的图像路径发送到此方法。它将返回压缩图像路径,然后从该路径生成文件并上载
public static String compressImage(String filePath) {
try {
//String filePath = getRealPathFromURI(imageUri);
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
//by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
//you try the use the bitmap here, you will get null.
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(filePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
//max Height and width values of the compressed image is taken as 816x612
float maxHeight = 816.0f;
float maxWidth = 612.0f;
float imgRatio = actualWidth / actualHeight;
float maxRatio = maxWidth / maxHeight;
//width and height values are set maintaining the aspect ratio of the image
if (actualHeight > maxHeight || actualWidth > maxWidth) {
if (imgRatio < maxRatio) {
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
} else if (imgRatio > maxRatio) {
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
} else {
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
}
}
//setting inSampleSize value allows to load a scaled down version of the original image
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
//inJustDecodeBounds set to false to load the actual bitmap
options.inJustDecodeBounds = false;
//this options allow android to claim the bitmap memory if it runs low on memory
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
//load the bitmap from its path
bmp = BitmapFactory.decodeFile(filePath, options);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
try {
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
//check the rotation of the image and display it properly
ExifInterface exif;
try {
exif = new ExifInterface(filePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Log.d("EXIF", "Exif: " + orientation);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 3) {
matrix.postRotate(180);
Log.d("EXIF", "Exif: " + orientation);
} else if (orientation == 8) {
matrix.postRotate(270);
Log.d("EXIF", "Exif: " + orientation);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
true);
} catch (IOException e) {
e.printStackTrace();
}
FileOutputStream out = null;
//String filename = getFilename();
String filename = getFilename();
try {
out = new FileOutputStream(filename);
//write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return filename;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
公共静态字符串压缩图像(字符串文件路径){
试一试{
//字符串filePath=getRealPathFromURI(imageUri);
位图缩放位图=空;
BitmapFactory.Options=new-BitmapFactory.Options();
//通过将此字段设置为true,实际位图像素不会加载到内存中。只加载边界。如果
//如果您尝试在此处使用位图,将得到null。
options.inJustDecodeBounds=true;
位图bmp=BitmapFactory.decodeFile(文件路径,选项);
int实际高度=options.outHeight;
int actualWidth=options.outWidth;
//压缩图像的最大高度和宽度值为816x612
浮动最大高度=816.0f;
浮动最大宽度=612.0f;
浮动高度=实际宽度/实际高度;
浮点最大比值=最大宽度/最大高度;
//设置宽度和高度值以保持图像的纵横比
如果(实际高度>最大高度| |实际宽度>最大宽度){
if(imgRatiomaxRatio){
imgRatio=最大宽度/实际宽度;
实际高度=(int)(imgRatio*实际高度);
实际宽度=(int)最大宽度;
}否则{
实际高度=(int)最大高度;
实际宽度=(int)最大宽度;
}
}
//设置inSampleSize值允许加载原始图像的缩小版本
options.inSampleSize=calculateInSampleSize(选项、实际宽度、实际高度);
//inJustDecodeBounds设置为false以加载实际位图
options.inJustDecodeBounds=false;
//此选项允许android在内存不足时声明位图内存
options.inpurgable=true;
options.inInputShareable=true;
options.inTempStorage=新字节[16*1024];
试一试{
//从位图路径加载位图
bmp=BitmapFactory.decodeFile(文件路径,选项);
}捕获(OutOfMemoryError异常){
异常。printStackTrace();
}
试一试{
scaledbimat=Bitmap.createBitmap(实际宽度、实际高度、Bitmap.Config.ARGB_8888);
}捕获(OutOfMemoryError异常){
例外
private uploadPostImage(String imagePath) throws Exception {
String orientation = "Portrait";
Bitmap bm = null;
try {
bm = checkForRotation(imagePath);
if (bm.getHeight() > bm.getWidth()) {
orientation = "Portrait";
} else if (bm.getWidth() > bm.getHeight()) {
orientation = "Landscape";
} else {
orientation = "Portrait";
}
} catch (Exception e) {
Log.e(e.getClass().getName(), e.getMessage());
}
if(bm.getWidth()>1000)
{
bm = getResizedBitmap(bm,1000);
}
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte[] data = bos.toByteArray();
/*
/....
Multipart uploading work
..../
*/
} catch (Exception e) {
Log.e(e.getClass().getName(), e.getMessage());
}
}
public Bitmap checkForRotation(String filename) {
Bitmap bitmap = BitmapFactory.decodeFile(filename);
int tmpHeight, tmpWidth;
tmpWidth = bitmap.getWidth();
tmpHeight = bitmap.getHeight();
if (tmpWidth > tmpHeight)
{
tmpWidth = 1000;
tmpHeight = (bitmap.getHeight() * tmpWidth) / bitmap.getWidth();
} else
{
tmpHeight = 1000;
tmpWidth = (bitmap.getWidth() * tmpHeight) / bitmap.getHeight();
}
bitmap= Bitmap.createScaledBitmap(bitmap, tmpWidth, tmpHeight, true);
ExifInterface ei = null;
try {
ei = new ExifInterface(filename);
new ExifInterface(filename);
} catch (IOException e) {
e.printStackTrace();
}
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
bitmap = rotateImage(bitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
bitmap = rotateImage(bitmap, 180);
break;
}
return bitmap;
}
public Bitmap getResizedBitmap(Bitmap bm, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float ratio = (float)width/(float)height;
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float)newWidth/ratio) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// RECREATE THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height,
matrix, false);
return resizedBitmap;
}