Reputation: 451
I want to write my own code for compressing an image before I upload it to server.
I have seen many posts on SO like this and there are many other posts also but everywhere there are only code samples. It is not actually explained anywhere. I am not able to understand from the given code.
I just want to know about the overall approach to compress images so that I can start writing code by myself.
I am not looking for the code, only the steps that one person needs to follow to compress an image. (Like an algorithm is written before writing program i.e., pseudocode)
Upvotes: 4
Views: 4377
Reputation: 1165
You can just use the android sdk - bitmap.compress();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
if (myBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos)) {
//image is now compressed into the output stream
uploadImage(bos);
} else {
//compress failed
}
you can always check the android source code to learn more about it but if you are an android developer I think putting the time on learning how to compress shouldn't be your main focus specially when you have such an easy solution for it, if you still think you do I would've start by learning how does one compress files first, then I would move to images and only then I would've looked at the source code
Upvotes: 1
Reputation: 494
crop the image and then send to server.Its working well,
add dependency in to gradle,
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
gallery Intent,
private static final int PICK_FROM_FILE = 3;
private Uri mImageCaptureUri=null;
File sdCard = Environment.getExternalStorageDirectory();
String pathName;
File filepath;
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, PICK_FROM_FILE);
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK)
return;
switch (requestCode) {
case PICK_FROM_FILE:
mImageCaptureUri = data.getData();
// METHOD FOR CROP
beginCrop(mImageCaptureUri);
System.out.println("CHECK_GALLERY_path :" + mImageCaptureUri);
break;
case Crop.REQUEST_CROP:
handleCrop(resultCode, data);
break;
}
}
private void beginCrop(Uri source) {
Uri destination = Uri.fromFile(new File(getCacheDir(), "cropped"));
Crop.of(source, destination).start(this);
}
private void handleCrop(int resultCode, Intent result) {
if (resultCode == RESULT_OK) {
mImageCaptureUri = Crop.getOutput(result);
pathName = mImageCaptureUri.getPath();
//uploadImageToServer();
// getImageUri(mImageCaptureUri);
Picasso.with(Activity_My_Account.this).load(mImageCaptureUri).into(getimage); //IMAGE SAVE TO STORAGE
getImageUri(mImageCaptureUri);
System.out.println("path_name+++" + mImageCaptureUri);
} else if (resultCode == Crop.RESULT_ERROR) {
Toast.makeText(this, Crop.getError(result).getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void getImageUri(Uri mImageCaptureUri) {
Bitmap photo = null;
try {
InputStream image_stream = getContentResolver().openInputStream(mImageCaptureUri);
java.util.Date date = new java.util.Date();
pathName = sdCard + "/" + "LEUF";
File myDir = new File(pathName);
System.out.println("GET_CHECK_PATH_NAME :" + pathName);
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
// if (file.exists()) file.delete();
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
Bitmap bitmapOrg = Bitmap.createScaledBitmap(BitmapFactory.decodeStream(image_stream), 350, 350, false);
photo.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
filepath=file;
try {
// file.createNewFile();
FileOutputStream fo = new FileOutputStream(file);
fo.write(bytes.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
//here call to upload image to server
public void UploadProfilePic(filepath){
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
Upvotes: 0
Reputation: 21407
I think Chetan Joshi's answer is the closest so far. But to explain a bit further,
"Compressing" an image and "scaling" (resizing) an image are different. Since you merely want to reduce the bandwidth (kb/Mb) over the network when you upload to the server, you are most likely talking about "scaling" since that will make the most difference to the size of the image.
Note, as in other answers Android, you will need to work with Bitmaps. You need to use the API calls associated with Bitmaps to do what you want.
Starting point:
If you allow your app to take a photo using the camera or pick from the gallery, you get an Uri which allows you to open an InputStream like this:
InputStream is = getContext().getContentResolver().openInputStream(photoUri);
That's the first step. The next part is the pseudocode where you want something like this:
InputStream
of the photo/selected picture. This is just a stream of bytes that represent the image.Bitmap
using BitmapFactory.decodeStream(InputStream src)
Bitmap.createScaledBitmap(src, dstWidth, dstHeight, filter);
. You'll have to decide on a destination width and destination height you want yourself. See the next set of pseudocode.imageFormat.getBitmapCompressFormat(), 100, output)
where output is an instance of ByteArrayOutputStream
output.toByteArray();
to get the bytes.Note about how to choose the destination width and height to scale to:
Altogether the high level process is something like this:
Upvotes: 2
Reputation: 5711
Image Compression in Android means we are working with Bitmaps, while we are compressing any big image to lower then we have method compress in Bitmap class but if difference between size of original bitmap and wanted bitmap is too highr then bitmap quality always reduced .
To compress bitmap with high quality we have to use recursive process to compress any Bitmap rather compressing any bitmap directly from original height width to wanted height and width, we should compress image with 3 to 5 steps for example if our image size is 1000x1000
and wanted width and height are 300x300
then we applied recursive process to do this like below:
1000 x 1000
850 x 850
650 x 650
300 x 300
In this way our Bitmap quality not reduced but make sure do not create new bitmap object each time use same bitmap object to assigned compressed bitmap otherwise you must face OutOfmemmory issue.
Upvotes: 1
Reputation: 734
The code from your link describes not so much compression but rather sampling the image with a lower density and downscaling it. So it is not really compression but a reduction of quality (number of pixels and size) to make it smaller. Good compression algorithms will usually find a way to save the image in a way that uses less space without compromising the quality too much (with math and stuff).
Upvotes: 0
Reputation: 401
Java provides ImageIO
APIs which can help in compressing an image with your choice of quality and factor of compression. ImageWriter
and ImageWriteParam
provides the mentioned capabilities out of the box.
Are you planning to write your own API for some other reasons custom to your requirement ?
If not using java out of the box APIs , high level approach could be : 1) Read the image file. 2) using ImageIO , get the ImageWriter based on the image type like (jpeg,png etc.) 3) Get ImageWriteParam object from the writer and set compression params as per your requirement. 4) write the image.
Let me know if it doesnot work for you.
Upvotes: 0
Reputation: 608
Since you aren't actually looking for code, here is a fantastic resource for learning about the thought process behind image compression Data Compression Theory
There are a variety of algorithms that make use of different techniques to leverage on the different variables involved. Computational complexity, storage space, compression ration, and retaining image quality are all factors that these different algorithms (or file formats) seek to optimize, often favoring one attribute over the other. e.g PNG vs JPEG for quality vs. space
Upvotes: 0