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();
|
||||
}
|
||||
} 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();
|
||||
return;
|
||||
}
|
||||
|
@ -222,7 +222,7 @@ public abstract class ImageProvider {
|
|||
callback.onSuccess(newFields);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
@ -307,7 +307,7 @@ public abstract class ImageProvider {
|
|||
callback.onSuccess(newFields);
|
||||
});
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ public class ImageProviderFactory {
|
|||
switch (scheme) {
|
||||
case ContentResolver.SCHEME_CONTENT: // content://
|
||||
// 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();
|
||||
if (host != null) {
|
||||
switch (host) {
|
||||
|
|
|
@ -9,6 +9,16 @@ import android.os.Build;
|
|||
import android.provider.MediaStore;
|
||||
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.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
@ -20,6 +30,8 @@ import deckers.thibault.aves.utils.StorageUtils;
|
|||
import deckers.thibault.aves.utils.Utils;
|
||||
import io.flutter.plugin.common.EventChannel;
|
||||
|
||||
import static deckers.thibault.aves.utils.MetadataHelper.getOrientationDegreesForExifCode;
|
||||
|
||||
public class MediaStoreImageProvider extends ImageProvider {
|
||||
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);
|
||||
String path = cursor.getString(pathColumn);
|
||||
int width = cursor.getInt(widthColumn);
|
||||
// TODO TLAD sanitize mimeType
|
||||
// problem: some images were added as image/jpeg, but they're actually image/png
|
||||
// possible solution:
|
||||
// 1) check that MediaStore mimeType matches expected mimeType from file path extension
|
||||
// 2) extract actual mimeType with metadata-extractor
|
||||
// 3) update MediaStore
|
||||
if (width > 0) {
|
||||
newEntryHandler.handleEntry(
|
||||
new HashMap<String, Object>() {{
|
||||
put("uri", itemUri.toString());
|
||||
put("path", path);
|
||||
put("contentId", contentId);
|
||||
put("mimeType", cursor.getString(mimeTypeColumn));
|
||||
put("width", width);
|
||||
put("height", cursor.getInt(heightColumn));
|
||||
put("orientationDegrees", orientationColumn != -1 ? cursor.getInt(orientationColumn) : 0);
|
||||
put("sizeBytes", cursor.getLong(sizeColumn));
|
||||
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);
|
||||
}});
|
||||
entryCount++;
|
||||
} else {
|
||||
int height = cursor.getInt(heightColumn);
|
||||
int orientationDegrees = orientationColumn != -1 ? cursor.getInt(orientationColumn) : 0;
|
||||
if (width <= 0 || height <= 0) {
|
||||
// some images are incorrectly registered in the Media Store,
|
||||
// they are valid but miss some attributes, such as width, height, orientation
|
||||
try (InputStream is = activity.getContentResolver().openInputStream(itemUri)) {
|
||||
Metadata metadata = ImageMetadataReader.readMetadata(is);
|
||||
|
||||
// JPEG
|
||||
|
||||
JpegDirectory jpegDir = metadata.getFirstDirectoryOfType(JpegDirectory.class);
|
||||
if (jpegDir != null) {
|
||||
if (jpegDir.containsTag(JpegDirectory.TAG_IMAGE_WIDTH)) {
|
||||
width = jpegDir.getInt(JpegDirectory.TAG_IMAGE_WIDTH);
|
||||
}
|
||||
if (jpegDir.containsTag(JpegDirectory.TAG_IMAGE_HEIGHT)) {
|
||||
height = jpegDir.getInt(JpegDirectory.TAG_IMAGE_HEIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
// EXIF
|
||||
|
||||
ExifIFD0Directory exifDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
|
||||
if (exifDir != null) {
|
||||
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);
|
||||
// // some images are incorrectly registered in the MediaStore,
|
||||
// // they are valid but miss some attributes, such as width, height, orientation
|
||||
// try {
|
||||
// imageEntry.fixMissingWidthHeightOrientation(activity);
|
||||
// entrySink.success(imageEntry);
|
||||
// } catch (IOException e) {
|
||||
// // this is probably not a real image, like "/storage/emulated/0", so we skip it
|
||||
// Log.w(LOG_TAG, "failed to compute dimensions of imageEntry=" + imageEntry);
|
||||
// }
|
||||
} else {
|
||||
Map<String, Object> entryMap = new HashMap<String, Object>() {{
|
||||
put("uri", itemUri.toString());
|
||||
put("path", path);
|
||||
put("contentId", contentId);
|
||||
put("mimeType", cursor.getString(mimeTypeColumn));
|
||||
put("sizeBytes", cursor.getLong(sizeColumn));
|
||||
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();
|
||||
|
|
Loading…
Reference in a new issue