Android - Load image byte by byte in imageview - android

I have a large size of the image file which is nearly 16MB size. I want to load this image in my imageView and zoom it after that add markers. I tried this with subsampling-scale-image-view. I am following the below link https://github.com/davemorrissey/subsampling-scale-image-view .
The important point is I am loading image from url. The above library not supporting that. So I just downloaded the image and save to SD card after that load from that local file. Technically which is working.
Issue:
Now the issue is it is taking too much of time for the first time downloading. Also even second time it takes nearly a minute.
My Idea:
Due to this issue, I try to load image byte by byte. Once the image is downloading 100bytes then show that in imageView next download the next part of the image from url. Is it possible to doing like that?
Currently I am loading image like the following code:
URL url = new URL(url_);
URLConnection conection = url.openConnection();
conection.connect();
// getting file length
int lenghtOfFile = conection.getContentLength();
// input stream to read file - with 8k buffer
InputStream input = new BufferedInputStream(url.openStream(), 8192);
// Output stream to write file
OutputStream output = new FileOutputStream(root+"/"+ fileName);
byte data[] = new byte[1024];
long total = 0;
while ((count = input.read(data)) != -1) {
total += count;
// writing data to file
output.write(data, 0, count);
}
// flushing output
output.flush();
// closing streams
output.close();
input.close();
runOnUiThread(new Runnable() {
#Override
public void run() {
image.setImage(ImageSource.uri(root+"/"+ fileName));
}
});
Can somebody help me to solve this riddle?
Note: If there are any possibilities other than this library pls add your suggestions.

Never tried this but you can check if this work.
Get the data from url in form of byte Array.
data = getImageStream(url); //should call in async Task..
Now convert byte array into bitmap and set in imageView.
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
image.setImageBitmap(bitmap)
Not writing into file.This will help with some performance improvement.
public byte[] getImageStream(String url){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = null;
try {
is = url.openStream ();
byte[] byteChunk = new byte[4096]; // Or whatever size you want to read in at a time.
int n;
while ( (n = is.read(byteChunk)) > 0 ) {
baos.write(byteChunk, 0, n);
}
}
catch (IOException e) {
System.err.printf ("Failed while reading bytes from %s: %s", url.toExternalForm(), e.getMessage());
e.printStackTrace ();
// Perform any other exception handling that's appropriate.
}
finally {
if (is != null) { is.close(); }
}
return baos.toByteArray();
}

Related

Image URL to File Object

I'm trying to convert this image url to file object :
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7D
this link came from the facebook response after i logged in.
i used this method to convert this image url to File object:
URL url = null;
try {
url = new URL(sharePreferences.getPreferencesProfilePicture());
} catch (MalformedURLException e) {
e.printStackTrace();
}
File f = new File(url.getFile());
Log.d("CHECKER",""+f.exists());
Log.d("CHECKER",""+f.length());
but when i check it's length, its just 0 and the file exist is false.
You have a file with length 0 because you are just creating it with the name of the result of url.getFile(), url.getFile() returns a string which corresponds to the fetched file name.So you end up with a file named picture:
https://graph.facebook.com/v4.0/10211842143528384/picture?height=200&width=200&migration_overrides=%7Boctober_2012%3Atrue%7 But what about the contents? you have to download them fron the internet as a stream and feed that stream into a file. There many ways of doing that with plain Java. A basic copy-paste from https://www.baeldung.com/java-download-file
try (BufferedInputStream in = new BufferedInputStream(new URL(FILE_URL).openStream());
FileOutputStream fileOutputStream new FileOutputStream(FILE_NAME)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
} catch (IOException e) {
// handle exception
}
Since you are using android I would strongly encourage you to use fully featured Network libraries such as OkHttp3, Retrofit or Volley, but guessing your knowledge I think you will do better learning the basics on Java then jump to the mentioned libraries.
Remember, for android you need the INTERNET permission to access the internet, then if you download into a file on the external storage you would also need the EXTERNAL_STORAGE permission. Snippet for android:
try {
URLConnection conection = url.openConnection();
conection.connect();
int lenghtOfFile = conection.getContentLength();
// Read from the Network stream
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(Environment
.getExternalStorageDirectory().toString()
+ "/downloaded.png");
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
total += count;
// Feed the bytes read from the input stream into our output stream
output.write(data, 0, count);
}
// Flushing the out stream.
output.flush();
// closing streams
output.close();
input.close();
} catch (Exception e) {
Log.e("Error: ", e.getMessage());
}
This snippet does networking stuff so you need to run it on a background thread. I hope my answer helps you, if not, let me know what else can I do for you.

Image size increased more after convert to Base64

I am using Compressor third party library for compress the captured images size its working fine and now size is showing KB's but when i convert this images to BASE64 file size becomes 6MB or more size showing my code is below can some one help me please what should i do for resolve this issue
code:
File file= new Compressor(this).compressToFile(f);
String base64File = getBase64StringFile(file);
// Converting File to Base64.encode String type using Method
public static String getBase64StringFile(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;
}
You can resolve this issue using some other Compressor tools like FFMPEG.
Base64 always increase your file size
Base64 is often used on binary data that needs to be transmitted across a system that isn't really designed for binary. Depending on what you're doing, you may not even need to encode it. And per the wikipedia, on average, a file is expected to grow about 37% when you base64 encode it, which is almost exactly what your numbers are.

How to download all images one by one and show progress status

I want to download all the images I have on server in the array string of Url one by one so that I may do not have to download a zip file of images from the server and to unzip after downloading it.
So I thought to download the images one by one and to show the download status in the progress bar. But I am extremely failed in it. An Idea came into my mind to make the string array of the Url and to use the For loop to download but it is downloading the last image of the String array and decline or pass all other images in the array . I think I have got the idea that what is going on but I have know Idea what would be the solution then.
What I have done So far
protected Void doInBackground(Void... arg0) {
try {
//set the download URL, a url that points to a file on the internet
//this is the file to be downloaded
String [] imageUrl = {"http://www.androidbegin.com/tutorial/flag/india.png","http://www.androidbegin.com/tutorial/flag/pakistan.png"
,"http://www.androidbegin.com/tutorial/flag/china.png","http://www.androidbegin.com/tutorial/flag/unitedstates.png"};
URL url;
HttpURLConnection urlConnection = null;
for(int i=0;i<imageUrl.length;i++){
url = new URL(imageUrl[i]);
//create the new connection
urlConnection = (HttpURLConnection) url.openConnection();
//set up some things on the connection
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
//and connect!
urlConnection.connect();
}
File storagePath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "Test");
storagePath.mkdirs();
String finalName = Long.toString(System.currentTimeMillis());
File myImage = new File(storagePath, finalName + ".png");
//this will be used to write the downloaded data into the file we created
FileOutputStream fileOutput = new FileOutputStream(myImage);
//this will be used in reading the data from the internet
InputStream inputStream = urlConnection.getInputStream();
//this is the total size of the file
int totalSize = urlConnection.getContentLength();
//variable to store total downloaded bytes
int downloadedSize = 0;
//create a buffer...
byte[] buffer = new byte[1024];
int bufferLength = 0; //used to store a temporary size of the buffer
//now, read through the input buffer and write the contents to the file
while ((bufferLength = inputStream.read(buffer)) > 0) {
//add the data in the buffer to the file in the file output stream (the file on the sd card
fileOutput.write(buffer, 0, bufferLength);
//add up the size so we know how much is downloaded
downloadedSize += bufferLength;
//this is where you would do something to report the prgress, like this maybe
// updateProgress(downloadedSize, totalSize);
}
//close the output stream when done
fileOutput.close();
//catch some possible errors...
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// see http://androidsnippets.com/download-an-http-file-to-sdcard-with-progress-notification
return null;
}
** What I want :**
Download all the images one by one.
After downloading one Image it should get save in the device and update the progress status.
Please show me some source code rather then giving me just Idea how to do it. And little source code and complete work around on this would be appreciated.
the saving image code should be taken inside for loop. as this code is outside of for loop only your last image is getting saved as at the end of for loop last url is used.

Downloading image from stream

From the two lines below, in which line the actual download happens ?. and if possible please explain
InputStream input = new java.net.URL(imageURL).openStream();
bitmap = BitmapFactory.decodeStream(input);
This:
InputStream input = new java.net.URL(imageURL).openStream();
Creates a connection to the URL. The result is a stream, that can be used to get the content of the URL.
This:
bitmap = BitmapFactory.decodeStream(input);
Uses the above mentioned stream to read the URL's content and use it to create the bitmap, so this is where the "download" happens. Bear in mind, that this doesn't mean the image is actually saved on the internal memory or SD card. It's just there in memory.
Try this for getting and saving .
Also you can easly work with Universal Image lOader library or picasso
https://github.com/nostra13/Android-Universal-Image-Loader
http://square.github.io/picasso/
URL url = new URL("....your site .....");
InputStream input = null;
FileOutputStream output = null;
try {
String outputName = "thumbnail.jpg";
input = url.openConnection().getInputStream();
output = c.openFileOutput(outputName, Context.MODE_PRIVATE);
int read;
byte[] data = new byte[1024];
while ((read = input.read(data)) != -1)
output.write(data, 0, read);
return outputName;
} finally {
if (output != null)
output.close();
if (input != null)
input.close();
}

Android: Base64 Sample issue

currently I'm using kSoap to publish data to C# web services. Now I've come to the part where I need to upload images from my machine using Base64Binary. I searched everywehre internet but couldn't come up with a proper solution.
there is a solution with external Base64 class example but I'm interested in native solution as there is a API from Android 2.2.
Since I'm a newbie I couldn't do it myself. Basically I have a sd card file path of images, I want to convert them into Base64 format to upload.
Hope someone can help me or direct me to proper documents.
Thanks in advance.
Please try this, use Base64.java from link you have specified.
Bitmap bmImage = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory() + File.separator + "Your filename");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bmImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
String encodedString = Base64.encodeBytes( baos.toByteArray() );
You should change extension of this Bitmap.CompressFormat.JPEG statement according to your file type. You can decode a base 64 string to image using following code
byte[] b;
b = Base64.decode("base 64 string");
final Bitmap unscaledBitmap = BitmapFactory.decodeByteArray(b, 0, b.length );
I figured out the issue
String Image64 = null;
try {
Image64 = Base64.encodeToString((getBytesFromFile(new File(path))), DEFAULT);
} catch (IOException e) {
e.printStackTrace();
}
//encording
public static byte[] getBytesFromFile(File file) throws IOException {
InputStream is = new FileInputStream(file);
// Get the size of the file
long length = file.length();
// You cannot create an array using a long type.
// It needs to be an int type.
// Before converting to an int type, check
// to ensure that file is not larger than Integer.MAX_VALUE.
if (length > Integer.MAX_VALUE) {
// File is too large
}
// 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;
}
// Ensure all the bytes have been read in
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+file.getName());
}
// Close the input stream and return bytes
is.close();
return bytes;
}

Categories

Resources