fix missing width/height for jpeg & mp4
This commit is contained in:
parent
298817d888
commit
ce878614cf
3 changed files with 79 additions and 38 deletions
|
@ -107,7 +107,7 @@ public abstract class ImageProvider {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.w(LOG_TAG, "failed to update MediaStore after renaming entry at path=" + oldPath, e);
|
Log.w(LOG_TAG, "failed to update Media Store after renaming entry at path=" + oldPath, e);
|
||||||
callback.onFailure();
|
callback.onFailure();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ public abstract class ImageProvider {
|
||||||
callback.onSuccess(newFields);
|
callback.onSuccess(newFields);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Log.w(LOG_TAG, "failed to update fields in MediaStore for uri=" + uri);
|
Log.w(LOG_TAG, "failed to update fields in Media Store for uri=" + uri);
|
||||||
callback.onSuccess(newFields);
|
callback.onSuccess(newFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ public abstract class ImageProvider {
|
||||||
callback.onSuccess(newFields);
|
callback.onSuccess(newFields);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Log.w(LOG_TAG, "failed to update fields in MediaStore for uri=" + uri);
|
Log.w(LOG_TAG, "failed to update fields in Media Store for uri=" + uri);
|
||||||
callback.onSuccess(newFields);
|
callback.onSuccess(newFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ public class ImageProviderFactory {
|
||||||
switch (scheme) {
|
switch (scheme) {
|
||||||
case ContentResolver.SCHEME_CONTENT: // content://
|
case ContentResolver.SCHEME_CONTENT: // content://
|
||||||
// a URI's authority is [userinfo@]host[:port]
|
// a URI's authority is [userinfo@]host[:port]
|
||||||
// but we only want the host when comparing to MediaStore's "authority"
|
// but we only want the host when comparing to Media Store's "authority"
|
||||||
String host = uri.getHost();
|
String host = uri.getHost();
|
||||||
if (host != null) {
|
if (host != null) {
|
||||||
switch (host) {
|
switch (host) {
|
||||||
|
|
|
@ -9,6 +9,16 @@ import android.os.Build;
|
||||||
import android.provider.MediaStore;
|
import android.provider.MediaStore;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.drew.imaging.ImageMetadataReader;
|
||||||
|
import com.drew.imaging.ImageProcessingException;
|
||||||
|
import com.drew.metadata.Metadata;
|
||||||
|
import com.drew.metadata.MetadataException;
|
||||||
|
import com.drew.metadata.exif.ExifIFD0Directory;
|
||||||
|
import com.drew.metadata.jpeg.JpegDirectory;
|
||||||
|
import com.drew.metadata.mp4.media.Mp4VideoDirectory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
@ -20,6 +30,8 @@ import deckers.thibault.aves.utils.StorageUtils;
|
||||||
import deckers.thibault.aves.utils.Utils;
|
import deckers.thibault.aves.utils.Utils;
|
||||||
import io.flutter.plugin.common.EventChannel;
|
import io.flutter.plugin.common.EventChannel;
|
||||||
|
|
||||||
|
import static deckers.thibault.aves.utils.MetadataHelper.getOrientationDegreesForExifCode;
|
||||||
|
|
||||||
public class MediaStoreImageProvider extends ImageProvider {
|
public class MediaStoreImageProvider extends ImageProvider {
|
||||||
private static final String LOG_TAG = Utils.createLogTag(MediaStoreImageProvider.class);
|
private static final String LOG_TAG = Utils.createLogTag(MediaStoreImageProvider.class);
|
||||||
|
|
||||||
|
@ -113,41 +125,70 @@ public class MediaStoreImageProvider extends ImageProvider {
|
||||||
Uri itemUri = ContentUris.withAppendedId(contentUri, contentId);
|
Uri itemUri = ContentUris.withAppendedId(contentUri, contentId);
|
||||||
String path = cursor.getString(pathColumn);
|
String path = cursor.getString(pathColumn);
|
||||||
int width = cursor.getInt(widthColumn);
|
int width = cursor.getInt(widthColumn);
|
||||||
// TODO TLAD sanitize mimeType
|
int height = cursor.getInt(heightColumn);
|
||||||
// problem: some images were added as image/jpeg, but they're actually image/png
|
int orientationDegrees = orientationColumn != -1 ? cursor.getInt(orientationColumn) : 0;
|
||||||
// possible solution:
|
if (width <= 0 || height <= 0) {
|
||||||
// 1) check that MediaStore mimeType matches expected mimeType from file path extension
|
// some images are incorrectly registered in the Media Store,
|
||||||
// 2) extract actual mimeType with metadata-extractor
|
// they are valid but miss some attributes, such as width, height, orientation
|
||||||
// 3) update MediaStore
|
try (InputStream is = activity.getContentResolver().openInputStream(itemUri)) {
|
||||||
if (width > 0) {
|
Metadata metadata = ImageMetadataReader.readMetadata(is);
|
||||||
newEntryHandler.handleEntry(
|
|
||||||
new HashMap<String, Object>() {{
|
// JPEG
|
||||||
put("uri", itemUri.toString());
|
|
||||||
put("path", path);
|
JpegDirectory jpegDir = metadata.getFirstDirectoryOfType(JpegDirectory.class);
|
||||||
put("contentId", contentId);
|
if (jpegDir != null) {
|
||||||
put("mimeType", cursor.getString(mimeTypeColumn));
|
if (jpegDir.containsTag(JpegDirectory.TAG_IMAGE_WIDTH)) {
|
||||||
put("width", width);
|
width = jpegDir.getInt(JpegDirectory.TAG_IMAGE_WIDTH);
|
||||||
put("height", cursor.getInt(heightColumn));
|
}
|
||||||
put("orientationDegrees", orientationColumn != -1 ? cursor.getInt(orientationColumn) : 0);
|
if (jpegDir.containsTag(JpegDirectory.TAG_IMAGE_HEIGHT)) {
|
||||||
put("sizeBytes", cursor.getLong(sizeColumn));
|
height = jpegDir.getInt(JpegDirectory.TAG_IMAGE_HEIGHT);
|
||||||
put("title", cursor.getString(titleColumn));
|
}
|
||||||
put("dateModifiedSecs", cursor.getLong(dateModifiedColumn));
|
}
|
||||||
put("sourceDateTakenMillis", cursor.getLong(dateTakenColumn));
|
|
||||||
put("bucketDisplayName", cursor.getString(bucketDisplayNameColumn));
|
// EXIF
|
||||||
put("durationMillis", durationColumn != -1 ? cursor.getLong(durationColumn) : 0);
|
|
||||||
}});
|
ExifIFD0Directory exifDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
|
||||||
entryCount++;
|
if (exifDir != null) {
|
||||||
} else {
|
if (exifDir.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
|
||||||
|
orientationDegrees = getOrientationDegreesForExifCode(exifDir.getInt(ExifIFD0Directory.TAG_ORIENTATION));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MP4
|
||||||
|
|
||||||
|
Mp4VideoDirectory mp4VideoDir = metadata.getFirstDirectoryOfType(Mp4VideoDirectory.class);
|
||||||
|
if (mp4VideoDir != null) {
|
||||||
|
if (mp4VideoDir.containsTag(Mp4VideoDirectory.TAG_WIDTH)) {
|
||||||
|
width = mp4VideoDir.getInt(Mp4VideoDirectory.TAG_WIDTH);
|
||||||
|
}
|
||||||
|
if (mp4VideoDir.containsTag(Mp4VideoDirectory.TAG_HEIGHT)) {
|
||||||
|
height = mp4VideoDir.getInt(Mp4VideoDirectory.TAG_HEIGHT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException | ImageProcessingException | MetadataException e) {
|
||||||
|
// this is probably not a real image, like "/storage/emulated/0", so we skip it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (width <= 0 || height <= 0) {
|
||||||
Log.w(LOG_TAG, "failed to get size for uri=" + itemUri + ", path=" + path);
|
Log.w(LOG_TAG, "failed to get size for uri=" + itemUri + ", path=" + path);
|
||||||
// // some images are incorrectly registered in the MediaStore,
|
} else {
|
||||||
// // they are valid but miss some attributes, such as width, height, orientation
|
Map<String, Object> entryMap = new HashMap<String, Object>() {{
|
||||||
// try {
|
put("uri", itemUri.toString());
|
||||||
// imageEntry.fixMissingWidthHeightOrientation(activity);
|
put("path", path);
|
||||||
// entrySink.success(imageEntry);
|
put("contentId", contentId);
|
||||||
// } catch (IOException e) {
|
put("mimeType", cursor.getString(mimeTypeColumn));
|
||||||
// // this is probably not a real image, like "/storage/emulated/0", so we skip it
|
put("sizeBytes", cursor.getLong(sizeColumn));
|
||||||
// Log.w(LOG_TAG, "failed to compute dimensions of imageEntry=" + imageEntry);
|
put("title", cursor.getString(titleColumn));
|
||||||
// }
|
put("dateModifiedSecs", cursor.getLong(dateModifiedColumn));
|
||||||
|
put("sourceDateTakenMillis", cursor.getLong(dateTakenColumn));
|
||||||
|
put("bucketDisplayName", cursor.getString(bucketDisplayNameColumn));
|
||||||
|
put("durationMillis", durationColumn != -1 ? cursor.getLong(durationColumn) : 0);
|
||||||
|
}};
|
||||||
|
entryMap.put("width", width);
|
||||||
|
entryMap.put("height", height);
|
||||||
|
entryMap.put("orientationDegrees", orientationDegrees);
|
||||||
|
newEntryHandler.handleEntry(entryMap);
|
||||||
|
entryCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cursor.close();
|
cursor.close();
|
||||||
|
|
Loading…
Reference in a new issue