fixed page identification in multipage HEIC with non-unique track IDs
This commit is contained in:
parent
ef528c4c90
commit
8fb349fc6e
5 changed files with 16 additions and 16 deletions
|
@ -593,10 +593,11 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
|
||||||
KEY_PAGE to i,
|
KEY_PAGE to i,
|
||||||
KEY_MIME_TYPE to trackMime,
|
KEY_MIME_TYPE to trackMime,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// do not use `MediaFormat.KEY_TRACK_ID` as it is actually not unique between tracks
|
||||||
|
// e.g. there could be both a video track and an image track with KEY_TRACK_ID == 1
|
||||||
|
|
||||||
format.getSafeInt(MediaFormat.KEY_IS_DEFAULT) { page[KEY_IS_DEFAULT] = it != 0 }
|
format.getSafeInt(MediaFormat.KEY_IS_DEFAULT) { page[KEY_IS_DEFAULT] = it != 0 }
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
|
||||||
format.getSafeInt(MediaFormat.KEY_TRACK_ID) { page[KEY_TRACK_ID] = it }
|
|
||||||
}
|
|
||||||
format.getSafeInt(MediaFormat.KEY_WIDTH) { page[KEY_WIDTH] = it }
|
format.getSafeInt(MediaFormat.KEY_WIDTH) { page[KEY_WIDTH] = it }
|
||||||
format.getSafeInt(MediaFormat.KEY_HEIGHT) { page[KEY_HEIGHT] = it }
|
format.getSafeInt(MediaFormat.KEY_HEIGHT) { page[KEY_HEIGHT] = it }
|
||||||
if (isVideo(trackMime)) {
|
if (isVideo(trackMime)) {
|
||||||
|
@ -875,7 +876,6 @@ class MetadataHandler(private val context: Context) : MethodCallHandler {
|
||||||
private const val KEY_HEIGHT = "height"
|
private const val KEY_HEIGHT = "height"
|
||||||
private const val KEY_WIDTH = "width"
|
private const val KEY_WIDTH = "width"
|
||||||
private const val KEY_PAGE = "page"
|
private const val KEY_PAGE = "page"
|
||||||
private const val KEY_TRACK_ID = "trackId"
|
|
||||||
private const val KEY_IS_DEFAULT = "isDefault"
|
private const val KEY_IS_DEFAULT = "isDefault"
|
||||||
private const val KEY_DURATION = "durationMillis"
|
private const val KEY_DURATION = "durationMillis"
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ class MultiTrackImageGlideModule : LibraryGlideModule() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiTrackImage(val context: Context, val uri: Uri, val trackId: Int?)
|
class MultiTrackImage(val context: Context, val uri: Uri, val trackIndex: Int?)
|
||||||
|
|
||||||
internal class MultiTrackThumbnailLoader : ModelLoader<MultiTrackImage, Bitmap> {
|
internal class MultiTrackThumbnailLoader : ModelLoader<MultiTrackImage, Bitmap> {
|
||||||
override fun buildLoadData(model: MultiTrackImage, width: Int, height: Int, options: Options): ModelLoader.LoadData<Bitmap> {
|
override fun buildLoadData(model: MultiTrackImage, width: Int, height: Int, options: Options): ModelLoader.LoadData<Bitmap> {
|
||||||
|
@ -52,9 +52,9 @@ internal class MultiTrackImageFetcher(val model: MultiTrackImage, val width: Int
|
||||||
|
|
||||||
val context = model.context
|
val context = model.context
|
||||||
val uri = model.uri
|
val uri = model.uri
|
||||||
val trackId = model.trackId
|
val trackIndex = model.trackIndex
|
||||||
|
|
||||||
val bitmap = MultiTrackMedia.getImage(context, uri, trackId)
|
val bitmap = MultiTrackMedia.getImage(context, uri, trackIndex)
|
||||||
if (bitmap == null) {
|
if (bitmap == null) {
|
||||||
callback.onLoadFailed(Exception("null bitmap"))
|
callback.onLoadFailed(Exception("null bitmap"))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -16,17 +16,17 @@ object MultiTrackMedia {
|
||||||
private val LOG_TAG = LogUtils.createTag(MultiTrackMedia::class.java)
|
private val LOG_TAG = LogUtils.createTag(MultiTrackMedia::class.java)
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.P)
|
@RequiresApi(Build.VERSION_CODES.P)
|
||||||
fun getImage(context: Context, uri: Uri, trackId: Int?): Bitmap? {
|
fun getImage(context: Context, uri: Uri, trackIndex: Int?): Bitmap? {
|
||||||
val retriever = StorageUtils.openMetadataRetriever(context, uri) ?: return null
|
val retriever = StorageUtils.openMetadataRetriever(context, uri) ?: return null
|
||||||
try {
|
try {
|
||||||
return if (trackId != null) {
|
return if (trackIndex != null) {
|
||||||
val imageIndex = trackIdToImageIndex(context, uri, trackId) ?: return null
|
val imageIndex = trackIndexToImageIndex(context, uri, trackIndex) ?: return null
|
||||||
retriever.getImageAtIndex(imageIndex)
|
retriever.getImageAtIndex(imageIndex)
|
||||||
} else {
|
} else {
|
||||||
retriever.primaryImage
|
retriever.primaryImage
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(LOG_TAG, "failed to extract image from uri=$uri trackId=$trackId", e)
|
Log.w(LOG_TAG, "failed to extract image from uri=$uri trackIndex=$trackIndex", e)
|
||||||
} finally {
|
} finally {
|
||||||
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
|
// cannot rely on `MediaMetadataRetriever` being `AutoCloseable` on older APIs
|
||||||
retriever.release()
|
retriever.release()
|
||||||
|
@ -34,7 +34,7 @@ object MultiTrackMedia {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun trackIdToImageIndex(context: Context, uri: Uri, trackId: Int): Int? {
|
private fun trackIndexToImageIndex(context: Context, uri: Uri, trackIndex: Int): Int? {
|
||||||
val extractor = MediaExtractor()
|
val extractor = MediaExtractor()
|
||||||
try {
|
try {
|
||||||
extractor.setDataSource(context, uri, null)
|
extractor.setDataSource(context, uri, null)
|
||||||
|
@ -42,7 +42,7 @@ object MultiTrackMedia {
|
||||||
var imageIndex = 0
|
var imageIndex = 0
|
||||||
for (i in 0 until trackCount) {
|
for (i in 0 until trackCount) {
|
||||||
val trackFormat = extractor.getTrackFormat(i)
|
val trackFormat = extractor.getTrackFormat(i)
|
||||||
if (trackId == trackFormat.getInteger(MediaFormat.KEY_TRACK_ID)) {
|
if (trackIndex == i) {
|
||||||
return imageIndex
|
return imageIndex
|
||||||
}
|
}
|
||||||
if (MimeTypes.isImage(trackFormat.getString(MediaFormat.KEY_MIME))) {
|
if (MimeTypes.isImage(trackFormat.getString(MediaFormat.KEY_MIME))) {
|
||||||
|
@ -50,7 +50,7 @@ object MultiTrackMedia {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(LOG_TAG, "failed to get image index for uri=$uri, trackId=$trackId", e)
|
Log.w(LOG_TAG, "failed to get image index for uri=$uri, trackIndex=$trackIndex", e)
|
||||||
} finally {
|
} finally {
|
||||||
extractor.release()
|
extractor.release()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.4.30'
|
ext.kotlin_version = '1.4.31'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
@ -71,7 +71,7 @@ class SinglePageInfo implements Comparable<SinglePageInfo> {
|
||||||
final index = map['page'] as int;
|
final index = map['page'] as int;
|
||||||
return SinglePageInfo(
|
return SinglePageInfo(
|
||||||
index: index,
|
index: index,
|
||||||
pageId: map['trackId'] as int ?? index,
|
pageId: index,
|
||||||
mimeType: map['mimeType'] as String,
|
mimeType: map['mimeType'] as String,
|
||||||
isDefault: map['isDefault'] as bool ?? false,
|
isDefault: map['isDefault'] as bool ?? false,
|
||||||
width: map['width'] as int ?? 0,
|
width: map['width'] as int ?? 0,
|
||||||
|
|
Loading…
Reference in a new issue