How to reduce bitmap quality without affecting it's size - android

is there a way i can compress an image of 115kb to be 4kb in android Without affecting it size?. just reducing it quality?
i only know of using
BitmapFactory.Options which reduces both size and quality
Bitmap.compress which does not give you options for specifying size in bytes.
public Bitmap compressImage(String imagePath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
bmp = BitmapFactory.decodeStream(new FileInputStream(imagePath),null, options);
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
bmp = BitmapFactory.decodeStream(new FileInputStream(imagePath),null, options);
return bmp;
}
public 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;
}

Image re sizing means you're going to shorten the resolution of the image. suppose user selects a 1000*1000 px image. you're going to convert the image into a 300*300 image. thus image size will be reduced.
And Image compression is lowering the file size of the image without compromising the resolution. Of course lowering file size will affect the quality of the image. There are many compression algorithm available which can reduce the file size without much affecting the image quality.
One handy way I found in here is :
Bitmap original = BitmapFactory.decodeStream(getAssets().open("1024x768.jpg"));
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.PNG, 100, out);
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
Log.e("Original dimensions", original.getWidth()+" "+original.getHeight());
Log.e("Compressed dimensions", decoded.getWidth()+" "+decoded.getHeight());
gives
12-07 17:43:36.333: E/Original dimensions(278): 1024 768 12-07
17:43:36.333: E/Compressed dimensions(278): 1024 768

public static int getSquareCropDimensionForBitmap(Bitmap bitmap)
{
int dimension;
//If the bitmap is wider than it is tall
//use the height as the square crop dimension
if (bitmap.getWidth() >= bitmap.getHeight())
{
dimension = bitmap.getHeight();
}
//If the bitmap is taller than it is wide
//use the width as the square crop dimension
else
{
dimension = bitmap.getWidth();
}
return dimension;
}
int dimension = getSquareCropDimensionForBitmap(bitmap);
System.out.println("before cropped height " + bitmap.getHeight() + "and width: " + bitmap.getWidth());
Bitmap croppedBitmap = ThumbnailUtils.extractThumbnail(bitmap, dimension, dimension);
System.out.println("after cropped height "+croppedBitmap.getHeight() +"and width: " + croppedBitmap.getWidth());
it can crop and can reduce size u can specify ur own size

Related

How to set fullHD image to ImageView

I want to set a fullHD(1080x1920) image to ImageView.
I have searched but no efficient method.
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
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("DUE","Options height: " + height + " - 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;
}
}
return inSampleSize;
}
Or:
private Bitmap resize(int resId, int width, int height){
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId, bmpFactoryOptions);
int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height);
int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width);
if (heightRatio > 1 || widthRatio > 1)
{
if (heightRatio > widthRatio)
{
bmpFactoryOptions.inSampleSize = heightRatio;
} else {
bmpFactoryOptions.inSampleSize = widthRatio;
}
}else{
}
bmpFactoryOptions.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeResource(getResources(), resId, bmpFactoryOptions);
return bitmap;
}
I want to display the original image size, without reducing the size of image
Can you help me?
Thanks all!
You can use image loading libraries like Universal Image Loader, Fresco.
1) https://github.com/nostra13/Android-Universal-Image-Loader
2) https://github.com/facebook/fresco
3) https://guides.codepath.com/android/Displaying-Images-with-the-Fresco-Library
Both examples you posted are useful to reduce the image size (i.e. to save memory).
I want to display the original image size, without reducing the size of image
If you only want to set a image from resources, there are much simpler alternatives.
Assing the image in code to an ImageView:
ImageView img;
img.setImageResource(R.drawable.image);
Or create a Bitmap from your Resource:
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.image);
Or set your image in xml:
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/image"
android:scaleType="center"/>
you can use glide
Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.
full documantation
Downloading custom sizes with Glide allow to add hight & width of iamge
Glide's ModelLoader interface provides developers with the size of the view they are loading an image into and allows them to use that size to choose a url to download an appropriately sized version of the image.
Using appropriately sized image saves bandwidth, storage space on the device, and improves the performance of the app.

Load Image into map Marker using android

I am trying to add bitmap to google map marker icon.
Below is my code to add image to marker icon. Application is crashing because of bitmap size
Error : java.lang.IllegalArgumentException: Textures with dimensions4096x8192 are larger than the maximum supported size 4096x4096
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType=options.outMimeType;
if(imageWidth > imageHeight) {
options.inSampleSize = calculateInSampleSize(options,10,10);//if landscape
} else{
options.inSampleSize = calculateInSampleSize(options,10,10);//if portrait
}
options.inJustDecodeBounds = false;
Bitmap mapbitmap = BitmapFactory.decodeFile("/storage/emulated/0/Pictures/TAG_IMG_25.2571724_55.2994563.jpg", options);
latLng=new LatLng(25.254376, 55.2973058);
marker = googleMap.addMarker(new MarkerOptions()
.position(latLng)
.title(_title)
.snippet("dubai")
.icon(BitmapDescriptorFactory.fromBitmap(mapbitmap)));
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;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and width
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
Answer is in your question itself.
Textures with dimensions4096x8192 are larger than the maximum supported size 4096x4096
So you must reduce the image size below 4096x4096 using any image editors such as Photoshop.
if you are not familiar , Here is a tutorial.

Android Compress a Bitmap

I have wrote this method before I noticed there is a compress method in Bitmap class.
/**
* Calcuate how much to compress the image
* #param options
* #param reqWidth
* #param reqHeight
* #return
*/
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1; // default to not zoom image
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;
}
return inSampleSize;
}
/**
* resize image to 480x800
* #param filePath
* #return
*/
public static Bitmap getSmallBitmap(String filePath) {
File file = new File(filePath);
long originalSize = file.length();
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
// Calculate inSampleSize based on a preset ratio
options.inSampleSize = calculateInSampleSize(options, 480, 800);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap compressedImage = BitmapFactory.decodeFile(filePath, options);
return compressedImage;
}
I was wondering, compare to the built in Compress method, should I keep using this one, or switch to use the built in one? what is the difference?
Your method is in line with Loading Large Bitmap guidelines
Large file on disk
Small bitmap in memory
compress() methods converts a large bitmap to a small one:
Large bitmap in memory
Small bitmap on disk (IOStream) (and possibly in different format)
I would use your method if I needed to load bitmap from a file to ImageViews of different sizes.
Basically
What you are doing in the above code is just resizing the image ,which will not loose much of the quality of the image since you use the SampleSize .
compress(Bitmap.CompressFormat format, int quality, OutputStream stream)
It is used when you want to change the imageFormat you have Bitmap.CompressFormat JPEG
Bitmap.CompressFormat PNG Bitmap.CompressFormat WEBP or to reduce the quality of the image using the quality parameter 0 - 100 .

Is there difference between .jpg and .JPG for android?

I wonder if there is any difference between image extensions .jpg and .JPG. I encountered a problem in that .JPG images cannot be opened with the following code:
public static Bitmap decodeSampledBitmapFromResource(String path,
int reqWidth, int reqHeight) {
Log.e("PATH", path);
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// Calculate inSampleSizeŠ°
options.inSampleSize = calculateInSampleSize(options, reqWidth,
reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
Bitmap b = BitmapFactory.decodeFile(path, options);
if(b!=null){
Log.d("bitmap","decoded sucsessfully");
}else{
Log.d("bitmap","decoding failed; options: "+options.toString());
}
return b;
}
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;
int inSampleSize = 1;
Log.d("bitmap", "original options: height "+ height + " widnth "+width+" inSampleSize "+inSampleSize);
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
Log.d("bitmap", "options: height "+ height + " widnth "+width+" inSampleSize "+inSampleSize);
}
return inSampleSize;
}
If I call
decodeSampledBitmapFromResource(path, 80, 60)
on *.JPG image, the returned bitmap is null.
I'm asking if they are generally implemented in different way or it is specific for Galaxy S3? (I was not able to repeat it on Galaxy Tab 7.7 or on HTC phones.)
Android runs on Linux operating system, which is case sensitive.
If the file has the extension in lowercase, like this: ".jpg", so you should refer in the source code. If the file has the extension ".JPG", also, the same should be written in code.

Image decoded from Base64 is getting smaller than the normal image. [png]

I can successfully convert the given Base64 string to corresponding image in Android.
To test this scenario in my app, I took one image from my drawable folder and convert it into its corresponding Base64 string using this website : Motobit.com. The image that I gave on this website was this:
Its 23X25 pixels in dimension and 46.3KB in size.
Using below code in my Android I am converting this image's Base64 into Image as follows:
byte[] decodedString = Base64.decode(tabData.getString("TabIconImageData"), Base64.DEFAULT);
BitmapFactory.Options options = new Options();
options.inJustDecodeBounds = true;
options.inSampleSize = calculateInSampleSize(options, 500, 500);
options.inJustDecodeBounds = false;
Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length,options);
myImageView.setImageBitmap(decodedByte);
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;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
// Calculate ratios of height and width to requested height and
// width
final int heightRatio = Math.round((float) height
/ (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
// Choose the smallest ratio as inSampleSize value, this will
// guarantee
// a final image with both dimensions larger than or equal to the
// requested height and width.
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
}
The Base64 string is getting converted successfully in image, but it looks nealy half in the size than of its original image. I want the image of its original size and also in PNG format.
Please guide me for this to resolve.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
Bitmap btm = decodeBase64("Base64 String");
Bitmap bt=Bitmap.createScaledBitmap(btm, btm.getWidth(), btm.getHeight(), false);
company_logo.setImageBitmap(bt);
and this
public static Bitmap decodeBase64(String input)
{
byte[] decodedByte = Base64.decode(input, 0);
return BitmapFactory.decodeByteArray(decodedByte, 0, decodedByte.length);
}

Categories

Resources