diff --git a/android/app/build.gradle b/android/app/build.gradle index 81ee004c4..ad88be50b 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -236,7 +236,7 @@ dependencies { implementation 'com.github.deckerst:Android-TiffBitmapFactory:90c06eebf4' implementation 'com.github.deckerst.mp4parser:isoparser:4cc0c5d06c' implementation 'com.github.deckerst.mp4parser:muxer:4cc0c5d06c' - implementation 'com.github.deckerst:pixymeta-android:706bd73d6e' + implementation 'com.github.deckerst:pixymeta-android:9ec7097f17' // huawei flavor only huaweiImplementation "com.huawei.agconnect:agconnect-core:$huawei_agconnect_version" diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/PixyMetaHelper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/PixyMetaHelper.kt index eee140f28..200379383 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/PixyMetaHelper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/PixyMetaHelper.kt @@ -1,5 +1,7 @@ package deckers.thibault.aves.metadata +import android.content.Context +import android.net.Uri import deckers.thibault.aves.metadata.Metadata.TYPE_COMMENT import deckers.thibault.aves.metadata.Metadata.TYPE_EXIF import deckers.thibault.aves.metadata.Metadata.TYPE_ICC_PROFILE @@ -10,6 +12,8 @@ import deckers.thibault.aves.metadata.Metadata.TYPE_JPEG_DUCKY import deckers.thibault.aves.metadata.Metadata.TYPE_PHOTOSHOP_IRB import deckers.thibault.aves.metadata.Metadata.TYPE_XMP import deckers.thibault.aves.model.FieldMap +import deckers.thibault.aves.utils.MimeTypes +import deckers.thibault.aves.utils.StorageUtils import pixy.meta.meta.Metadata import pixy.meta.meta.MetadataEntry import pixy.meta.meta.MetadataType @@ -19,6 +23,7 @@ import pixy.meta.meta.iptc.IPTCRecord import pixy.meta.meta.jpeg.JPGMeta import pixy.meta.meta.xmp.XMP import pixy.meta.string.XMLUtils +import java.io.File import java.io.InputStream import java.io.OutputStream import java.util.* @@ -105,6 +110,48 @@ object PixyMetaHelper { fun XMP.extendedXmpDocString(): String = XMLUtils.serializeToString(extendedXmpDocument) + fun copyIptcXmp( + context: Context, + sourceMimeType: String, + sourceUri: Uri, + targetMimeType: String, + targetUri: Uri, + editableFile: File, + ) { + var pixyIptc: IPTC? = null + var pixyXmp: XMP? = null + if (MimeTypes.canReadWithPixyMeta(sourceMimeType)) { + StorageUtils.openInputStream(context, sourceUri)?.use { input -> + val metadata = Metadata.readMetadata(input) + if (MimeTypes.canEditIptc(targetMimeType)) { + pixyIptc = metadata[MetadataType.IPTC] as IPTC? + } + if (MimeTypes.canEditXmp(targetMimeType)) { + pixyXmp = metadata[MetadataType.XMP] as XMP? + } + } + } + if (pixyIptc != null || pixyXmp != null) { + editableFile.outputStream().use { output -> + if (pixyIptc != null) { + // reopen input to read from start + StorageUtils.openInputStream(context, targetUri)?.use { input -> + val iptcs = pixyIptc!!.dataSets.flatMap { it.value } + Metadata.insertIPTC(input, output, iptcs) + } + } + if (pixyXmp != null) { + // reopen input to read from start + StorageUtils.openInputStream(context, targetUri)?.use { input -> + val xmpString = pixyXmp!!.xmpDocString() + val extendedXmp = if (pixyXmp!!.hasExtendedXmp()) pixyXmp!!.extendedXmpDocString() else null + setXmp(input, output, xmpString, if (targetMimeType == MimeTypes.JPEG) extendedXmp else null) + } + } + } + } + } + fun removeMetadata(input: InputStream, output: OutputStream, metadataTypes: Set) { val types = metadataTypes.map(::toMetadataType).toTypedArray() Metadata.removeMetadata(input, output, *types) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt index 766c3b936..0c00d42fb 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt @@ -53,15 +53,12 @@ import deckers.thibault.aves.utils.MimeTypes.canEditExif import deckers.thibault.aves.utils.MimeTypes.canEditIptc import deckers.thibault.aves.utils.MimeTypes.canEditXmp import deckers.thibault.aves.utils.MimeTypes.canReadWithExifInterface -import deckers.thibault.aves.utils.MimeTypes.canReadWithPixyMeta import deckers.thibault.aves.utils.MimeTypes.canRemoveMetadata import deckers.thibault.aves.utils.MimeTypes.extensionFor import deckers.thibault.aves.utils.MimeTypes.isVideo import deckers.thibault.aves.utils.StorageUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import pixy.meta.meta.Metadata -import pixy.meta.meta.MetadataType import java.io.ByteArrayInputStream import java.io.File import java.io.FileOutputStream @@ -405,39 +402,7 @@ abstract class ImageProvider { } // copy IPTC / XMP via PixyMeta - - var pixyIptc: pixy.meta.meta.iptc.IPTC? = null - var pixyXmp: pixy.meta.meta.xmp.XMP? = null - if (canReadWithPixyMeta(sourceMimeType)) { - StorageUtils.openInputStream(context, sourceUri)?.use { input -> - val metadata = Metadata.readMetadata(input) - if (canEditIptc(targetMimeType)) { - pixyIptc = metadata[MetadataType.IPTC] as pixy.meta.meta.iptc.IPTC? - } - if (canEditXmp(targetMimeType)) { - pixyXmp = metadata[MetadataType.XMP] as pixy.meta.meta.xmp.XMP? - } - } - } - if (pixyIptc != null || pixyXmp != null) { - editableFile.outputStream().use { output -> - if (pixyIptc != null) { - // reopen input to read from start - StorageUtils.openInputStream(context, targetUri)?.use { input -> - val iptcs = pixyIptc!!.dataSets.flatMap { it.value } - Metadata.insertIPTC(input, output, iptcs) - } - } - if (pixyXmp != null) { - // reopen input to read from start - StorageUtils.openInputStream(context, targetUri)?.use { input -> - val xmpString = pixyXmp!!.xmpDocString() - val extendedXmp = if (pixyXmp!!.hasExtendedXmp()) pixyXmp!!.extendedXmpDocString() else null - PixyMetaHelper.setXmp(input, output, xmpString, if (targetMimeType == MimeTypes.JPEG) extendedXmp else null) - } - } - } - } + PixyMetaHelper.copyIptcXmp(context, sourceMimeType, sourceUri, targetMimeType, targetUri, editableFile) // copy Exif via ExifInterface