I develop an Android App and I develop a feature to take a picture from the gallery and to send it to my server and assign it to user as his profil picture.
I select an image (important : taken by ma camera) and I convert it to base64 before sending it to my server. When I get the image and I try to display it I have only part of the picture but not for image in png... I tried to change compressformat in JPEG and it's worst... I didn't understand the problem since 2 days I get crazy... Help Please :)
private Bitmap bitmap;
public void chooseProfilePicture(View view) {
Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(i, REQUEST_CODE);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
InputStream stream = null;
if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK)
try {
if (bitmap != null)
bitmap.recycle(); // recyle unused bitmaps
stream = getContentResolver().openInputStream(data.getData());
bitmap = BitmapFactory.decodeStream(stream);
imageView.setImageBitmap(bitmap);
// HERE THE IMAGE IS DISPLAYED 100% WELL
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (stream != null)
try {
stream.close();
} catch (Exception ex) {
Log.e("EditProfilActivity", ex.getMessage());
}
}
}
public void save(View view) {
if (bitmap != null) {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
bitmap.recycle();
byte[] imageBytes = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
String encodedImage = Base64.encodeToString(imageBytes, Base64.DEFAULT);
picture = encodedImage;
// HERE WHEN I TRY TO DISPLAY THE IMAGE I HAVE ONLY A PART OF THE IMAGE
} catch (Exception e) {
Log.e("", e.getMessage());
}
}
You are trying to show image form string(from encoding image file)?
byte[] imagebyteArry = byteArrayOutputStream.toByteArray();
String imageString = encodeImage(imagebyteArry);
sendImageToserver(imageString);
............
String imageString = getImageFromserver();
byte[] imagebyteArry = decodeImage(imageString);
Search how to show image from byte[] in android?
public static String encodeImage(byte[] imageByteArray) {
return Base64.encodeBase64URLSafeString(imageByteArray);
}
public static byte[] decodeImage(String imageDataString) {
return Base64.decodeBase64(imageDataString);
}
Related
I would like to display an image from the URL that is providing me raw data for the image(png or JPG).
I checked this link but not much useful.
Here is my image link
I am processing the raw data but could not see the image. I am not sure how do I check that I got the right raw data.
here is my effort
private class DownloadImageTask extends AsyncTask<String, Void, Void> {
byte[] bytes;
Bitmap picture = null;
#Override
protected Void doInBackground(String... urls) {
// final OkHttpClient client = new OkHttpClient();
//
// Request request = new Request.Builder()
// .url(urls[0])
// .build();
//
// Response response = null;
//
// try {
// response = client.newCall(request).execute();
// } catch (IOException e) {
// e.printStackTrace();
// }
// assert response != null;
// if (response.isSuccessful()) {
// try {
// assert response.body() != null;
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// IOUtils.copy(response.body().byteStream(), baos);
// bytes = baos.toByteArray();
// picture = BitmapFactory.decodeStream(response.body().byteStream());
// } catch (Exception e) {
// Log.e("Error", Objects.requireNonNull(e.getMessage()));
// e.printStackTrace();
// }
//
// }
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
URL url = new URL(urls[0]);
byte[] chunk = new byte[4096];
int bytesRead;
InputStream stream = url.openStream();
while ((bytesRead = stream.read(chunk)) > 0) {
outputStream.write(chunk, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
return null;
}
bytes = outputStream.toByteArray();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (bytes != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
cameraView.setImageBitmap(bitmap);
}
// cameraView.setImageBitmap(picture);
}
}
The location of your problem/s in your workflow seems ill-determined.
You should first identify this.
(Plus, you did not specify if you are bound to a specific programming language).
For this sake, I suggest you:
Start using a raw image file that you know is correct, and test its processing.
There are quite a few raw image formats.
Judging from the tag android, I guess the following can help:
To capture a raw iamge into a file: How to capture raw image from android camera
To display in ImageView: Can't load image from raw to imageview
https://gamedev.stackexchange.com/questions/14046/how-can-i-convert-an-image-from-raw-data-in-android-without-any-munging
https://developer.android.com/reference/android/graphics/ImageFormat
https://www.androidcentral.com/raw-images-and-android-everything-you-need-know
Try getting a raw image from an URL that you can manage.
Apply this to the actual target URL.
This way you will know where your problem resides.
Without more info it is hard to "debug" your problem.
You can also inspect code in FOSS projects.
You could use a library named Picasso and do the following:
String url = get url from the Async Function and convert it to String
/*if you url has no image format, you could do something like this con convert the uri into a Bitmap*/
public Bitmap getCorrectlyOrientedImage(Context context, Uri uri, int maxWidth)throws IOException {
InputStream input = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
onlyBoundsOptions.inJustDecodeBounds = true;
onlyBoundsOptions.inDither = true;//optional
onlyBoundsOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;//optional
BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
try {
input.close();
} catch (NullPointerException e) {
e.printStackTrace();
}
/*trying to get the right orientation*/
if ((onlyBoundsOptions.outWidth == -1) || (onlyBoundsOptions.outHeight == -1)) {
return null;
}
int originalSize = Math.max(onlyBoundsOptions.outHeight, onlyBoundsOptions.outWidth);
double ratio = (originalSize > maxWidth) ? (originalSize / maxWidth) : 1.0;
Matrix matrix = new Matrix();
int rotationInDegrees = exifToDegrees(orientation);
if (orientation != 0) matrix.preRotate(rotationInDegrees);
int bmpWidth = 0;
try {
assert bitmap != null;
bmpWidth = bitmap.getWidth();
} catch (NullPointerException e) {
e.printStackTrace();
}
Bitmap adjustedBitmap = bitmap;
if (bmpWidth > 0)
adjustedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
return adjustedBitmap;
}
/*Then you has the image in Bitmap, you can use the solution below or if Picasso doesn't allows you to put Bitmap you can pass it directly to the ImageView as a Bitmap.*/
ImageView imageView = view.findViewById(R.id.imageViewId);
/*Then use Picasso to draw the image into the ImageView*/
Picasso.with(context).load(url).fit().into(imageView );
This is the dependency for build.gradle, not sure if is the last version but you could try.
implementation 'com.squareup.picasso:picasso:2.5.2'
Kind regards!
Identify the following questions:
Using URL to get bytes to load images
I wrote down what I can with reference to
class DownLoadImageTask extends AsyncTask<String, Void, Bitmap> {
#Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
imageView.setImageBitmap(bitmap);
}
#Override
protected Bitmap doInBackground(String... strings) {
try {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(strings[0]).build();
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
InputStream inputStream = response.body().byteStream();
return BitmapFactory.decodeStream(inputStream);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
This is the URL I use
https://upload.wikimedia.org/wikipedia/commons/thumb/b/b6/Image_created_with_a_mobile_phone.png/440px-Image_created_with_a_mobile_phone.png
https://upload.wikimedia.org/wikipedia/commons/3/3a/Cat03.jpg
I can test it. I hope it can help you
Im trying to capture image and then for good practice I put bitmap file in the the FileOutputStream how can I recover the bitmap using the filename.
Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK){
if (requestCode == REQUEST_CODE_CAMERA && data != null){
fragment = null;
Bitmap bmp = (Bitmap) data.getExtras().get("data");
String filename = "bitmap.png";
try {
FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
assert bmp != null;
bmp.compress(Bitmap.CompressFormat.PNG,100,stream);
stream.close();
bmp.recycle();
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.slide_in_left,R.anim.fade_out,R.anim.fade_in,R.anim.slide_out_right);
fragment =FragmentCropper.newInstance(filename);
fragmentTransaction.add(R.id.fragmentContainer,fragment,Constant.BackStackTag.CROP_TAG);
fragmentTransaction.addToBackStack(Constant.BackStackTag.CROP_TAG);
fragmentTransaction.commit();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
In the Fragment
How to recover the Bitmap using the filename
try {
//FileInputStream stream = getActivity().openFileInput(filename);
//mBitmap = BitmapFactory.decodeStream(stream);
//stream.close();
String path = "path/"+filename;
mBitmap = BitmapUtils.decodeSampledBitmapFromFile(path,500,500);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (mBitmap.isRecycled())
mBitmap.recycle();
mBitmap=null;
}
String path = "path/"+filename;
Change to
String path = getFilesDir().getAbsolutePath() + "/" + filename;
First of all I would like to say, that loading big images strategy is described here. I am aware of the obligation to resize the image to omit OutOfMemoryError. I would like to get bytes from the image to be able to send it through Internet.
public byte[] getAttachment(Context context, String fullFilePath) {
byte[] fileBytes = mFileUtil.readFileAsBytes(fullFilePath);
if (fileBytes == null) {
Logger.i("Unable to get bytes, trying through content resolver");
try {
fileBytes = mFileUtil.readFileFromContentResolver(context, fullFilePath);
} catch (OutOfMemoryError e) {
Uri imageUri = Uri.parse(fullFilePath);
if (checkIfFileIsImage(context, imageUri)) {
try {
InputStream stream = context.getContentResolver().openInputStream(imageUri);
if (stream == null) {
return null;
}
BitmapFactory.Options options = getOptions(stream, 2000, 2000);
stream.close();
stream = context.getContentResolver().openInputStream(imageUri);
if (stream == null) {
return null;
}
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, options);
bitmap = rotateBitmap(context, imageUri, bitmap);
stream.close();
fileBytes = convertBitmapToArray(bitmap);
} catch (Exception e1) {
Logger.e("Unable to get bytes using fallback method, attachment " +
"will not be added");
} catch (OutOfMemoryError e2) {
Logger.e("Unable to get bytes using fallback method, because " +
"attachment is too big. Attachment will not be added");
}
}
System.gc();
}
}
return fileBytes;
}
FileUtil.class
public byte[] readFileAsBytes(String fileName) {
File originalFile = new File(fileName);
byte[] bytes = null;
try {
FileInputStream fileInputStreamReader = new FileInputStream(originalFile);
bytes = new byte[(int) originalFile.length()];
fileInputStreamReader.read(bytes);
} catch (IOException e) {
}
return bytes;
}
public byte[] readFileFromContentResolver(Context context, String fileName) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
InputStream is = null;
InputStream inputStream = null;
try {
inputStream = context.getContentResolver().openInputStream(Uri.parse(fileName));
is = new BufferedInputStream(inputStream);
byte[] data = new byte[is.available()];
is.read(data);
bos.write(data);
} catch (Exception e) {
} finally {
try {
if (is != null) {
is.close();
}
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e1) {
}
}
return bos.toByteArray();
}
As you can see the aim of this code is to get byte[] from Bitmap unlike here. It works without problems in almost any case. However it is especially error prone on low-end devices with older Android systems (but also very rarely).
I don't like the idea of setting largeHeap inside AndroidManifest.xml as this is just masking the problem rather than cope with it. I also would not like to send even smaller images.
Could this piece of code be improved in any other way in order to get rid of OutOfMemoryError?
i am using this method to get images from url and i am downloading more than one image the varable below called "name" is an array of names of the images .i want to be able to store all images whos name is in the array thats why i kept the url like that.it seems to work well but i have having problem selecting only one picture out or them.
this is the code to save images
String fileName="code";
try {
URL url = new URL("http://10.0.2.2/picure/"+name+".jpg");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.connect();
InputStream is = conn.getInputStream();
Bitmap bm = BitmapFactory.decodeStream(is);
FileOutputStream fos = getActivity().openFileOutput(fileName, Context.MODE_PRIVATE);
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
bm.compress(Bitmap.CompressFormat.JPEG, 100, outstream);
byte[] byteArray = outstream.toByteArray();
fos.write(byteArray);
fos.close();
Toast.makeText(getActivity()," connected", Toast.LENGTH_LONG).show();
} catch(Exception e) {
}
this is the code to collect images
String path = mContext.getFilesDir().toString();
String fileName = "code";
if (fileName != null && !fileName.equals("")) {
Bitmap bMap = BitmapFactory.decodeFile(path + "/" + fileName);
if (bMap != null) {
category_logo.setImageBitmap(bMap);
}
}
i know the names of the images i saved so how do i select that one specifically
For get all images use a Asynctask, this code can download images in cache directory of the app:
class ImageDownloader extends AsyncTask<String, Void, File> {
String imageurl;
String name;
Context ctx;
public ImageDownloader(Context context, String url, String fileName) {
this.imageurl = url;
this.name = fileName;
this.ctx = context;
}
#Override
protected File doInBackground(String... urls) {
Bitmap mIcon;
File cacheDir = ctx.getCacheDir();
File f = new File(cacheDir, name);
try {
InputStream in = new java.net.URL(imageurl).openStream();
mIcon = BitmapFactory.decodeStream(in);
try {
FileOutputStream out = new FileOutputStream(
f);
mIcon.compress(
Bitmap.CompressFormat.JPEG,
100, out);
out.flush();
out.close();
return f;
} catch (FileNotFoundException e) {
return null;
} catch (IOException e) {
return null;
}
} catch (Exception e) {
return null;
}
}
#Override
protected void onPostExecute(File result) {
super.onPostExecute(result);
Toast.makeText(ctx," connected " + name, Toast.LENGTH_LONG).show();
}
}
}
For call the asynctask, you need use a FOR for get all names and url of the image:
new ImageDownloader(getBaseContext(),url[i],name[i]).execute();
You can edit the doInBackground with your code, but the HTTPConnection that you use is deprecated in API 22, please use the example above, you can change the directory.
And sorry for the code, you can reformat later.
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CODE_MULTIPLE_IMG_GALLERY && resultCode==RESULT_OK){
ClipData clipData = data.getClipData();
if (clipData!=null){
File folderPath = new File(getIntent().getStringExtra("folderpath"));
for (int i = 0;i< clipData.getItemCount();i++){
ClipData.Item item = clipData.getItemAt(i);
Uri uri = item.getUri();
Bitmap selectedImage = loadFromUri(uri);
File imagePath = new File(folderPath,System.currentTimeMillis()+".jpg");
try {
outputStream = new FileOutputStream(imagePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
selectedImage.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
Log.d("uri",uri.toString());
imageModelList.add(new ImageModel(uri.toString()));
}
imagesAdapter.notifyDataSetChanged();
Toast.makeText(ImageDetailActivity.this, "Added Successfully!", Toast.LENGTH_SHORT).show();
}
}
}
public Bitmap loadFromUri(Uri photoUri) {
Bitmap image = null;
try {
// check version of Android on device
if(Build.VERSION.SDK_INT > 27){
// on newer versions of Android, use the new decodeBitmap method
ImageDecoder.Source source = ImageDecoder.createSource(this.getContentResolver(), photoUri);
image = ImageDecoder.decodeBitmap(source);
} else {
// support older versions of Android by using getBitmap
image = MediaStore.Images.Media.getBitmap(this.getContentResolver(), photoUri);
}
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
I'm trying to implement a simple file upload and associate the file with the current user.
I followed the guide on parse.com and checked with several questions on here with no luck.
The saveinBackground operation is successful, no exceptions are being thrown but I can't see the file in Parse.com data browser.
Here's my code.
final long time1 = Time;
//Image part
//upload the .jpg file for user's history
//Parse
byte[] data = filePath.getBytes();
final ParseFile file = new ParseFile("asdasd.jpg", data);
file.saveInBackground(new SaveCallback() {
public void done(ParseException e) {
// Handle success or failure here ...
if ( e == null){
ParseObject rentedTime = new ParseObject("Time");
rentedTime.put("duration", renttime1);
rentedTime.put("owner", ParseUser.getCurrentUser());
rentedTime.put("id", id);
rentedTime.put("image", file);
rentedTime.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null)
Log.d("upload successful" + file.getName(), null);
}
});
} else {
Log.d("terrible", e.getMessage());
}
}
}, new ProgressCallback() {
public void done(Integer percentDone) {
// Update your progress spinner here. percentDone will be between 0 and 100.
}
});
}
What am I missing?
That's because you are NOT uploading the file..see
byte[] data = filePath.getBytes();
just getting the bytes from the file path wont work reasonably.
First get the bitmap and then convert it to byte[] see how..
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
byte[] data = getBytes(bitmap);
private byte[] getBytes(Bitmap bitmap) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
byte[] data = outputStream.toByteArray();
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
And you can now use the data..
final ParseFile file = new ParseFile("asdasd.png", data);
I've changed the file name to .png format if you wish ti save in jpg format then compress in .JPG format as well.
Hope you find this helpful! :)