There are a couple of solutions on how to get thumbnail from the full image, such as
android get thumbnail of image stored on sdcard whose path is known
However, I need on the contrary to receive full image Uri from a Thumbnail Uri (or thumbnail id).
Here is how I get thumbnails:
fun getGalleryImages(): List<LocalImage> {
val baseUri: Uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI
val listOfAllImages = ArrayList<LocalImage>()
// Set up an array of the Thumbnail Image ID column we want
val projection = arrayOf(MediaStore.Images.Thumbnails._ID, MediaStore.Images.Thumbnails.IMAGE_ID)
// Create the cursor pointing to the SDCard
val cursor = context.contentResolver.query(
baseUri,
projection,
null,
null,
null)
// Get the column index of the Thumbnails Image ID
val thumbColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID)
val fullColumnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails.IMAGE_ID)
var thumbnailUri: Uri?
while (cursor.moveToNext()) {
val thumbId = cursor.getString(thumbColumnIndex)
thumbnailUri = Uri.withAppendedPath(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + thumbId)
// here I save image id for later retrieving full image
val imageId = cursor.getString(fullColumnIndex)
listOfAllImages.add(LocalImage(thumbnailUri = thumbnailUri), imId = imageId)
}
cursor.close()
return listOfAllImages
}
And then I have to retrieve a full image by image id (or by thumbnail Uri)
private fun getFullImage(imageId: String): Uri {
val projection = arrayOf(MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA)
val cursor = context.contentResolver.query(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
projection,
MediaStore.Images.Media._ID + "=?",
arrayOf(imageId),
null)
val columnIndex = cursor.getColumnIndex(projection[0])
if (cursor.moveToFirst()) {
return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + cursor.getString(1))
}
cursor.close()
return Uri.EMPTY
}
This returns me a Uri which looks realistic:
content://media/external/images/media//storage/emulated/0/DCIM/Camera/IMG_20170720_085045.jpg
However, the Uri seems to be invalid since I cannot retrieve the image from it:
val bitmap = MediaStore.Images.Media.getBitmap(activity.contentResolver, image.imageUri)
java.lang.IllegalStateException: Unknown URL: content://media/external/images/media//storage/emulated/0/DCIM/Camera/IMG_20170720_085045.jpg
at android.os.Parcel.readException(Parcel.java:1950)
at android.database.DatabaseUtils.readExceptionFromParcel(DatabaseUtils.java:183)
at android.database.DatabaseUtils.readExceptionWithFileNotFoundExceptionFromParcel(DatabaseUtils.java:146)
at android.content.ContentProviderProxy.openTypedAssetFile(ContentProviderNative.java:698)
Picasso also fails to load image from this Uri
add this code after you get Uri of image.
if (largeImagePath != null) {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inSampleSize = OG;
thumbnail = BitmapFactory.decodeFile((largeImagePath), opts);
System.gc();
if (thumbnail != null) {
try {
thumbnail = Common.rotateImageIfRequired(mContext, thumbnail, Uri.fromFile(new File(largeImagePath)));
} catch (IOException e) {
e.printStackTrace();
}
imageCam(thumbnail);
}
}
public void imageCam(Bitmap thumbnail) {
Bitmap photo = thumbnail;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
photo.compress(Bitmap.CompressFormat.JPEG, 100, bos);
byte b[] = bos.toByteArray();
encodedImage = Base64.encodeToString(b, Base64.DEFAULT);
ll_preview.setVisibility(View.VISIBLE);
img_preview.setVisibility(View.VISIBLE);
img_preview.setImageBitmap(photo);
}
in Common.java file add this method in it.
/**
* Rotate an image if required.
*
* #param img The image bitmap
* #param selectedImage Image URI
* #return The resulted Bitmap after manipulation
*/
public static Bitmap rotateImageIfRequired(Context mContext, Bitmap img, Uri selectedImage) throws IOException {
InputStream input = mContext.getContentResolver().openInputStream(selectedImage);
ExifInterface ei;
if (Build.VERSION.SDK_INT > 23)
ei = new ExifInterface(input);
else
ei = new ExifInterface(selectedImage.getPath());
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotateImage(img, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotateImage(img, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotateImage(img, 270);
default:
return img;
}
}
I think this will solve your problem
Related
I am attempting to upload an image from an android application to the server. I am calling the upload function and trying to get the image from ImageVeiw but no success. The image is set on the ImageVeiw from the gallery or camera.
Unable to get the file to send to the server
This is my code that I am using to set image from camera and gallery.
if(requestCode == CAMERA_REQUEST & resultCode == RESULT_OK){
Log.d("camera/gallery", "camera");
Bitmap photo = (Bitmap) data.getExtras().get("data");
profilePicture.setImageBitmap(photo);
} else if (requestCode == RESULT_LOAD_IMAGE && resultCode == RESULT_OK && null != data) {
Log.d("camera/gallery", "gallery");
// get image from gallery
Uri selectedImage = data.getData();
String[] filePathColumn = { MediaStore.Images.Media.DATA };
Cursor cursor = getActivity().getContentResolver().query(selectedImage,filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
String picturePath = cursor.getString(columnIndex);
cursor.close();
Bitmap loadedBitmap = BitmapFactory.decodeFile(picturePath);
// check orientation of image and rotate if required
ExifInterface exifInterface = null;
try{
File pictureFile = new File(picturePath);
exifInterface = new ExifInterface(pictureFile.getAbsolutePath());
} catch (IOException e){
e.printStackTrace();
}
int orientation = exifInterface.ORIENTATION_NORMAL;
if(exifInterface != null){
orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
}
switch(orientation){
case ExifInterface.ORIENTATION_ROTATE_90:
loadedBitmap = rotateBitmap(loadedBitmap, 90);
break;
case ExifInterface.ORIENTATION_ROTATE_180:
loadedBitmap = rotateBitmap(loadedBitmap, 180);
break;
case ExifInterface.ORIENTATION_ROTATE_270:
loadedBitmap = rotateBitmap(loadedBitmap, 270);
break;
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
loadedBitmap = flipBitmap(loadedBitmap, true, false);
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
loadedBitmap = flipBitmap(loadedBitmap, false, true);
default:
loadedBitmap = loadedBitmap;
}
// set image to ImageView
profilePicture.setImageBitmap(loadedBitmap);
}
I am able to get the bitmap image and trying to save it to the file. I am later trying to retrieve the same file and upload it to the server using retrofit
I am getting this error from retrofit on failure
W/System.err: java.io.FileNotFoundException: file:/data/user/0/com.example.fileuploaddemo/files/cleaton_profile_20191023T111341.png (No such file or directory)
Code for storing and retrieving the file and send the image file
public void uploadProfileImage(){
Uri fileUri = getSelectedFile();
if(Uri.EMPTY.equals(fileUri)){
Toast.makeText(this, "Exception Occurred", Toast.LENGTH_SHORT).show();
} else {
File originalFile = FileUtils.getFile(fileUri.toString());
Log.d(TAG, "in upload"+originalFile.getAbsolutePath());
RequestBody filePart = RequestBody.create(MediaType.parse("image/*"), originalFile);
MultipartBody.Part file = MultipartBody.Part.createFormData("upload", originalFile.getName(), filePart);
RequestBody modePart = RequestBody.create(MultipartBody.FORM, "profilepicture");
APIInterface apiInterface = APIClient.getClient().create(APIInterface.class);
apiInterface.uploadPhoto(file, modePart).enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Toast.makeText(MainActivity.this, "File Uploaded", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(MainActivity.this, "Upload Fail", Toast.LENGTH_SHORT).show();
t.printStackTrace();
}
});
}
}
public Uri getSelectedFile(){
try{
String username = "cleaton";
// get bitmap from image set on imageview and convert to byte array
BitmapDrawable bitmapDrawable = (BitmapDrawable) profilePicture.getDrawable();
Bitmap bitmap = bitmapDrawable.getBitmap();
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 80, byteArrayOutputStream);
byte[] bitmapdata = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.flush();
byteArrayOutputStream.close();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd'T'HHmmss");
String timeStamp = dateFormat.format(new Date());
File file = new File(getFilesDir(), username+"_profile_"+timeStamp+".png");
// insert byte array into file output stream with name
FileOutputStream fileOutputStream = openFileOutput(username+"_profile_"+timeStamp+".png", MODE_PRIVATE);
fileOutputStream.write(bitmapdata);
fileOutputStream.flush();
fileOutputStream.close();
File profileImageFile = new File(file.getAbsolutePath());
Log.d(TAG, "file retrieve"+profileImageFile);
Uri fileUri = Uri.fromFile(profileImageFile);
Log.d(TAG, "file Uri"+fileUri);
return fileUri;
} catch(FileNotFoundException fnfe){
fnfe.printStackTrace();
return null;
}
catch(IOException ioe){
ioe.printStackTrace();
return null;
}
}
To expound on Webfreak's answer:
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Once the Bitmap is retrieved, you can create a byte stream from which you can read the bytes and send those to your network socket by using a method similar to those below. Without knowing your upload method I am not sure if this is sufficient.
private InputStream getBitmapInputStream(BitmapFactory.Options options,
Bitmap bitmap) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(getCompressionFormat(options), 100 /*ignored for PNG*/, bos);
byte[] bitmapdata = bos.toByteArray();
return new ByteArrayInputStream(bitmapdata);
}
private Bitmap.CompressFormat getCompressionFormat(BitmapFactory.Options options) {
if (options == null || options.outMimeType == null) return Bitmap.CompressFormat.JPEG;
if (options.outMimeType.endsWith("/png")) {
return Bitmap.CompressFormat.PNG;
} else if (options.outMimeType.endsWith("/webp")) {
return Bitmap.CompressFormat.WEBP;
} else {
return Bitmap.CompressFormat.JPEG;
}
}
Fist you need to get the bitmap from Imageview:
BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
Bitmap bitmap = drawable.getBitmap();
Once you have bitmap, you can upload it to server.
In my app, am trying to let the user select an image from the phone storage and display it. Trying to do so, I've faced a problem that the image is returned rotated. So after some search I found some code snippets that helped me to do it right. But testing the same strategy on images selected from google drive or any cloud storage gives an error.
Here are the code snippets I use to get the absolute path and modify the image rotation.
private static String getRealPathFromURI(Context context, Uri uri) {
String filePath = "";
String wholeID = DocumentsContract.getDocumentId(uri);
Log.d("here", wholeID);
// Split at colon, use second item in the array
String id = wholeID.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
// where id is equal to
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ id }, null);
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
filePath = cursor.getString(columnIndex);
}
cursor.close();
Log.d("here", filePath);
return filePath;
}
public static Bitmap modifyOrientation(Bitmap bitmap, String image_absolute_path) throws IOException {
ExifInterface ei = new ExifInterface(image_absolute_path);
int orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
return rotate(bitmap, 90);
case ExifInterface.ORIENTATION_ROTATE_180:
return rotate(bitmap, 180);
case ExifInterface.ORIENTATION_ROTATE_270:
return rotate(bitmap, 270);
case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
return flip(bitmap, true, false);
case ExifInterface.ORIENTATION_FLIP_VERTICAL:
return flip(bitmap, false, true);
default:
return bitmap;
}
}
public static Bitmap rotate(Bitmap bitmap, float degrees) {
Matrix matrix = new Matrix();
matrix.postRotate(degrees);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
public static Bitmap flip(Bitmap bitmap, boolean horizontal, boolean vertical) {
Matrix matrix = new Matrix();
matrix.preScale(horizontal ? -1 : 1, vertical ? -1 : 1);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
And finally am using the modify method here, after getting a bitmap:
public static String encodeImgToBase64(Uri uri, Context context) throws IOException {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
inputStream = context.getContentResolver().openInputStream(uri);
options.inSampleSize = calculateInSampleSize(options, REQUIRED_WIDTH, REQUIRED_HEIGHT);
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeStream(inputStream, null, options);
inputStream.close();
bitmap = modifyOrientation(bitmap, getRealPathFromURI(context, uri));
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, byteArrayOutputStream);
byte[] imgByteArray = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return Base64.encodeToString(imgByteArray, Base64.DEFAULT);
}
So, my question is how to do the same thing on images selected from a cloud storage ?
You can try download the image, save in device tmp storage then you can use same method that you used for gallery image to it.
This is definitive fix for the Android's problem of duplicating a photo. Tested it on 2.3 (which has the bug), 4.x (which doesnt have the bug) and 5.x (which has the bug too).
The problem is that the photo is saved in two formats: usually one is the timestamp.jpg, and the other one is the full_date_and_time.jpg; sometimes in the same folder, sometimes in different folders. For example, "1430910805600.jpg" and "2015-05-06 11.14.00.jpg". Worstly, one cannot be converted to the other.
The fix uses code that i found in some questions here in StackOverflow, and also an improvement of my own.
First, you get the image with the URI you used to create the intent, get its added date, and delete it. Then, you get the last image added to the gallery, and compare with the added date of the original image. I delete it if difference is less than one second (its usually less than 10ms).
This is the code used to take the photo:
private static final int EXTCAMERA_RETURN = 1234324334;
private String imageFN; // stored globally but could be a parameter
...
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "tctemp.jpg");
values.put (MediaStore.Images.Media.IS_PRIVATE, 1);
capturedImageURI = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageURI);
startActivityForResult(intent, EXTCAMERA_RETURN);
And this is the one to grab the taken photo:
String[] projection = {MediaStore.Images.Media.DATA, BaseColumns._ID, MediaStore.Images.Media.DATE_ADDED};
Cursor cursor = managedQuery(capturedImageURI, projection, null, null, null);
cursor.moveToFirst();
String capturedImageFilePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
long date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
if (capturedImageFilePath == null || !AndroidUtils.copyFile(capturedImageFilePath,imageFN,cameraType == CAMERA_NATIVE_NOCOPY))
resultCode = RESULT_OK+1; // error
else
{
autoRotatePhoto(imageFN);
getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, BaseColumns._ID + "=" + cursor.getString(cursor.getColumnIndexOrThrow(BaseColumns._ID)), null);
try {new File(capturedImageFilePath).delete();} catch (Exception e) {} // on android 2.3 the code above does not work, so we just ensure that we delete the file
removeLastImageFromGallery(date);
}
This code is used to remove the last photo of the gallery IF the difference is less than one second
private void removeLastImageFromGallery(long orig)
{
try
{
final String[] imageColumns = { MediaStore.Images.Media._ID, MediaStore.Images.Media.DATE_ADDED };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
if (imageCursor.moveToFirst())
{
long last = imageCursor.getLong(imageCursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_ADDED));
int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
long dif = Math.abs(orig-last);
if (dif < 1) // 1 second - usually is less than 10ms
getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
}
}
catch (Exception e)
{
AndroidUtils.handleException(e, false);
}
}
Finally, the autorotate code is:
public static void autoRotatePhoto(String imagePath)
{
try
{
File f = new File(imagePath);
ExifInterface exif = new ExifInterface(f.getPath());
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
AndroidUtils.debug(imagePath+" -> "+orientation);
int angle = 0;
switch (orientation)
{
case ExifInterface.ORIENTATION_ROTATE_90: angle = 90; break;
case ExifInterface.ORIENTATION_ROTATE_180: angle = 180; break;
case ExifInterface.ORIENTATION_ROTATE_270: angle = 270; break;
default: return;
}
Matrix mat = new Matrix();
mat.postRotate(angle);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;
Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
Bitmap bitmap = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);
FileOutputStream out = new FileOutputStream(f);
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
out.close();
AndroidUtils.debug("auto-rotated "+imagePath);
}
catch (Exception e)
{
AndroidUtils.handleException(e, false);
}
}
The AndroidUtils.debug and handleException are used to dump the Log and print the exception. The copyFile is shown here:
public static boolean copyFile(String in, String out, boolean deleteOriginal)
{
try
{
byte[] buf = new byte[4096];
FileInputStream fin = new FileInputStream(in);
FileOutputStream fout = new FileOutputStream(out);
int r;
while ((r=fin.read(buf,0,buf.length)) > 0)
fout.write(buf,0,r);
fin.close();
fout.close();
if (deleteOriginal)
new File(in).delete();
return true;
}
catch (Exception e)
{
handleException(e,false);
return false;
}
}
Hi i'm developer in korea. I have some question so i enter this site.
InputStream is;
URL url =
new URL("http://112.216.25.58:8888/VOD_LAUNCHER/media/youtube_sample3.mp4");
Uri uri = Uri.parse(url.toURI().toString());
is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
//Bitmap bitmap = BitmapFactory.decodeFile(url.toString());
//MediaMetadataRetriever ret = new MediaMetadataRetriever();
//ret.setDataSource(url.toString());
//Bitmap bitmap = ret.getFrameAtTime(0);
//mImageView.setImageURI(uri);
//Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(uri.toString(), Thumbnails.MICRO_KIND);
mImageView.setImageBitmap(bitmap);
private Bitmap getPreview(URI uri) {
File image = new File(uri);
BitmapFactory.Options bounds = new BitmapFactory.Options();
bounds.inJustDecodeBounds = true;
BitmapFactory.decodeFile(image.getPath(), bounds);
if ((bounds.outWidth == -1) || (bounds.outHeight == -1))
return null;
int originalSize = (bounds.outHeight > bounds.outWidth) ? bounds.outHeight
: bounds.outWidth;
BitmapFactory.Options opts = new BitmapFactory.Options();
//opts.inSampleSize = originalSize / THUMBNAIL_SIZE;
return BitmapFactory.decodeFile(image.getPath(), opts);
}
private String getRealPathFromURI(Uri contentUri) {
String[] proj = { MediaStore.Images.Media.DATA };
CursorLoader loader = new CursorLoader(getApplicationContext(),
contentUri, proj, null, null, null);
Cursor cursor = loader.loadInBackground();
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
}
I try to use ThumbnailUtil and etc but it didn't work.
How to get ThumbnailImage on android 4.0?
Thanks any reply.
From API level 8 you can just do this:
String path = /*get video path*/;
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(path,
MediaStore.Images.Thumbnails.MINI_KIND);
Nice and simple :)
If you want to extract a frame of a video you should use this class. The code should be something like that:
MediaMetadataRetriever media = new MediaMetadataRetriever();
media.setDataSource(path);
Bitmap extractedImage = media.getFrameAtTime(time, option);
Hope it´s useful
Try This to get Thumbnail of a Video.
ImageView videoview;
Bitmap thumb = ThumbnailUtils.createVideoThumbnail("YOUR VIDEO STRING PATH", MediaStore.Images.Thumbnails.MINI_KIND);
Matrix matrix = new Matrix();
Bitmap bmThumbnail = Bitmap.createBitmap(thumb, 0, 0,
thumb.getWidth(), thumb.getHeight(), matrix, true);
videoview.setImageBitmap(bmThumbnail);
Edited: Use this method to get string path of Video URI.
/**
* Try to return the absolute file path of the Gallery video.
*
* #param context
* #param uri
* #return the file path or null
*/
public static String getVideoPathFromGallary(final Context context,Uri contentUri) {
String[] proj = { MediaStore.Video.Media.DATA, MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DURATION};
Cursor cursor = ((Activity) context).managedQuery(contentUri, proj, null, null, null);
if (cursor == null)
return null;
cursor.moveToFirst();
int column_index = cursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
int fileSize = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
long duration = TimeUnit.MILLISECONDS.toSeconds(cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION)));
System.out.println("size: " + fileSize);
System.out.println("duration: " + duration);
return cursor.getString(column_index);
}
very simple !!! you can use glide library.
first add an imageView on videoView and use the code below:
>
GlideApp.with(getApplicationContext()).load("empty")
.thumbnail(GlideApp.with(getApplicationContext()).load("videoURL"))
.into(imageView);
this code will download an image, and eventually, that leads to less internet consumption.
i can getting the image width through MediaStore.Images.Media normally
but i need to getting the image width and height from image which selected from dropbox
so currently i have following method to getting image size from dropbox
private void getDropboxIMGSize(Uri uri){
String size = Long.toString(new File(uri.getPath()).length());
return size;
}
but what i actually need are getting the file width and height value
anyone know how to achieve that?please help!
private void getDropboxIMGSize(Uri uri){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(uri.getPath()).getAbsolutePath(), options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
}
no there is no way. You have to create a Bitmap object. if you use the inJustDecodeBounds flag the bitmap would not be loaded in memory. In fact BitmapFactory.decodeFile will return null. In my example uri is the phisical path to the image
Blackbelt's answer is correct if you have a file uri. However, if you are using the new file providers as in the official camera tutorial, it won't work. This works for that case:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(
getContext().getContentResolver().openInputStream(mPhotoUri),
null,
options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
Blackbelt's answer will work most of the time using Options, but I would like to propose another solution or fallback solution by using the ExifInterface. If you have the image URI, you can create the ExifInterface using the full path, no need for Bitmap object nor BitmapFactory.Options.
ex.
int width = exif.getAttributeInt( ExifInterface.TAG_IMAGE_WIDTH, defaultValue );
int height = exif.getAttributeInt( ExifInterface.TAG_IMAGE_LENGTH, defaultValue );
the solution is use new File(uri.getPath()).getAbsolutePath() instead of uri.toString()
The accepted answer returns with me a 0 of width/height, by replacing uri.getPath() with uri.getLastPathSegment(), it returns the correct dimensions
public static int[] getImageDimension(Uri uri){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(uri.getLastPathSegment()).getAbsolutePath(), options);
return new int[]{options.outWidth, options.outHeight};
}
In addition to #Blackbelt answer you should use the following code to retrieve file path from Uri:
public static String getPathFromURI(Context context, Uri contentUri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
DocumentsContract.isDocumentUri(context, contentUri)) {
return getPathForV19AndUp(context, contentUri);
} else {
return getPathForPreV19(context, contentUri);
}
}
private static String getPathForPreV19(Context context, Uri contentUri) {
String[] projection = { MediaStore.Images.Media.DATA };
Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
try {
int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
return cursor.getString(columnIndex);
} finally {
cursor.close();
}
}
return null;
}
#TargetApi(Build.VERSION_CODES.KITKAT)
private static String getPathForV19AndUp(Context context, Uri contentUri) {
String documentId = DocumentsContract.getDocumentId(contentUri);
String id = documentId.split(":")[1];
String[] column = { MediaStore.Images.Media.DATA };
String sel = MediaStore.Images.Media._ID + "=?";
Cursor cursor = context.getContentResolver().
query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
column, sel, new String[]{ id }, null);
if (cursor != null) {
try {
int columnIndex = cursor.getColumnIndex(column[0]);
if (cursor.moveToFirst()) {
return cursor.getString(columnIndex);
}
} finally {
cursor.close();
}
}
return null;
}
For folks having content uri (starting with content://), open an InputStream & decode that stream to avoid getting 0 width and height. I'll use Kotlin
val uri: Uri = ....
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
val inputStream = contentResolver.openInputStream(uri)
BitmapFactory.decodeStream(inputStream, null, options)
val width = options.outWidth
val height = options.outHeight
Please use InputStream:
public int[] getImageSize(Uri uri){
try {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
InputStream input = this.getContentResolver().openInputStream(uri);
BitmapFactory.decodeStream(input, null, options); input.close();
return new int[]{options.outWidth, options.outHeight};
}
catch (Exception e){}
return new int[]{0,0};
}
It'll return in array form:
int[]{ width , height }
This is a concrete working example of the ExifInterface solution proposed by #simplatek, using an extension function on the Uri type:
fun Uri.getImageDimensions(context: Context): Pair<Int, Int> {
val inputStream = context.contentResolver.openInputStream(this)!!
val exif = ExifInterface(inputStream)
val width = exif.getAttributeInt(ExifInterface.TAG_IMAGE_WIDTH, defaultValue)
val height = exif.getAttributeInt(ExifInterface.TAG_IMAGE_LENGTH, defaultValue)
return Pair(width, height)
}
If you guys keep getting (0,0) in the width and height, you probably want to decode a stream, and not a file.
It probably because you're trying to read an image from the assets. Try this:
val b = BitmapFactory.decodeStream(context.assets.open("path/in/assets/img.png"))
val width = b.width
val height = b.height