I have an app where you can take a picture or select an image from the gallery.
The photo taken/selected once must be uploaded to the server.
My question is, as there are different devices with different sizes and resolutions, should the compressed image be loaded to the original size on the server or should it be scaled up and then compressed?
What is the best way for scale an image for all device?
Now I'm using this algorithm when user take a photo by the camera or by gallery
private void setPic() throws IOException {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, options);
// Calculate inSampleSize
int sampleSize = calculateInSampleSize(options, 720, 720);
Log.d("UserPanel", "Samplesize: " + sampleSize);
Log.d("SquareImage", ""+image.getWidth());
options.inSampleSize = sampleSize;
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.inPreferredConfig= Bitmap.Config.ARGB_8888;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, options);
Log.d("UserPanel", "Bytebitmap: " + bitmap.getByteCount());
ExifInterface exif = new ExifInterface(mCurrentPhotoPath);
String orientString = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
int orientation = orientString != null ? Integer.parseInt(orientString) : ExifInterface.ORIENTATION_NORMAL;
int rotationAngle = 0;
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) rotationAngle = 90;
if (orientation == ExifInterface.ORIENTATION_ROTATE_180) rotationAngle = 180;
if (orientation == ExifInterface.ORIENTATION_ROTATE_270) rotationAngle = 270;
Matrix matrix = new Matrix();
matrix.setRotate(rotationAngle, (float) bitmap.getWidth() / 2, (float) bitmap.getHeight() / 2);
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, options.outWidth, options.outHeight, matrix, true);
Log.d("UserPanel", "Bytebitmaprotate: " + rotatedBitmap.getByteCount());
MediaStore.Images.Media.insertImage(getContentResolver(), rotatedBitmap, imageFileName, "");
File fdelete = new File(mCurrentPhotoPath);
if (fdelete.delete()) Log.d("UserPanel", "Delete");
imageToServer = getStringImage(rotatedBitmap);
}
This is calculateSampleSize
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
Log.d("UserPanel", "Width: " + width + " height: " + height);
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;
}
To compress the image I fixed a size of 100KB
private String getStringImage(Bitmap bmp) {
int compressQuality = 100;
int streamLength = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
do{
ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
Log.d("compressBitmap", "Quality: " + compressQuality);
bmp.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
byte[] bmpPicByteArray = bmpStream.toByteArray();
streamLength = bmpPicByteArray.length;
compressQuality -= 5;
Log.d("compressBitmap", "Size: " + streamLength/1024+" kb");
}while (streamLength >= 100000);
bmp.compress(Bitmap.CompressFormat.JPEG, compressQuality, baos);
byte[] imageBytes = baos.toByteArray();
Log.d("UserPanel", "Bytebitmap compress: " + imageBytes.length);
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
return encodedImage;
}