How to Upload Bitmap Images with Retrofit? - android

In my App i need to enable the user to upload 6 images as max from gallery after resize the images to Bitmaps, i have finished the selecting and resizing part successfully as shown below code and store the results in array of bitmaps imageslist .
My question is How to upload my bitmaps array using Retrofit MultipartBody ?? all the topics of Retrofit talking about file upload via file path like the answer of this question which i can't upload the files directly before resize
Retrofit Uploading multiple images to a single key
This is my code :
private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
if (maxHeight > 0 && maxWidth > 0) {
int width = image.getWidth();
int height = image.getHeight();
float ratioBitmap = (float) width / (float) height;
float ratioMax = (float) maxWidth / (float) maxHeight;
int finalWidth = maxWidth;
int finalHeight = maxHeight;
if (ratioMax > 1) {
finalWidth = (int) ((float)maxHeight * ratioBitmap);
} else {
finalHeight = (int) ((float)maxWidth / ratioBitmap);
}
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
return image;
} else {
return image;
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ConstantsCustomGallery.REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
//The array list has the image paths of the selected images
ArrayList<Image> images = data.getParcelableArrayListExtra(ConstantsCustomGallery.INTENT_EXTRA_IMAGES);
for (int i = 0; i < images.size(); i++) {
Uri uri = Uri.fromFile(new File(images.get(i).path));
Bitmap bm = BitmapFactory.decodeFile(images.get(i).path);
Bitmap resized = resize(bm,512,512);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
// ignore below line
//String encodedImage = Base64.encodeToString(byteArrayOutputStream.toByteArray(), Base64.DEFAULT);
imageslist.add(resized);
// ignore below lines
//TextSliderView textSliderView = new TextSliderView(uploadimages.this);
//textSliderView.image(new File(images.get(i).path));
//mslider.addSlider(textSliderView);
}
}
Any help will be much appreciated

Related

How to resize bitmap image with createdScaleBitmap and without blur

I want to capture image from camera and store it in sqlite. I resize it before saving.
I use this code it is work but i get a blurring image when i get a fullscreen image wen i display it.
public Bitmap resizeBitmap(Bitmap bitmap) {
int reqWidth = 900;
int reqHeight = 900;
RequestSizeOptions options = null;
try {
if (reqWidth > 0 && reqHeight > 0 && (options == RequestSizeOptions.RESIZE_FIT ||options == RequestSizeOptions.RESIZE_INSIDE || options == RequestSizeOptions.RESIZE_EXACT || options ==RequestSizeOptions.RESIZE_CENTRE_CROP)) {
Bitmap resized = null;
if (options == RequestSizeOptions.RESIZE_EXACT) {
resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false);
} else {
int width = bitmap.getWidth();
int height = bitmap.getHeight();
float scale = Math.max(width / (float) reqWidth, height / (float) reqHeight);
if (scale > 1 || options == RequestSizeOptions.RESIZE_FIT) {
resized = Bitmap.createScaledBitmap(bitmap, (int) (width / scale), (int) (height / scale), false);
}
if (scale > 1 || options == RequestSizeOptions.RESIZE_CENTRE_CROP) {
int smaller_side = (height-width)>0?width:height;
int half_smaller_side = smaller_side/2;
Rect initialRect = new Rect(0,0,width,height);
Rect finalRect = new Rect(initialRect.centerX()-half_smaller_side,initialRect.centerY()-half_smaller_side,
initialRect.centerX()+half_smaller_side,initialRect.centerY()+half_smaller_side);
bitmap = Bitmap.createBitmap(bitmap, finalRect.left, finalRect.top, finalRect.width(), finalRect.height(), null, true);
//keep in mind we have square as request for cropping, otherwise - it is useless
resized = Bitmap.createScaledBitmap(bitmap, reqWidth, reqHeight, false);
}
}
if (resized != null) {
if (resized != bitmap) {
bitmap.recycle();
}
return resized;
}
}
} catch (Exception e) {
Log.w("AIC", "Failed to resize cropped image, return bitmap before resize", e);
}
return bitmap;
This is the code, i use resize in this function. these function are in model class.
this.image = bitmapToString(resizeBitmap(image));
private static String bitmapToString(Bitmap bitmap) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
byte[] b = baos.toByteArray();
return Base64.encodeToString(b, Base64.DEFAULT);
}
the camera intent
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(takePictureIntent, 1);
NB: I save a image in sqlite and i display it on fullsceen.

How to send recently saved picture to ImageView?

I have the camera up and running, and saving the picture to my phone, but I now want to display it in an ImageView that I have set up, and then once more every time the app is launched after that. Any suggestions on how I can expand upon what I already have to achieve this?
My camera code is as follows:
private void takePic() {
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File pictureDirectory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
String pictureName = "Avatar.jpg";
File imageFile = new File(pictureDirectory, pictureName);
Uri pictureUri = Uri.fromFile(imageFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
And I have a button that simply calls on takePic(). I had an onActivityResult() before that looked like this:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
AvatarMe.setImageBitmap(photo);
}
}
I used this to simply display the thumbnail in my ImageView, but when I modified the code to save the picture I had to remove it, otherwise the app would crash. It seems Android won't let me do both, so I need some help to figure out how I can do that.
So basically I want to take a picture, display it in my ImageView, and save it so that if the app is killed after the picture has been taken I can just fill the ImageView with the saved picture.
You can do it with picasso library.
In your onActivityResult() data is coming from intent but you have to save into internal storage and show in imageview, have look.
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE)
{
if (resultCode == Activity.RESULT_OK)
{
Bitmap bmp = (Bitmap)data.getExtras().get("data");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
//saving image into internal storage
File myfile = new File(Environment.getExternalStorageDirectory(),"yourfilename.jpg");
FileOutputStream fo;
try {
myfile.createNewFile();
fo = new FileOutputStream(myfile);
fo.write(byteArray);
fo.flush();
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// convert byte array to Bitmap
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0,
byteArray.length);
imageView.setImageBitmap(bitmap);
}
}
}
Happy coding!!
you can use picasso library or you can my approach that i use that compress tha image and this ImageCompression class
`
private Context context;
float maxHeight;
float maxWidth;
boolean wantSave;
public ImageCompression(Context context) {
this.context = context;
}
public ImageCompression(Context context, float maxHeight, float maxWidth, boolean wantSave) {
this.context = context;
this.maxHeight = maxHeight;
this.maxWidth = maxWidth;
this.wantSave = wantSave;
}
#Override
protected Bitmap doInBackground(String... strings) {
if (strings.length == 0 || strings[0] == null)
return null;
return compressImage(strings[0]);
}
protected void onPostExecute(Bitmap imagePath) {
// imagePath is path of new compressed image.
}
public Bitmap compressImage(String imagePath) {
// to check if image is exist or not
File checkFile = new File(imagePath);
if (!checkFile.exists()) {
return null;
}
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile(imagePath, options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float imgRatio = (float) actualWidth / (float) actualHeight;
float maxRatio = maxWidth / maxHeight;
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;
}
}
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try {
bmp = BitmapFactory.decodeFile(imagePath, options);
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565);
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);
if (bmp != null) {
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
bmp.recycle();
}
ExifInterface exif;
try {
exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6) {
matrix.postRotate(90);
} else if (orientation == 3) {
matrix.postRotate(180);
} else if (orientation == 8) {
matrix.postRotate(270);
}
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
} catch (IOException e) {
e.printStackTrace();
}
// these lines from 144 to 157 for save the new photo
if (wantSave) {
FileOutputStream out = null;
String filepath = imagePath;
try {
out = new FileOutputStream(filepath);
//write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
return scaledBitmap;
} catch (OutOfMemoryError exception) {
exception.printStackTrace();
}
return null;
}
public static int calculateInSampleSize(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 heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
inSampleSize++;
}
return inSampleSize;
}
}
then in onActivityResult call
ImageCompression imageCompression = new ImageCompression(context, imageHeight, imageHeight, false) {
#Override
protected void onPostExecute(Bitmap bitmab) {
super.onPostExecute(bitmab);
try {
if (imagePath != null) {
mCropImageView.setImageBitmap(bitmab);
}
} catch (OutOfMemoryError error) {
Toast.makeText(CropImageActivity.this, "OutOfMemory, no space", Toast.LENGTH_SHORT).show();
}
}
};
imageCompression.execute(imagePath);
i hope this will help
The "data" from the camera intent is null in this case. You can check this answer.
To solve this problem, you will have to make the uri you passed to the camera intent global.
//make this a global variable
Uri pictureUri = Uri.fromFile(imageFile);
then you can access the bitmap like this
void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
{
Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), pictureUri);
AvatarMe.setImageBitmap(bitmap);
}
}
You can also store the pictureUri using a db or shared preference and reuse it later.

Base64 conversion is showing huge string android

I am converting image to Base64 to send it to the server, But the converted string is a huge string. If the converted image is ~100kb then the converted base64 value string is ~1mb...
My code...
protected String doInBackground(Void...arg0) {
Cursor cursor = mydb.getDat1();
//fetching the image location
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
for( int i=0 ; i< 1 ; i++ )
{
if( cursor.getColumnName(i) != null )
{
try
{
if( cursor.getString(i) != null )
{
//saving image to bitmap
Bitmap bitmap = BitmapFactory.decodeFile(cursor.getString(cursor.getColumnIndex(DBHelper.PHOTO)));
//converting it to base64
String en= encodeToBase64( resize(bitmap,1080,1920), Bitmap.CompressFormat.JPEG,100);
Log.d("base",en);
//inserting it to table pic
mydb.insertpic(cursor.getInt(1),en);
}
}
catch( Exception ignored)
{
}
}
}
cursor.moveToNext();
}
cursor.close();
mydb.updatebin();
return null;
}
private static Bitmap resize(Bitmap image, int maxWidth, int maxHeight) {
//for conerting images to lower resolution
if (maxHeight > 0 && maxWidth > 0) {
int width = image.getWidth();
int height = image.getHeight();
float ratioBitmap = (float) width / (float) height;
float ratioMax = (float) maxWidth / (float) maxHeight;
int finalWidth = maxWidth;
int finalHeight = maxHeight;
if (ratioMax > 1) {
finalWidth = (int) ((float)maxHeight * ratioBitmap);
} else {
finalHeight = (int) ((float)maxWidth / ratioBitmap);
}
image = Bitmap.createScaledBitmap(image, finalWidth, finalHeight, true);
return image;
} else {
return image;
}
}
public static String encodeToBase64(Bitmap image, Bitmap.CompressFormat compressFormat, int quality)
{
//converting image to base 64
ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
image.compress(compressFormat, quality, byteArrayOS);
return Base64.encodeToString(byteArrayOS.toByteArray(), Base64.DEFAULT);
}
How can i resolve this issue.?
This is the code:
Code to fetch image :
if (requestCode == TAKE_PHOTO_CODE && resultCode == RESULT_OK) {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
final Bitmap selectedImage = BitmapFactory.decodeStream(imageStream);
String encodedImage = encodeImage(selectedImage);
}
Try to compress and then convert(Bitmap)
private String encodeImage(Bitmap bm)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG,100,baos);
byte[] b = baos.toByteArray();
String encImage = Base64.encodeToString(b, Base64.DEFAULT);
return encImage;
}
My guess is that the encondeToBase64() is creating a large image file, since you resize the original image to 1920x1080 and convert to a jpeg with quality 100, and then the file then grows around 1.333... times in size when you convert to base64.

just a part of base64 decoded image is displaying

I want to post a bitmap to server by decoding base64. But after decoding I can display just a part of image(some top of image). How can I solve this problem?
I won't write codes for posting because they are work succesfully. In bitmapToString function I can get base64 strings and I try to display them, but I can see only a part of images.
Codes:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode==GALLERY_REQUEST) && resultCode == RESULT_OK) {
Uri selectedImage = data.getData();
String[] filePathColumn = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String filePath = cursor.getString(columnIndex);
Bitmap bitmap = scaleBitmap(BitmapFactory.decodeFile(filePath), 512,512,360);
bitMapToString(bitmap); //this function logs the base64 strings
}
}
}
public String bitmapToString(Bitmap bitmap){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String result = Base64.encodeToString(imageBytes, Base64.DEFAULT);
Log.d("BitmapToString",result); //here I get base64 strings
return result;
}
public Bitmap scaleBitmap(Bitmap bm, int maxWidth, int maxHeight, int ifSquareMaxValue) {
int width = bm.getWidth();
int height = bm.getHeight();
if(maxWidth>width && maxHeight>height)
return bm;
if (width > height) {
float ratio = (float) width / maxHeight;
width = maxHeight;
height = (int)(height / ratio);
} else if (height > width) {
float ratio = (float) height / maxWidth;
height = maxWidth;
width = (int)(width / ratio);
} else {
height = ifSquareMaxValue;
width = ifSquareMaxValue;
}
return Bitmap.createScaledBitmap(bm, width, height, true);
}
for example, a base64 string of an image is this: (from bitmapToString function line: Log.d("BitmapToString",result);)
/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAIAAgADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD/AD/6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiij/P8AP3+n5nnjk/r9O/8AXe+oBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUf1+aXXy/PVtNs/r80uvl+erabZRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAd58L/AOsfFH4geFvh9oKhtW8UaiNO08Mu5TMYLicZXemfkhbjeMEkk8HP9YnwW/wCDe/x+nwPurzx34dtLrxZcLp9zZXC2saBYJo72RvkN9IWyDBzvHfINfzI/so+NtN8B/HL4deIb+FGGmeIFuRMxdRGPsl4mdwOF+9wf9o85Jr/Ry/ZZ/ahi+MXgvTNT03WI3sorTTrZ4Y51dSRBLEM5XdkeSfzIyCDn+PPpSeJniJ4fQyJ8KU6NDK8TSnUzDH1cPKo44uOKlChSjONaM4QqQi+aNrNWbd7X8nMcdXwn8OCalFrnaTUZczSe+mi0ttpd3+L/AD0/2z/2UfFn7M3xS8Q+FNYsjbQaYVX5YDGgIkdTgiWQdlx83oODnd8T1/oQ/wDBWn9hrRP2h/gvquseFNLtbXxddPeSSarCqyXToDaugZZJNoA2vjjJDNknrX8D/wATfh9q3wz8Z674Q1WGdZ9FuhbSTSxFBIxQNkY+X+IcKe+OQhz+keAXi9g/FHhKjUxFWnDPsujHD5lheZKcvZKnT+uRjd2pV6k24RcpTSS5noaZZjY4uhr/ABIWUldX3kr23Sb2W+/Rtrz6iiiv3s9IKKKKACiiigAoooo07/1t3/ru3qAUUUUf1+S7+n3rrqwKKKKP6/Pzfb89XZ3AooooAKKKKACgAk4HJ/8A1j19v5c85JW74a8Pal4p1e30bSbae7vbjPkwW0TzTPtYD5Y1BZjz27k9zzE5xpwnOclGMIuUpSdoqK5rybvokkm30XNu1qrqz12/4K2+X/Bu039E/slfsuePv2r/AIoW/wAN/AVr52rSG1fD27Spsle57ebEM4hb+Pjuck5/pq+Iv/Bv14s0n4E6PreneGraLxJa6Jd3er3Bt0y0kM0z7sfbOP3SLjk985JJr75/4Iif8E/dO+Dfwx8IftG+LNLgXULyJI5ra7RIL5TBHIQXh84Trk3J6pyd3OcZ/SH9rT9oy08F+EvEvm6pHa2C6XfrFavMqL5YhkBjXIyQx4A7kgAEg5/zm8XfpLcW4jxDjwt4cVsPLCZZiqeFxFV0ZV/rOYQqzo4qjzQqQcoR9nzRjblV37zd2/ncVm1RValDDKL+GLk4uXvKck7WfTftsrttt/5oHxv+C/iX4K+LtT8O+Io1jkg1G4tYwqbB+6MhIx5snQDjk9eTkivFK+4v25PjNoXxd+J2qXOjWK2v2DWLwTuvmkTMFkiLZkHO5jn5eOOpAr4dr+/OFcVmmO4eyzFZzRWHzGthKE8VS5VFRqOMnpFSduZe9a7a5o3be/vUJTlSTqfFZX9fe835fhvYKKKK+gNQooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigCWCea1lSe3kaKaM7o5EJDo2GGVIPBwx9eDj1J/oZ/4JIft06j4A1LQ/hJr15LLa6lcrI+o3kyuY1gmuQBkhpAMXJwFB6LkE4J/nhrsPAvjTVvh/4js/E2jOwvrLPk4kaMfMyk5YB8Y2DHynnr0zXxHiBwTlnH3C+ZcP5lRp1FiKUpYac1rSxcYVo4etGV1b2cpqdneO3Mn7xz4nDxxFGdOXVaPzvKz017O1+iWrd3/qWeB/F2g+OdBRGktdVsLiN1RmUyRN5iuMhWTPYHpnBPJ21/JZ/wWm/4J83Hgff8U/AdhJrE/iS+F7fW2nxMv2SJbyCBi4nkjTasQ8whCTjPVjtr7w/4JZftu6Z8RvA3hrwhrGsq3icLG09mHVyA6yBf3hVGb/Vn+DqMd81+z/xZ8EeG/jh8OtW0TWUjuH/sXUIrQG3jlzM8UrIAC64y4UZBJBzwDnd/lfw7mHEv0efFScK0K6wlDGRo4zDz5408xy5VakaM2rL3W/3qlSavb4mtH8jSnVy7FO6aimk1Zq6TlZ9VrdfLrrKR/l33drPZXVxZ3MbRT20jRSxtjcjoWDK2CRkYHQ/3upGDXr9HP+ChP7Jmu/s4/Eu+a70p7K11/WLu4tGbcvmQyRyXCEKxbGVwcA4wRye/5zxRNLJ5YzuzgD1OSPfHT3/EkZ/1q4c4gy7iXJMDneXV4V8JjaFOrTqQkpK7TVRXjKXwSutXey1vJa/Y0asK1OM4u6aTv/4Ens+/L+Nm1dkf+f5j1Pp/PkkEk/H+fv6A+n6j0NfX3wU/YZ/aV+P8lsvws8EHXTd7PI/0iSPeHL4GFtZcZ2N+Wc9Sf2z/AGUv+DeH9prxzqcD/GT4ZXOk6XM8J86Ge4nPlkShztEdn0ZRkbucjnIzXnZzxzwvkVOtPHZthFOgr1MNSr0p4pWbTXsfaKV9NvXVtO/RClUqO0ISl0uk7fa3ey+G/wA11ufzMQWk106xW4Msjnakaj5mb5uBk4z8vr36k4z6PoPwT+LHijZ/wj/gfWNU342fZ1tfm64x5lynXHf2655/0Tvgf/wa1fsWW1hZar4/vNasNWhhim8n+y7mUGcl1cEnxNF0Ukg7MHBGOHNfqB8J/wDgij+xl8IRAPDs89ybbZs+0aICCU3jnfrc5/PuRzkHP4dnv0pfD/LI1aeCxlKtXp+7KljpLDNyTmuWK9tzPRdm229bu51QwFZ6TlSjtq5pPeS1Tej0Xfpp/N/lk6Z+xR+1nqqq2m/AvxfeK2NpiTSsEfNjhtRHoeR755OT1dt/wT1/bdutph/Zw8cyKccqmi9Mtzzq3ov/AOsnFf6/fhP9lb4R+CoY49F0jTLgRAbDLo1mPukgE7nl69ec/wAsewWPhHR9Lj8uz8L6CwQAAtpGncDc2M5tG/2+vTPUgc/mOI+mbgqc5xocNU8VCK0qYeeLqxau0neEnfbXotNbvXVYCCupVJX0s6cVJatq++u2nR+69Fdy/wAb1v8Agm9+28sRcfs4+OyQoIBXRs53Ec51fH5nkHGeAaw
when I use use in img tag display like this:
http://kombers.org/a.html

Xamarin forms android image is not getting compressed

I'm working on xamarin forms project. I'm taking images from gallery and uploading those to server. My back-end is parse backend where we can not upload files having size more than 1MB. So, I'm trying to compress the image so that every time the image size is less than 1MB.
Mentioned below is my code :-
protected override async void OnActivityResult (int requestCode, Result resultCode, Intent intent)
{
if (resultCode == Result.Canceled)
return;
try {
var mediafile = await intent.GetMediaFileExtraAsync (Forms.Context);
// get byte[] from file stream
byte[] byteData = ReadFully (mediafile.GetStream ());
byte[] resizedImage = ResizeAndCompressImage (byteData, 60, 60, mediafile);
var imageStream = new ByteArrayContent (resizedImage);
imageStream.Headers.ContentDisposition = new ContentDispositionHeaderValue ("attachment") {
FileName = Guid.NewGuid () + ".Png"
};
var multi = new MultipartContent ();
multi.Add (imageStream);
HealthcareProfessionalDataClass lDataClass = HealthcareProfessionalDataClass.Instance;
lDataClass.Thumbnail = multi;
App.mByteArrayOfImage = byteData;
MessagingCenter.Send<IPictureTaker,string> (this, "picturetaken", mediafile.Path);
} catch (InvocationTargetException e) {
e.PrintStackTrace ();
} catch (Java.Lang.Exception e) {
e.PrintStackTrace ();
}
}
public static byte[] ReadFully (System.IO.Stream input)
{
using (var ms = new MemoryStream ()) {
input.CopyTo (ms);
return ms.ToArray ();
}
}
public static byte[] ResizeAndCompressImage (byte[] imageData, float width, float height, MediaFile file)
{
try {
// Load the bitmap
var options = new BitmapFactory.Options ();
options.InJustDecodeBounds = true;
options.InMutable = true;
BitmapFactory.DecodeFile (file.Path, options);
// Calculate inSampleSize
options.InSampleSize = calculateInSampleSize (options, (int)width, (int)height);
// Decode bitmap with inSampleSize set
options.InJustDecodeBounds = false;
var originalBitMap = BitmapFactory.DecodeByteArray (imageData, 0, imageData.Length, options);
var resizedBitMap = Bitmap.CreateScaledBitmap (originalBitMap, (int)width, (int)height, false);
if (originalBitMap != null) {
originalBitMap.Recycle ();
originalBitMap = null;
}
using (var ms = new MemoryStream ()) {
resizedBitMap.Compress (Bitmap.CompressFormat.Png, 0, ms);
if (resizedBitMap != null) {
resizedBitMap.Recycle ();
resizedBitMap = null;
}
return ms.ToArray ();
}
} catch (Java.Lang.Exception e) {
e.PrintStackTrace ();
return null;
}
}
public static int calculateInSampleSize (BitmapFactory.Options options, int reqWidth, int reqHeight)
{
// Raw height and width of image
int height = options.OutHeight;
int width = options.OutWidth;
int inSampleSize = 16;
if (height > reqHeight || width > reqWidth) {
int halfHeight = height / 2;
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;
}
But the problem is my image is not getting compressed.I'm not able to upload an image having size = 2MB and I want to upload images having size at-least 30 MB. Also I've observed that calculateInSampleSize always returns 16 as inSampleSize which is default one.
Please let me know if there's any issue in my code.
This seems like a very complicated and convoluted way of doing it. Here's a more concise sample that should help you resize your images:
protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var stream = this.Resize(data.Data, 60, 60);
// Send the stream to Parse
}
private Stream Resize(Android.Net.Uri uri, float maxWidth, float maxHeight)
{
var scale = 1;
using (var rawStream = this.ContentResolver.OpenInputStream(f))
using (var options = new BitmapFactory.Options { InJustDecodeBounds = true })
{
BitmapFactory.DecodeStream(rawStream, null, options);
while(options.OutWidth / scale / 2 > maxWidth ||
options.OutHeight / scale / 2 > maxHeight)
{
scale *= 2;
}
}
using (var options = new BitmapFactory.Options { InSampleSize = scale })
using (var bitmap = f.GetBitmap(options))
{
var memoryStream = new MemoryStream();
bitmap.Compress(Bitmap.CompressFormat.Png, 0, memoryStream);
memoryStream.Position = 0;
return memoryStream;
}
}
Regarding why you are seeing InSampleSize = 16, my guess is that your image's height or width are less than 1920 (which is 60 * 2 * 16) and since you are using && in the while loop, the greater check for that side fails and thus, you never enter the while body.
Additionally, if you are looking to create smaller images, compressing them as Jpeg is a much better approach than using png's.

Categories

Resources