How to set imageview from Image Arraylist? - java

I am using this library but they did not explain all details like other libraries on the github.
in onCreate
ImagePicker.create(this)
.folderMode(true) // folder mode (false by default)
.folderTitle("Folder") // folder selection title
.imageTitle("Tap to select") // image selection title
.single() // single mode
// multi mode (default mode)
.limit(10) // max images can be selected (99 by default)
.showCamera(true) // show camera or not (true by default)
.imageDirectory("Camera") // directory name for captured image ("Camera" folder by default)
// original selected images, used in multi mode
.start(12); // start image picker activity with request code
It is working I can see gallery.
onActivityResult:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
ImageView imageview = (ImageView)findViewById(R.id.iv1);
if (requestCode == 12 && resultCode == RESULT_OK && data != null) {
ArrayList<Image> images = data.getParcelableArrayListExtra(ImagePickerActivity.INTENT_EXTRA_SELECTED_IMAGES);
// do your logic ....
imageview.setImageBitmap(images);//It is not working, I know it is not bitmap but how to set?
}
}
Finally how to set imageview ?

You can't set an image view to an arraylist of images, you can only set an image view to have one image as a source.
Also, looks like you are processing your images on the main thread, which is also not a good idea.
your images are in the Array, but you have to use them on multiple image views or a custom view that displays multiple images

private Bitmap getScreenshot(Image image) {
Image.Plane[] planes = image.getPlanes();
ByteBuffer buffer = planes[0].getBuffer();
int pixelStride = planes[0].getPixelStride();
int rowStride = planes[0].getRowStride();
int rowPadding = rowStride - pixelStride * mWidth;
// ??????Bitmap???
Bitmap bitmap = Bitmap.createBitmap(mWidth + rowPadding / pixelStride, mHeight, Bitmap.Config.RGB_565);
bitmap.copyPixelsFromBuffer(buffer);
image.close();
return bitmap;
}
Image is resource rather than a image but you can use above API to get bitmap by using ByteBuffer. Pass images.get(position) in getScreenshot(Image image). it'll return bitmap then simply set imageView.setImageBitmap(bitmap)
Example link

Related

Proper resize of image

I capture an image using android camera and was saved as Bitmap.
Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, CAMERA_CODE);
if(requestCode == CAMERA_CODE){
Bundle b = data.getExtras();
Bitmap bmp = (Bitmap)b.get("data");
//I changed the bitmap from immutable to mutable somewhere here
mutableBitmap = Bitmap.createScaledBitmap(mutableBitmap, widthOfscreen, heightOfScreen, false);
cropView.setBitmap(mutableBitmap);
}
The problem is that the bitmap is small and I want something bigger. It is just that the result of my code was that there were some pixelated areas or an instinct that the result was not matched from the original image.

SetImageUri showing no Image

I want to let a image on my phone to show up in the Imageview. But in the ANdroid Studio emulator it is working but not on my own phone.
String imgPath = getIntent().getExtras().getString("imgPath");
System.out.println(imgPath);
if(!imgPath.equals("?"))
{
File img_file = new File(imgPath);
ImageView imgView = findViewById(R.id.show_image_war);
imgView.setImageURI(Uri.fromFile(img_file));
}
The path is /storage/emulated/0/imagesWarranty/img_MyWarranty_ID1.jpg . Both on the image in my phone and the path in my code where I get the image.
It might be issue of resolution. Even I was getting error of resolution while I was displaying image from uri.
I used below code and It worked for me :
Uri imageUri = Uri.parse(imagePath);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(imageUri.getPath()).getAbsolutePath(), options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
if (imageHeight > 4096 || imageWidth > 4096) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = 4;
Bitmap bitmap = BitmapFactory.decodeFile(imageUri.toString(), opts);
viewHolder.imgAvatarLogoList3.setImageBitmap(bitmap);
} else {
Picasso.with(context)
.load(new File(imageUri.getPath())) // Uri of the picture
.into(viewHolder.imgAvatarLogoList3);
}
Addition to this answer [https://stackoverflow.com/a/48354307/9255006]
In that rotation bug define the image orientation for the image using ExifInterface.
Here is the code
private void SetOrientation(){
try {
ExifInterface exif=new ExifInterface(photoURI.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_UNDEFINED);
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) { orientationInDegrees=90; }
else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) { orientationInDegrees=180; }
else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) { orientationInDegrees=270; }
else { orientationInDegrees=0; }
Toast.makeText(this, String.valueOf(orientationInDegrees), Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
}
}
You can then set this orientation to your image.
This happens when the image has a very high resolution that the system needs some additional milliseconds to display, and since this happens in the UI thread onDraw() of the image view will draw it as an empty.
The easiest way I found for this issue is to use the Picasso library this way:
Picasso.get().load(imgUri).fit().centerCrop()
.into(imageview);
The reason behind those two methods (fit(), centerCrop())
Is that fit make sure that the image fit the bound container and then crop the image which force the system to redraw the image but this time with the convenient resolution (because of fit and crop).

Image losing quality and size in android?

I have an app which takes photos of receipts and upload it to a remote server.
I get the full-sized photo of the image from the camera intent correctly.I followed this using the official documentation in Google developer.
I then set my picture like this.
private void setPic() {
// Get the dimensions of the View
int targetW = imageView.getWidth();
int targetH = imageView.getHeight();
// Get the dimensions of the bitmap
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
// Determine how much to scale down the image
int scaleFactor = Math.min(photoW/targetW, photoH/targetH);
// Decode the image file into a Bitmap sized to fill the View
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scaleFactor;
bmOptions.inPurgeable = true;
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
//Bitmap bitmap = null;
//try
//{
//bitmap = MediaStore.Images.Media.getBitmap(getContentResolver() , //Uri.parse(mCurrentPhotoPath));
//}
//catch (Exception e)
//{
//handle exception
//}
imageView.setImageBitmap(bitmap);
new ImageSaver(getApplicationContext()).
setFileName("currentImage.png").
setDirectoryName("Android_Upload").
save(bitmap);
Model.currentImage = "currentImage.png";
}
This works fine when viewed on the device. But after its sent to the server and viewed from there, the image size is too small.
ImageSaver class pretty much saves the image elsewhere and compresses it but with 100 quality in png.I do this, so I can later the image in the database as Blob(again with 100 quality)
How can I decode the image and show the image in the image view but without losing quality (and the size?)
Apparently, you have scaled down your image while decoding.
You may want to remove the following line:
bmOptions.inSampleSize = scaleFactor;

Image from ACTION_IMAGE_CAPTURE Rotated

I am trying to simply get an image from a phone's camera. Surprisingly, it returns rotated. I've scoured the internet for fixes and came across many solutions using ExifInterface, but it only works sometimes. It gets the orientation wrong seemingly randomly, as I merely recompile and see different results. I have found some people saying this is a fault of the class itself being bugged.
I found other solutions that require like two additional libraries and more java files to do the job, but that just seems ridiculous (and I am avoiding additional packages). How come images are rotated in the first place (in storage they are perfectly fine), and how hard can it possibly be to fix the issue? Also - rotating the Image View also works (and seems much easier than literally creating a rotated image), but I need to know by how much to rotate the view.
EDIT---- I realized that the image is consistently rotated 270 degrees clockwise from the orientation the image was taken in (inside the intent) if the back camera was used, and 90 degrees if the front camera was used. Thus I only really need a way to find out this orientation.
Intent called here:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = setUpPhotoFile();
mCurrentPhotoPath = photoFile.getAbsolutePath();
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
} catch (IOException ex) {
// Error occurred while creating the File
photoFile = null;
mCurrentPhotoPath = null;
}
// Continue only if the File was successfully created
if (photoFile != null) {
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
} else {
Toast noStorage = Toast.makeText(this, "Cannot access mounted storage.", Toast.LENGTH_SHORT);
noStorage.show();
}
}
}
Bitmap created here:
private void setPic() {
/* Get the size of the ImageView */
int targetW = mImageView.getWidth();
int targetH = mImageView.getHeight();
/* Get the size of the image */
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
bmOptions.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
int photoW = bmOptions.outWidth;
int photoH = bmOptions.outHeight;
/* Figure out which way needs to be reduced less */
int scale = 1;
if (photoH > targetH|| photoW > targetW) {
scale = Math.max(
(int)Math.pow(2, (int) Math.ceil(Math.log(targetW /
(double) photoW)) / Math.log(0.5)),
(int)Math.pow(2, (int) Math.ceil(Math.log(targetH /
(double) photoH)) / Math.log(0.5)));
;
}
/* Set bitmap options to scale the image decode target */
bmOptions.inJustDecodeBounds = false;
bmOptions.inSampleSize = scale;
/* Decode the JPEG file into a Bitmap */
Bitmap bitmap = BitmapFactory.decodeFile(mCurrentPhotoPath, bmOptions);
/*-----------How should I rotate bitmap/mImageView to correct orientation?*/
/* Associate the Bitmap to the ImageView */
mImageView.setImageBitmap(bitmap);
mImageView.setVisibility(View.VISIBLE);
}
The best solution I have found is this one:
https://www.samieltamawy.com/how-to-fix-the-camera-intent-rotated-image-in-android/
I post the link because I don't want all the credit.
Sami Eltamawy has written a function that rotate the image if its need to be rotated.
I try the code and is working on my devices that the image got rotated.

Android: How to change OpenGLES texture data / bitmap from gallery / camera

I try reuse Android Media Effects samples and want to be able to change texture data with new bitmap from camera or gallery pick. No solution so far
This is the initial load texture from the sample : https://github.com/googlesamples/android-MediaEffects/blob/master/Application/src/main/java/com/example/android/mediaeffects/MediaEffectsFragment.java
private void loadTextures() {
// Generate textures
GLES20.glGenTextures(2, mTextures, 0);
// Load input bitmap
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.puppy);
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
// Upload to texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set texture parameters
GLToolbox.initTexParams();
}
and this is my trouble function :
public void changeBackground(Uri bitmapUri) {
Log.d(TAG, "changeBackground : " + bitmapUri.getPath());
Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath());
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
GLUtils.texSubImage2D(GLES20.GL_TEXTURE_2D, 0, 0, 0, bitmap);
theBackground.requestRender(); //my GLSurfaceView
bitmap.recycle();
}
I tried several ways :
using texSubImage2D only -> texture not updated
delete and recreate textures with new bitmap -> black texture
note: the bitmap dimension is fixed, at 1080 x 1080
How to change/modify/replace texture data with new bitmap ?
UPDATE:
I think the problem more relate to this question : Setting texture on 3D object using image from photo gallery. i call changeBackground() after grabbing the image from gallery intent and then crop it (another intent).
Now, how to effectively change texture data with bitmap from gallery intent? anyone have a clue?
SOLVED
I solved the problem by defering texture load process to onSurfaceChange() function. Simply use a flag to indicate the file to load and onSurfaceChange check the flag again.
private Uri mFileToLoad = null;
public void changeBackground(Uri bitmapUri) {
Log.d(TAG, "changeBackground : " + bitmapUri.getPath());
mFileToLoad = bitmapUri;
theBackground.requestRender();
}
and my onSurfaceChange()
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.d(TAG, "onSurfaceChanged w:" + width + " h:" + height);
if (mFileToLoad!=null) {
GLES20.glDeleteTextures(mTextures.length, mTextures, 0);
GLES20.glGenTextures(mTextures.length, mTextures, 0);
Bitmap bitmap = BitmapFactory.decodeFile(mFileToLoad.getPath());
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
// Upload to texture
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// Set texture parameters
GLToolbox.initTexParams();
mFileToLoad = null;
bitmap.recycle();
}
if (mTexRenderer != null) {
mTexRenderer.updateViewSize(width, height);
}
}
So far it works.
It looks like your changeBackground() method is probably called from the UI thread, or at least a thread other than the rendering thread.
GLSurfaceView creates a separate rendering thread, which has a current OpenGL context when your rendering methods are called. It is therefore ready for your OpenGL calls. This is not the case for all other threads. The current OpenGL context is per thread. So unless you do something about it (which is possible, but adds significant complexity), you can't make OpenGL calls from other threads.
There are a few options to resolve this. The easiest one is probably using the queueEvent() method on the GLSurfaceView, which allows you to pass in a Runnable that will be executed in the rendering thread.
I'm not sure what the mTexRenderer.updateTextureSize() method in your code does. But generally, if the texture size changes, you'll have to use GLUtils.texImage2D() instead of GLUtils.texSubImage2D() to update the texture.
The code could look like this (untested, so it might not work exactly as typed):
final Bitmap bitmap = BitmapFactory.decodeFile(bitmapUri.getPath());
theBackground.queueEvent(new Runnable() {
#Override
void run() {
mImageWidth = bitmap.getWidth();
mImageHeight = bitmap.getHeight();
mTexRenderer.updateTextureSize(mImageWidth, mImageHeight);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextures[0]);
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
bitmap.recycle();
}
});
theBackground.requestRender();

Categories

Resources