Skip to content

Commit

Permalink
#1037 use truncated preview when opening large DNG with metadata extr…
Browse files Browse the repository at this point in the history
…actor
  • Loading branch information
deckerst committed Jun 7, 2024
1 parent 981727c commit 1346e88
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
byGeoTiff[false]?.map { exifTagMapper(it) }?.let { dirMap.putAll(it) }
}

mimeType == MimeTypes.DNG -> {
mimeType == MimeTypes.DNG || mimeType == MimeTypes.DNG_ADOBE -> {
// split DNG tags in their own directory
val dngDirMap = metadataMap[DIR_DNG] ?: HashMap()
metadataMap[DIR_DNG] = dngDirMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ object Metadata {
return date.time + parseSubSecond(subSecond)
}

// Opening large PSD/TIFF files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
// Opening some large files yields an OOM (both with `metadata-extractor` v2.15.0 and `ExifInterface` v1.3.1),
// so we define an arbitrary threshold to avoid a crash on launch.
// It is not clear whether it is because of the file itself or its metadata.
private const val FILE_SIZE_MAX = 100 * (1 shl 20) // MB
Expand All @@ -136,6 +136,8 @@ object Metadata {
private fun getSafeUri(context: Context, uri: Uri, mimeType: String, sizeBytes: Long?): Uri {
return when (mimeType) {
// formats known to yield OOM for large files
MimeTypes.DNG,
MimeTypes.DNG_ADOBE,
MimeTypes.HEIC,
MimeTypes.HEIF,
MimeTypes.MP4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,20 @@ object Helper {
// e.g. "exif [...] 134 [...] 4578696600004949[...]"
private val PNG_RAW_PROFILE_PATTERN = Regex("^\\n(.*?)\\n\\s*(\\d+)\\n(.*)", RegexOption.DOT_MATCHES_ALL)

// providing the stream length is risky, as it may crash if it is incorrect
private const val SAFE_READ_STREAM_LENGTH = -1L

fun readMimeType(input: InputStream): String? {
val bufferedInputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
return FileTypeDetector.detectFileType(bufferedInputStream).mimeType
}

@Throws(IOException::class, ImageProcessingException::class)
fun safeRead(input: InputStream, sizeBytes: Long?): com.drew.metadata.Metadata {
fun safeRead(input: InputStream, @Suppress("unused_parameter") sizeBytes: Long?): com.drew.metadata.Metadata {
val inputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
val fileType = FileTypeDetector.detectFileType(inputStream)
val streamLength = sizeBytes ?: SAFE_READ_STREAM_LENGTH

// Providing the stream length is risky, as it may crash if it is incorrect.
// Not providing the stream length is also risky, as it may lead to OOM
// when `RandomAccessStreamReader` reads the entire stream to validate offsets.
val undefinedStreamLength = -1L

val metadata = when (fileType) {
FileType.Jpeg -> safeReadJpeg(inputStream)
Expand All @@ -84,9 +85,9 @@ object Helper {
FileType.Cr2,
FileType.Nef,
FileType.Orf,
FileType.Rw2 -> safeReadTiff(inputStream, streamLength)
FileType.Rw2 -> safeReadTiff(inputStream, undefinedStreamLength)

else -> ImageMetadataReader.readMetadata(inputStream, streamLength, fileType)
else -> ImageMetadataReader.readMetadata(inputStream, undefinedStreamLength, fileType)
}

metadata.addDirectory(FileTypeDirectory(fileType))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ object MimeTypes {
private const val CR2 = "image/x-canon-cr2"
private const val CRW = "image/x-canon-crw"
private const val DCR = "image/x-kodak-dcr"
const val DNG = "image/x-adobe-dng"
const val DNG = "image/dng"
const val DNG_ADOBE = "image/x-adobe-dng"
private const val ERF = "image/x-epson-erf"
private const val K25 = "image/x-kodak-k25"
private const val KDC = "image/x-kodak-kdc"
Expand Down Expand Up @@ -71,7 +72,7 @@ object MimeTypes {

fun isRaw(mimeType: String): Boolean {
return when (mimeType) {
ARW, CR2, CRW, DCR, DNG, ERF, K25, KDC, MRW, NEF, NRW, ORF, PEF, RAF, RAW, RW2, SR2, SRF, SRW, X3F -> true
ARW, CR2, CRW, DCR, DNG, DNG_ADOBE, ERF, K25, KDC, MRW, NEF, NRW, ORF, PEF, RAF, RAW, RW2, SR2, SRF, SRW, X3F -> true
else -> false
}
}
Expand Down Expand Up @@ -142,7 +143,7 @@ object MimeTypes {
return if (pageId != null && MultiPageImage.isSupported(mimeType)) {
true
} else when (mimeType) {
DNG, HEIC, HEIF, PNG, WEBP -> true
DNG, DNG_ADOBE, HEIC, HEIF, PNG, WEBP -> true
else -> false
}
}
Expand All @@ -151,7 +152,7 @@ object MimeTypes {
// according to EXIF orientation when decoding images of known formats
// but we need to rotate the decoded bitmap for the other formats
fun needRotationAfterContentResolverThumbnail(mimeType: String) = when (mimeType) {
DNG, PNG -> true
DNG, DNG_ADOBE, PNG -> true
else -> false
}

Expand Down

0 comments on commit 1346e88

Please sign in to comment.