I made a gallery application and stored more images in a SQL Server databse,
now I am getting images takes a lot of time.
So I want image uploading time MB to KB conversion (i.e.: 20KB, 30KB).
What shall I do? Help me, please.
My code is:
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm = null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(Admin.this.getApplicationContext().getContentResolver(), data.getData());
imgadminview.setImageBitmap(bm);
int bitmapByteCount= BitmapCompat.getAllocationByteCount(bm);
System.out.print(bitmapByteCount);
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bytes);
byteArray = bytes.toByteArray();
long lengthbmp = byteArray.length;
System.out.print(lengthbmp);
if(lengthbmp<=1048576){
//KB or more
rxKb = lengthbmp/1024;
System.out.print(rxKb + " KBs");}
else if(rxKb>=1024) {
//MB or more
rxMB = rxKb / 1024;
System.out.print(rxMB + " MBs");
}else if(rxMB>=1024) {
//GB or more
long rxGB = rxMB / 1024;
System.out.print(rxGB + Long.toString(rxGB));
}else {
//rxMB>1024
//rxKb > 1024
}//rxBytes>=1024
byte[] test=String.valueOf(rxKb).getBytes();
encodedImage = Base64.encodeToString(test, Base64.DEFAULT);
btarray = Base64.decode(encodedImage, Base64.DEFAULT);
bmimage = BitmapFactory.decodeByteArray(byteArray, 0, btarray.length);
} catch (IOException e) {
e.printStackTrace();
}
}
imgadminview.setImageBitmap(bm);
}
Related
How can I compress the file size and quality when uploading pictures?
I already finished the upload file to firebase, how to compress the file?
Because when the file size is big, it will slow loading in recyclerview.
So I wanna compress the file.
Uri imageUri = imageListUri.get(index);
if(spinner.getSelectedItem().toString().equals(getApplicationContext().getResources().getString(R.string.choose_sub))) {
AlertDialog alertDialog = new AlertDialog.Builder(this)
.setTitle(getApplicationContext().getResources().getString(R.string.alert_error))
.setMessage(getApplicationContext().getResources().getString(R.string.choose_sub))
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).create();
alertDialog.show();
} else if(image_check.equals("ok")) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage(getApplicationContext().getResources().getString(R.string.posting));
progressDialog.show();
if (imageUri != null) {
final StorageReference filerefrence = storageReference.child(System.currentTimeMillis()
+ "." + getFileExtension(imageUri));
// scaling the image
int scaleDivider = 1;
try {
Bitmap fullBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
int scaleWidth = fullBitmap.getWidth() / scaleDivider;
int scaleHeight = fullBitmap.getHeight() / scaleDivider;
byte[] downsizedImageBytes =
getDownsizedImageBytes(fullBitmap, scaleWidth, scaleHeight);
uploadTask = filerefrence.putBytes(downsizedImageBytes);
} catch (IOException e) {
e.printStackTrace();
}
static public byte[] getDownsizedImageBytes(Bitmap fullBitmap, int scaleWidth, int scaleHeight) throws IOException {
Bitmap scaledBitmap = Bitmap.createScaledBitmap(fullBitmap, scaleWidth, scaleHeight, true);
// 2. Instantiate the downsized image content as a byte[]
ByteArrayOutputStream baos = new ByteArrayOutputStream();
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
return baos.toByteArray();
}
So, is it correct?
try {
Bitmap fullBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
ByteArrayOutputStream out = new ByteArrayOutputStream();
fullBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out); // Here 100 is the quality in percent of the image
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
int scaleWidth = fullBitmap.getWidth() / scaleDivider;
int scaleHeight = fullBitmap.getHeight() / scaleDivider;
byte[] downsizedImageBytes =
getDownsizedImageBytes(fullBitmap, scaleWidth, scaleHeight);
uploadTask = filerefrence.putBytes(downsizedImageBytes);
} catch (IOException e) {
e.printStackTrace();
}
You can do it using the BitmapFactory class like so
Bitmap original = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri)
ByteArrayOutputStream out = new ByteArrayOutputStream();
original.compress(Bitmap.CompressFormat.JPEG, 100, out); // Here 100 is the quality in percent of the image
Bitmap decoded = BitmapFactory.decodeStream(new ByteArrayInputStream(out.toByteArray()));
Note that PNG is already a lossless format so it won't make any difference while compression, if you really want to see the effects use JPEG
Quality Accepts 0 - 100
0 = MAX Compression (Least Quality which is suitable for Small images)
100 = Least Compression (MAX Quality which is suitable for Big images)
Credits to this answer
I'm having quite a problem here.
When I read image and then save it, I get the same picture. But when I open the pixel value, the value of each pixel is slightly different(larger or smaller around 10 units).
Why did that pixel change? I only read the image, then save it, I don't make changes to the pixel. I create it with format RGB and save as a PNG with ByteArrayOutputStream method.
private void onCaptureImageResult(Intent data) {
Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
thumbnail.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File destination = new File(Environment.getExternalStorageDirectory(),
System.currentTimeMillis() + ".jpg");
FileOutputStream fo;
try {
destination.createNewFile();
fo = new FileOutputStream(destination);
fo.write(bytes.toByteArray());
fo.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
ivImage.setImageBitmap(thumbnail);
}
private void onSelectFromGalleryResult(Intent data) {
Bitmap bm=null;
if (data != null) {
try {
bm = MediaStore.Images.Media.getBitmap(getApplicationContext().getContentResolver(), data.getData());
} catch (IOException e) {
e.printStackTrace();
}
}
bmp = bm;
}
public void save(View view){
operation= Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),bmp.getConfig());
int size = bmp.getRowBytes() * bmp.getHeight();
bytearrayoutputstream = new ByteArrayOutputStream();
int[] gambarR = new int[size];
int[] gambarG = new int[size];
int[] gambarB = new int[size];
int[] gambarA = new int[size];
int k = 0;
for(int i=0; i<bmp.getWidth(); i++){
for(int j=0; j<bmp.getHeight(); j++){
int p = bmp.getPixel(i, j);
gambarR[k] = Color.red(p);
gambarG[k] = Color.green(p);
gambarB[k] = Color.blue(p);
gambarA[k] = Color.alpha(p);
k++;
}
}
int l = 0;
for(int i = 0; i<bmp.getWidth(); i++){
for(int j = 0; j<bmp.getHeight();j++){
operation.setPixel(i, j, Color.rgb(gambarR[l], gambarG[l], gambarB[l]));
l++;
}
}
String fileName = "_hasil.bmp";
Long tsLong = System.currentTimeMillis()/1000;
String ts = tsLong.toString();
String baseDir = Environment.getExternalStorageDirectory().getAbsolutePath();
File gambar = new File(baseDir + File.separator + ts + fileName);
try
{
gambar.createNewFile();
fileoutputstream = new FileOutputStream(gambar);
fileoutputstream.write(bytearrayoutputstream.toByteArray());
fileoutputstream.close();
}
catch (Exception e)
{
e.printStackTrace();
}
ivImage.setImageBitmap(operation);
}
I will show you the difference between the image. I only read and save, and don't change the pixel. I need the pixel didn't change when I save it back.
As others have noticed, much of the code that you posted appears to do not much useful, indicating that you either haven't read the documentation, or haven't thought through the problem thoroughly.
However, the specific problem appears to be that you are saving your image in a lossy compression format (JPEG), in this case, at 90% quality. "Lossy" means that by definition you will never get back exactly the bitmap that you had before compression. Even setting JPEG quality to 100% is unlikely to get you exactly the same bitmap as before compression.
If you want exactly the same values back when reading the file, you'll need to write a lossless format, such as PNG or BMP.
Here the report contain the path(pathname in sdcard in string format)
File dir = Environment.getExternalStorageDirectory();
File yourFile = new File(dir, report);
String encodeFileToBase64Binary = encodeFileToBase64Binary(yourFile);
private static String encodeFileToBase64Binary(File fileName) throws IOException {
byte[] bytes = loadFile(fileName);
byte[] encoded = Base64.encodeBase64(bytes);
String encodedString = new String(encoded);
return encodedString;
}
in the byte[] encoded line getting this error.
The method encodeBase64(byte[]) is undefined for the type Base64
String value = Base64.encodeToString(bytes, Base64.DEFAULT);
But you can directly convert it in to String .Hope this will work for you.
An updated, more efficient, Kotlin version, that bypasses Bitmaps and doesn't store entire ByteArray's in memory (risking OOM errors).
fun convertImageFileToBase64(imageFile: File): String {
return ByteArrayOutputStream().use { outputStream ->
Base64OutputStream(outputStream, Base64.DEFAULT).use { base64FilterStream ->
imageFile.inputStream().use { inputStream ->
inputStream.copyTo(base64FilterStream)
}
}
return#use outputStream.toString()
}
}
I believe these 2 sample codes will help at least someone the same way many have helped me through this platform. Thanks to StackOverflow.
// Converting Bitmap image to Base64.encode String type
public String getStringImage(Bitmap bmp) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] imageBytes = baos.toByteArray();
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
return encodedImage;
}
// Converting File to Base64.encode String type using Method
public String getStringFile(File f) {
InputStream inputStream = null;
String encodedFile= "", lastVal;
try {
inputStream = new FileInputStream(f.getAbsolutePath());
byte[] buffer = new byte[10240];//specify the size to allow
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
Base64OutputStream output64 = new Base64OutputStream(output, Base64.DEFAULT);
while ((bytesRead = inputStream.read(buffer)) != -1) {
output64.write(buffer, 0, bytesRead);
}
output64.close();
encodedFile = output.toString();
}
catch (FileNotFoundException e1 ) {
e1.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
lastVal = encodedFile;
return lastVal;
}
I will be glad to answer any question regarding to these codes.
To convert a file to Base64:
File imgFile = new File(filePath);
if (imgFile.exists() && imgFile.length() > 0) {
Bitmap bm = BitmapFactory.decodeFile(filePath);
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, bOut);
String base64Image = Base64.encodeToString(bOut.toByteArray(), Base64.DEFAULT);
}
Convert Any file, image or video or text into base64
1.Import the below Dependancy
compile 'commons-io:commons-io:2.4'
2.Use below Code to convert file to base64
File file = new File(filePath); //file Path
byte[] b = new byte[(int) file.length()];
try {
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(b);
for (int j = 0; j < b.length; j++) {
System.out.print((char) b[j]);
}
} catch (FileNotFoundException e) {
System.out.println("File Not Found.");
e.printStackTrace();
} catch (IOException e1) {
System.out.println("Error Reading The File.");
e1.printStackTrace();
}
byte[] byteFileArray = new byte[0];
try {
byteFileArray = FileUtils.readFileToByteArray(file);
} catch (IOException e) {
e.printStackTrace();
}
String base64String = "";
if (byteFileArray.length > 0) {
base64String = android.util.Base64.encodeToString(byteFileArray, android.util.Base64.NO_WRAP);
Log.i("File Base64 string", "IMAGE PARSE ==>" + base64String);
}
You can try this.
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
...
byte[] byteArray = byteArrayOutputStream.toByteArray();
base64Value = Base64.encodeToString(byteArray, Base64.DEFAULT);
public static String uriToBase64(Uri uri, ContentResolver resolver, boolean thumbnail) {
String encodedBase64 = "";
try {
byte[] bytes = readBytes(uri, resolver, thumbnail);
encodedBase64 = Base64.encodeToString(bytes, 0);
} catch (IOException e1) {
e1.printStackTrace();
}
return encodedBase64;
}
private static byte[] readBytes(Uri uri, ContentResolver resolver, boolean thumbnail)
throws IOException {
// this dynamically extends to take the bytes you read
InputStream inputStream = resolver.openInputStream(uri);
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
if (!thumbnail) {
// this is storage overwritten on each iteration with bytes
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
// we need to know how may bytes were read to write them to the
// byteBuffer
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
} else {
Bitmap imageBitmap = BitmapFactory.decodeStream(inputStream);
int thumb_width = imageBitmap.getWidth() / 2;
int thumb_height = imageBitmap.getHeight() / 2;
if (thumb_width > THUMBNAIL_SIZE) {
thumb_width = THUMBNAIL_SIZE;
}
if (thumb_width == THUMBNAIL_SIZE) {
thumb_height = ((imageBitmap.getHeight() / 2) * THUMBNAIL_SIZE)
/ (imageBitmap.getWidth() / 2);
}
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, thumb_width, thumb_height, false);
imageBitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteBuffer);
}
// and then we can return your byte array.
return byteBuffer.toByteArray();
}
and call it in this way
String image = BitmapUtils.uriToBase64(Uri.fromFile(file), context.getContentResolver());
I'm trying to compress an image that I saved in the file. I'm trying to compress the File into 1MB. I try a few way but it usually make an OutofMemoryError.
and then i tried to use this solution, but it makes the bitmap blank.
How to compress bitmap from 10mb image from camera to 300kb beforw setting to imageview in android
Here is my code :
System.gc();
getActivity().getContentResolver().notifyChange(mImageTempUri, null);
Bitmap bitmap;
bitmap = BitmapFactory.decodeFile(mImageDirectory + mImageName, options);
if(bitmap == null){
howRequestFailedErrorMessage("Gambar gagal di-upload");
return;
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 25, bytes);
File f = new File(mImageDirectory + mImageName);
if(f.exists()){
f.delete();
}
FileOutputStream fo;
try {
fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();
okay, I got my own answer
File f = new File(mImageDirectory + mImageName);
if(f.exists()){
f.delete();
}
int MAX_IMAGE_SIZE = 1000 * 1024;
int streamLength = MAX_IMAGE_SIZE;
int compressQuality = 105;
ByteArrayOutputStream bmpStream = new ByteArrayOutputStream();
while (streamLength >= MAX_IMAGE_SIZE && compressQuality > 5) {
try {
bmpStream.flush();//to avoid out of memory error
bmpStream.reset();
} catch (IOException e) {
e.printStackTrace();
}
compressQuality -= 5;
bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream);
byte[] bmpPicByteArray = bmpStream.toByteArray();
streamLength = bmpPicByteArray.length;
if(BuildConfig.DEBUG) {
Log.d("test upload", "Quality: " + compressQuality);
Log.d("test upload", "Size: " + streamLength);
}
}
FileOutputStream fo;
try {
fo = new FileOutputStream(f);
fo.write(bmpStream.toByteArray());
fo.flush();
fo.close();
} catch (IOException e) {
e.printStackTrace();
}
Kotlin Way
if (file.length() > MAX_IMAGE_SIZE) {
var streamLength = MAX_IMAGE_SIZE
var compressQuality = 105
val bmpStream = ByteArrayOutputStream()
while (streamLength >= MAX_IMAGE_SIZE && compressQuality > 5) {
bmpStream.use {
it.flush()
it.reset()
}
compressQuality -= 5
val bitmap = BitmapFactory.decodeFile(file.absolutePath, BitmapFactory.Options())
bitmap.compress(Bitmap.CompressFormat.JPEG, compressQuality, bmpStream)
val bmpPicByteArray = bmpStream.toByteArray()
streamLength = bmpPicByteArray.size
if (BuildConfig.DEBUG) {
Log.d("test upload", "Quality: $compressQuality")
Log.d("test upload", "Size: $streamLength")
}
}
FileOutputStream(file).use {
it.write(bmpStream.toByteArray())
}
}
Constant
companion object {
//2000 * 1024 = 2 MB
private const val MAX_IMAGE_SIZE = 2048000
}
I am looking for the most efficient way of converting image file to Base64 String in Android.
The image has to be sent in a single Base64 String at once to backend.
First I use imageToByteArray and then imageToBase64 to get the String.
public static byte[] imageToByteArray(String ImageName) throws IOException {
File file = new File(sdcard, ImageName);
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// Create the byte array to hold the data
byte[] bytes = new byte[(int)length];
// Read in the bytes
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
//Close input stream
is.close();
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
return bytes;
}
public String imageToBase64(String ImageName){
String encodedImage = null;
try {
encodedImage = Base64.encodeToString(imageToByteArray(ImageName), Base64.DEFAULT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return encodedImage;
}
Below is how I handle it mostly, this is in the gotActivityResults callback after calling the image picker activity. It's similar to your's but I think it will be more efficient because the toByteArray from the stream is native c code behind it as opposed to the java loop in yours.
Uri selectedImage = imageReturnedIntent.getData();
InputStream imageStream = getContentResolver().openInputStream(selectedImage);
Bitmap yourSelectedImage = BitmapFactory.decodeStream(imageStream);
ByteArrayOutputStream bao = new ByteArrayOutputStream();
yourSelectedImage.compress(Bitmap.CompressFormat.JPEG, 90, bao);
byte [] ba = bao.toByteArray();
String ba1= Base64.encodeToString(ba, 0);
HashMap<String, String > params = new HashMap<String, String>();
params.put("avatar", ba1);
params.put("id", String.valueOf(uc.user_id));
params.put("user_id", String .valueOf(uc.user_id));
params.put("login_token", uc.auth_token);
uc.setAvatar(params);