Remove or update exif thumbnail from image - android

Is there anyway to remove an exif thumbnail from an image?
I'm cropping images in my app and copying all exif data lossless with the sanselan library. Afterwards, I update width/height/rotation accordingly.
I could not find any way to update the exif thumbnail or to remove it, any ideas how to do that?

I have similar kind of problem of exif data
private void removeThumbnails(ContentResolver contentResolver, long photoId) {
try {
Cursor thumbnails = contentResolver.query(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Thumbnails.IMAGE_ID
+ "=?", new String[]{String.valueOf(photoId)}, null);
if (thumbnails != null) {
for (thumbnails.moveToFirst(); !thumbnails.isAfterLast() && !thumbnails.isBeforeFirst(); thumbnails.moveToNext()) {
long thumbnailId = thumbnails.getLong(thumbnails.getColumnIndex(MediaStore.Images.Thumbnails._ID));
String path = thumbnails.getString(thumbnails.getColumnIndex(MediaStore.Images.Thumbnails.DATA));
File file = new File(path);
if (file.delete()) {
contentResolver.delete(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, MediaStore.Images.Thumbnails._ID + "=?",
new String[]{String.valueOf(thumbnailId)});
}
}
thumbnails.close();
}
} catch (Exception e) {
}
}
So I have removed the thumbnail of it first then done the operation on the image
So u can try removing the thumbnail and try to crop it after

Related

Android: How do I get thumbnail from a Video (Uri)

I want thumbnail from a video at any specific position. I am using ThumbnailUtils in order to get thumbnail from video uri and assigning to bitmap but I am getting null value on bitmap.
Any reasons how this is happening and how do I fix this?
selectedVideoUri = data.getData();
bitmap = ThumbnailUtils.createVideoThumbnail(getRealPathFromURI(videoUri),
MediaStore.Images.Thumbnails.MINI_KIND);
public String getRealPathFromURI(Uri contentUri) {
String res = null;
String[] proj = { MediaStore.Images.Media.DATA };
Cursor cursor = getContentResolver().query(contentUri, proj, null, null, null);
if(cursor.moveToFirst()){;
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
res = cursor.getString(column_index);
}
cursor.close();
return res;
}
You can use Glide to load thumb directly to imageview
Glide.with(activity).load(videoPath).into(imageview);
First Load Video List with its path in Your array list using below method
private void loadData(String currentAppPath) {
hiddenpath = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + currentAppPath);
String[] fileName = hiddenpath.list();
try{
for(String f : fileName){
if(HelpperMethods.isVideo(f)){
videoFiles.add(hiddenpath.getAbsolutePath()+"/"+f);
}
}
new Loader().loadImages(Environment.getExternalStorageState());
}catch (Exception e){
}
}
You need Loader().loadImages method so i declare this method in separate class file. see below code
public class Loader {
String[] imagieFiles;
public void loadImages(String path){
Log.e("path",path);
System.out.println(path);
} }
Then after You can use below Code to Get Video Thumbnail. By default Each Video Store two size Thumbnail.
1) MINI -- MediaStore.Images.Thumbnails.MINI_KIND and
2) MICRO -- MediaStore.Images.Thumbnails.MICRO_KIND
Bitmap thumb = ThumbnailUtils.createVideoThumbnail(filePath,
MediaStore.Images.Thumbnails.MINI_KIND);
BitmapDrawable bitmapDrawable = new BitmapDrawable(thumb);
contentViewHolder.videoView.setImageBitmap(thumb);
This is supported by Android natively using MediaPlayer SeekTo method
If you just want to show the video placeholder to display then you can use below code:
video_view.setVideoPath(videoPath);
video_view.seekTo(3000); // in milliseconds i.e. 3 seconds
ThumbnailUtils returns null when file or video is corrupted.
but I wanted to only use Uri and this is a good solution to do this:
val mmr = MediaMetadataRetriever()
mmr.setDataSource(videoUri)
val thummbnailBitmap = mmr.frameAtTime
imageView.setImageBitmap(thummbnailBitmap)

Get the latest image from external storage in android

I want to load the latest image from the external storage in Android.
Do you have any ideas how to get the name of the latest image?
Currently, I load a certain picture from the gallery this way:
File externalDirectory = Environment.getExternalStorageDirectory();
File directory = new File (externalDirectory.getAbsolutePath());
File file = new File(directory, "pic.jpg");
FileInputStream streamIn = null;
try {
streamIn = new FileInputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
So is there a way to load the latest?
String[] projection = new String[]{
MediaStore.Images.ImageColumns._ID,
MediaStore.Images.ImageColumns.DATA,
MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, //the album it in
MediaStore.Images.ImageColumns.DATE_TAKEN,
MediaStore.Images.ImageColumns.MIME_TYPE
};
final Cursor cursor = getContext().getContentResolver()
.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null,
null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
// Put it in the image view
if (cursor.moveToFirst()) {
final ImageView imageView = (ImageView) findViewById(R.id.pictureView);
String imageLocation = cursor.getString(1);
File imageFile = new File(imageLocation);
if (imageFile.exists()) { // TODO: is there a better way to do this?
Bitmap bm = BitmapFactory.decodeFile(imageLocation);
imageView.setImageBitmap(bm);
}
}
Use content resolver
Updated :
if you mean you want to load an image from a certain directory you create for storing image you need to make sure in every device that certain directory is created. You can use a while loop to loop through all the image by checking wether the BUCKET_DISPLAY_NAME also known as album have the same name to your created album. If yes get the first picture since you already order it by descending order sort by date time.
int albumColumn = cur.getColumnIndexOrThrow(MediaStore.Images.Media.BUCKET_DISPLAY_NAME);
do{
String album = cur.getString(albumColumn);
if(album == "YOUR CREATE DIR"){
break;
}
}while(cursor.moveToNext());
Integrate this code with the above code with your own logic. Basically the BUCKET_DISPLAY_NAME is the album which I mention earlier.
you may try this
String path = "/mnt/sdcard/Videos/Videoname"; // Your path
String fileName = new File(path).getName(); // you file name

Is it possible to retrieve images from gallery that is captured by camera in a certain time span

I'm working on a project on which I need to retrieve images from gallery that is captured by camera in a certain time span. Please advice a way to do this.
Thanks.
Edit:
Here is what I found,
You can make use of ExifInterface. Here is the doc.
First, retrieve images taken by camera by using this
Then get the real path of images by using this
private String getRealPathFromURI(Uri contentURI, Activity activity) {
Cursor cursor = activity.getContentResolver()
.query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file
// path
return contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
return cursor.getString(idx);
}
}
Now use this to get the time the image captures using the following code
String currentImageFile = Utility.getRealPathFromURI(flyerUri, getActivity());
ExifInterface ei = null;
try {
ei = new ExifInterface(currentImageFile);
if(ei != null)
{
Log.e("","---> date and time "+ei.getAttribute(ExifInterface.TAG_DATETIME));
}
} catch (IOException e) {
e.printStackTrace();
}
Now you have the images captured by camera and time the picture was taken. Use it according to your requirement. :)

Android Gallery doesn't support streamed files

In my app the user can select files and open them in the appropriate app (using an ACTION_VIEW intent).
I need to do some work on the data before giving it to the other app. So I'm using a streaming solution : I implemented a ContentProvider that implements openTypedAssetFile and writeDataToPipe (this method fills the output ParcelFileDescriptor created by openPipeHelper).
This works : I can open .pdf files, .txt files etc. The streaming seems correct.
I can open images usings 3-party apps.
However when I open an image using the Gallery, it doesn't work (Gallery shows a black screen), and I get the following exception :
fail to open myfile.jpg
UriImage(21890): java.io.FileNotFoundException: Not a whole file
I had a look at the Gallery source (here) and I could see that the exception is thrown here :
try {
if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
InputStream is = mApplication.getContentResolver()
.openInputStream(mUri);
mRotation = Exif.getOrientation(is);
Utils.closeSilently(is);
}
**mFileDescriptor = mApplication.getContentResolver()
.openFileDescriptor(mUri, "r");**
if (jc.isCancelled()) return STATE_INIT;
return STATE_DOWNLOADED;
} catch (FileNotFoundException e) {
Log.w(TAG, "fail to open: " + mUri, e);
return STATE_ERROR;
}
However, once in the Gallery app, if I select "Set as wallpaper", then I can see my image, it is then well streamed. So the problem appears when Gallery opens.
After a deeper look (in the ContentResolver code etc.) I couldn't understand why it behaves this way. It seems that Gallery does not support streaming files. Is that right ?
Do you have any idea ?
Thanks a lot.
String scheme = mUri.getScheme();
ContentResolver contentResolver = getContentResolver();
// If we are sent file://something or
// content://org.openintents.filemanager/mimetype/something...
if (scheme.equals("file")
|| (scheme.equals("content") && fileUri
.getEncodedAuthority().equals(
"org.openintents.filemanager"))) {
// Get the path
filePath = fileUri.getPath();
// Trim the path if necessary
// openintents filemanager returns
// content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.jpg
if (filePath.startsWith("/mimetype/")) {
String trimmedFilePath = filePath
.substring("/mimetype/".length());
filePath = trimmedFilePath.substring(trimmedFilePath
.indexOf("/"));
}
} else if (scheme.equals("content")) {
// If we are given another content:// URI, look it up in the
// media provider
filePath = getFilePathFromContentUri(fileUri,
contentResolver);
} else {
Log.e("filePath--------->>>>>", filePath + "");
}
and
private String getFilePathFromContentUri(Uri selectedVideoUri,
ContentResolver contentResolver) {
String filePathString;
String[] filePathColumn = { MediaColumns.DATA };
Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn,
null, null, null);
cursor.moveToFirst();
int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePathString = cursor.getString(columnIndex);
cursor.close();
return filePathString;
}
and now use this filepath ..
try {
if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) {
InputStream is = mApplication.getContentResolver()
.openInputStream(filePath); // ** change is here
mRotation = Exif.getOrientation(is);
Utils.closeSilently(is);
}
** mFileDescriptor = mApplication.getContentResolver()
.openFileDescriptor(filePath, "r"); **
if (jc.isCancelled()) return STATE_INIT;
return STATE_DOWNLOADED;
} catch (FileNotFoundException e) {
Log.w(TAG, "fail to open: " + mUri, e);
return STATE_ERROR;
}
this is work for me

Refreshing the thumbnail using MediaScanner

When I save an image to new location and then use MediaScanner to refresh the gallery then everything is fine - thumbnails and images are refreshed well.
But when I save an image to EXISTING location and then use MediaScanner - then only 'new' thumbnail isnt refreshed. (even though file is overwritten).
How to solve it?
Here is my code :
File file = new File(SDCARD_PATH, filename);
try {
FileOutputStream out = new FileOutputStream(file);
bmp.compress(format, BEST_IMAGE_QUALITY, out);
}catch (FileNotFoundException e) {
}
//refreshing single file using media scanner, no need to paste
This is a common and well know problem in Android. If you edit a media file, the thumbnail does not seem to update.
I have a fix for this, however, its still a fix and not a clean solution.
My fix is simple, and it basically deletes the stale thumbnail and then uses media scanner to update the thumbnails.
Here're the steps to be followed:
Step 1. Edit the file as you like. Say filename, "myVideoToBeEdited".
Step 2. Once you are done editing, delete its existing thumbnail.
First, get the video id using code like this:
final String[] columns = {
BaseColumns._ID, MediaColumns.DATA
};
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, columns, null, null, null);
boolean cancel = false;
if(null != cursor){
while(cursor.moveToNext() && !cancel){
String fileName = cursor.getString(cursor.getColumnIndex(MediaColumns.DATA));
int imageId = cursor.getInt(cursor.getColumnIndex(BaseColumns._ID));
if(fileName.equals(myVideoToBeEdited)){
removeVideoThumbnail(getContentResolver(), imageId); // step 3
cancel = true;
}
}
}
There are other ways to get the id, and more optimised ones as well.
Step 3. Delete the thumbnail.
public void removeVideoThumbnail(ContentResolver contentResolver, long photoId) {
Cursor thumbnails = contentResolver.query(android.provider.MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI, null, android.provider.MediaStore.Video.Thumbnails.VIDEO_ID + "=?", new String[]{String.valueOf(photoId)}, null);
for (thumbnails.moveToFirst(); !thumbnails.isAfterLast(); thumbnails.moveToNext()) {
long thumbnailId = thumbnails.getLong(thumbnails.getColumnIndex(android.provider.MediaStore.Video.Thumbnails._ID));
String path = thumbnails.getString(thumbnails.getColumnIndex(android.provider.MediaStore.Video.Thumbnails.DATA));
File file = new File(path);
if (file.delete()) {
contentResolver.delete(android.provider.MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI, android.provider.MediaStore.Video.Thumbnails._ID + "=?", new String[]{String.valueOf(thumbnailId)});
}
}
}
Or, here's the method to delete image thumbnail
public void removeImageThumbnail(ContentResolver contentResolver, long photoId) {
Cursor thumbnails = contentResolver.query(android.provider.MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, null, android.provider.MediaStore.Images.Thumbnails.IMAGE_ID + "=?", new String[]{String.valueOf(photoId)}, null);
for (thumbnails.moveToFirst(); !thumbnails.isAfterLast(); thumbnails.moveToNext()) {
long thumbnailId = thumbnails.getLong(thumbnails.getColumnIndex(android.provider.MediaStore.Images.Thumbnails._ID));
String path = thumbnails.getString(thumbnails.getColumnIndex(android.provider.MediaStore.Images.Thumbnails.DATA));
File file = new File(path);
if (file.delete()) {
contentResolver.delete(android.provider.MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, android.provider.MediaStore.Images.Thumbnails._ID + "=?", new String[]{String.valueOf(thumbnailId)});
}
}
}
Step 4. And finally use media scanner connection to scan the file so that it updates the thumbnails.
MediaScannerConnection.scanFile(context,
new String[] { myVideoToBeEdited }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {
// pass the mime type, else passing a null will enable file extension to dictate the mime type
// you are good to go
}
});
Have you tried to remove the "old" picture prior to saving the new one to file system? Like so:
File file = new File(SDCARD_PATH, filename);
try {
// Delete the "old" file.
if (file.exists()) {
file.delete();
}
FileOutputStream out = new FileOutputStream(file);
bmp.compress(format, BEST_IMAGE_QUALITY, out);
}catch (FileNotFoundException e) {
}catch (SecurityException e) {
}

Categories

Resources