Stefan Oltmann
10/09/2023, 7:04 AMNSData
into ByteArray
requires having both byte arrays in memory at a time. For class SkiaAppleImageLoader() : AbstractImageLoader() {
private val imageManager = PHImageManager.defaultManager()
private val fullImageRequestOptions = PHImageRequestOptions().apply {
deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat
resizeMode = PHImageRequestOptionsResizeModeNone
networkAccessAllowed = true
synchronous = true
}
fun loadFromSystemPhotoLibraryAsData(uri: String): NSData? {
val asset: PHAsset = PHAsset.fetchAssetsWithLocalIdentifiers(
identifiers = listOf(uri),
options = null
).firstObject as? PHAsset ?: return null
var imageData: NSData? = null
imageManager.requestImageDataAndOrientationForAsset(
asset = asset,
options = fullImageRequestOptions
) { result, _, _, _ ->
imageData = result
}
return imageData
}
@OptIn(ExperimentalForeignApi::class)
override suspend fun loadFullImageFromSystemPhotoLibrary(uri: String): ImageBitmap {
val nsData = loadFromSystemPhotoLibraryAsData(uri)
assertNotNull(nsData) { "Failed to load NSData for asset $uri" }
// FIXME Converting NSData into ByteArray causes having both in memory at a time.
val bytes = ByteArray(nsData.length.toInt()).apply {
usePinned {
memcpy(
__dst = it.addressOf(0),
__src = nsData.bytes,
__n = nsData.length
)
}
}
return Image.makeFromEncoded(bytes).toComposeImageBitmap()
}
}
private suspend fun readNSDataIncrementally(nsData: NSData): ByteArray {
val bufferSize = 4096 // Adjust the buffer size as needed
val byteArrayOutputStream = ByteArrayOutputStream()
val buffer = ByteArray(bufferSize)
nsData.bytes.usePinned { pinned ->
var bytesRead = 0
while (bytesRead < nsData.length.toInt()) {
val bytesToRead = min(bufferSize, nsData.length.toInt() - bytesRead)
val srcOffset = bytesRead.toLong()
memcpy(
__dst = buffer.refTo(0),
__src = (pinned.address + srcOffset).reinterpret(),
__n = bytesToRead.toLong()
)
byteArrayOutputStream.write(buffer, 0, bytesToRead)
bytesRead += bytesToRead
}
}
return byteArrayOutputStream.toByteArray()
}
Michael Paus
10/09/2023, 7:29 AMStefan Oltmann
10/09/2023, 7:31 AMMichael Paus
10/09/2023, 7:50 AMStefan Oltmann
10/09/2023, 7:56 AMSebastian Aigner
10/10/2023, 3:38 PM