我的服务器限制上传图片的大小为2MB。我想从安卓设备上传图片到服务器,我需要调整图片大小。有什么最好的方法可以调整图片大小?
我的服务器限制上传图片的大小为2MB。我想从安卓设备上传图片到服务器,我需要调整图片大小。有什么最好的方法可以调整图片大小?
使用以下代码。使用“MAX_IMAGE_SIZE”指定您的最大文件大小(以千字节为单位)。在此代码中,首先我调整图像大小,然后压缩它。请参阅代码中的注释以更好地理解逻辑。
public static String resizeAndCompressImageBeforeSend(Context context,String filePath,String fileName){
final int MAX_IMAGE_SIZE = 700 * 1024; // max final file size in kilobytes
// First decode with inJustDecodeBounds=true to check dimensions of image
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath,options);
// Calculate inSampleSize(First we are going to resize the image to 800x800 image, in order to not have a big but very low quality image.
//resizing the image will already reduce the file size, but after resizing we will check the file size and start to compress image
options.inSampleSize = calculateInSampleSize(options, 800, 800);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.inPreferredConfig= Bitmap.Config.ARGB_8888;
Bitmap bmpPic = BitmapFactory.decodeFile(filePath,options);
int compressQuality = 100; // quality decreasing by 5 every loop.
int streamLength;
do{
ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
Log.d("compressBitmap", "Quality: " + compressQuality);
bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
byte[] bmpPicByteArray = bmpStream.toByteArray();
streamLength = bmpPicByteArray.length;
compressQuality -= 5;
Log.d("compressBitmap", "Size: " + streamLength/1024+" kb");
}while (streamLength >= MAX_IMAGE_SIZE);
try {
//save the resized and compressed file to disk cache
Log.d("compressBitmap","cacheDir: "+context.getCacheDir());
FileOutputStream bmpFile = new FileOutputStream(context.getCacheDir()+fileName);
bmpPic.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpFile);
bmpFile.flush();
bmpFile.close();
} catch (Exception e) {
Log.e("compressBitmap", "Error on saving file");
}
//return the path of resized and compressed file
return context.getCacheDir()+fileName;
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
String debugTag = "MemoryInformation";
// Image nin islenmeden onceki genislik ve yuksekligi
final int height = options.outHeight;
final int width = options.outWidth;
Log.d(debugTag,"image height: "+height+ "---image width: "+ width);
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;
}
}
Log.d(debugTag,"inSampleSize: "+inSampleSize);
return inSampleSize;
}
在将图像编码为字符串后,您还可以这样做:将其压缩并计算保存图像之前所需的长度。在这种情况下,如果图像太大,用户将被迫更改图像。我假设您已经对图像进行了编码。
long myBitmapLength = myEncodedImage.getBytes().length/1024;
if(myBitmapLength < 200){
//allow saving
}
修复图像分辨率和文件大小。
private const val TAG = "Compressor"
private const val START_QUALITY = 100
private const val QUALITY_DECREASE_STEP = 10
private const val DEFAULT_SIZE_LIMIT = 512_000
private const val MARGIN = 30
//image resolution 1024*768
private const val LONG_SIZE = 1024
private const val SHORT_SIZE = 768
object Compressor {
private val FORMAT = Bitmap.CompressFormat.JPEG
fun compressImage(
imageFile: File,
limitSize: Int = DEFAULT_SIZE_LIMIT,
watermark: String? = null
): String {
val originalBitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
val bitmapWithWaterMark = mark(originalBitmap, watermark)
val (newWidth, newHeight) = calculateNewWidthAndHeight(bitmapWithWaterMark)
val resizedBitmap = getResizedBitmap(bitmapWithWaterMark, newWidth, newHeight)
val stream = ByteArrayOutputStream()
var quality = START_QUALITY
//compressed Bitmap write to ByteArrayOutputStream
resizedBitmap.compress(FORMAT, quality, stream)
while (stream.size() > limitSize && quality > QUALITY_DECREASE_STEP) {
stream.reset()
quality -= QUALITY_DECREASE_STEP
resizedBitmap.compress(FORMAT, quality, stream)
}
val base64String = Base64.encodeToString(stream.toByteArray(), Base64.DEFAULT)
return base64String
}
private fun calculateNewWidthAndHeight(waterMarkBitmap: Bitmap): Pair<Int, Int> {
val newWidth = if (isPortrait(waterMarkBitmap)) SHORT_SIZE else LONG_SIZE
val newHeight = if (isPortrait(waterMarkBitmap)) LONG_SIZE else SHORT_SIZE
return Pair(newWidth, newHeight)
}
private fun isPortrait(bitmap: Bitmap) = bitmap.height > bitmap.width
private fun mark(source: Bitmap, watermark: String? = null): Bitmap {
if (watermark == null) return source
val width = source.width
val height = source.height
val result = Bitmap.createBitmap(width, height, source.config)
val canvas = Canvas(result)
canvas.drawBitmap(source, 0f, 0f, null)
val paint = getPaint(18)
val (widthPaint, heightPaint) = paint.getTextWidthAndHeight(watermark)
//watermark background
val backgroundPaint = getBackgroundPaint()
canvas.drawRect(
width - widthPaint - MARGIN,
height - heightPaint * 2,
width.toFloat(),
height.toFloat() - heightPaint + MARGIN,
backgroundPaint
)
//watermark text
canvas.drawText(
watermark,
width - widthPaint,
height - heightPaint,
paint
)
return result
}
private fun getBackgroundPaint(): Paint {
return Paint().apply {
style = Paint.Style.FILL
color = Color.BLACK
}
}
private fun dpToPx(dp: Int): Float {
return TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
dp.toFloat(),
App.resources.displayMetrics
)
}
private fun getPaint(textSize: Int, isShadowEnable: Boolean = false): Paint {
return Paint(Paint.ANTI_ALIAS_FLAG).apply {
setTextSize(dpToPx(textSize))
typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
if (isShadowEnable) {
setShadowLayer(2f, 2f, 2f, Color.BLACK)
}
color = Color.WHITE
textAlign = Paint.Align.LEFT
}
}
private fun Paint.getTextWidthAndHeight(text: String): Pair<Float, Float> {
val baseline = -this.ascent() // ascent() is negative
val width: Float = this.measureText(text) + dpToPx(8)
val height: Float = baseline + this.descent() + dpToPx(4)
return Pair(width, height)
}
private fun getResizedBitmap(bitmap: Bitmap, newWidth: Int, newHeight: Int): Bitmap {
val width = bitmap.width
val height = bitmap.height
val scaleWidth = newWidth.toFloat() / width
val scaleHeight = newHeight.toFloat() / height
// CREATE A MATRIX FOR THE MANIPULATION
val matrix = Matrix()
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight)
// "RECREATE" THE NEW BITMAP
val resizedBitmap = Bitmap.createBitmap(
bitmap, 0, 0, width, height, matrix, false
)
bitmap.recycle()
return resizedBitmap
}
}
Bitmap scaledBitmap = scaleDown(realImage, MAX_IMAGE_SIZE, true);
缩小比例方法:
public static Bitmap scaleDown(Bitmap realImage, float maxImageSize,
boolean filter) {
float ratio = Math.min(
(float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width,
height, filter);
return newBitmap;
}