compose-imageloader
compose-imageloader copied to clipboard
Load image using bytearray
Hi,
Can we load image from ByteArray in compose imageloader? if yes how we can do that?
Thanks
Actually it is not loading image from ios uri, I used compose-multiplatform-file-picker for picking the file from iOS files, then i use rememberImagePainter, it does not load image. I gets this error in the logs:
2024-01-06 14:37:54.858217+0530 KMPAppExample[9447:410797] [DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}
And this is the path of image which im getting from file picker and using in rememberImagePainter:
/Users/sunil/Library/Developer/CoreSimulator/Devices/F38BFB2D-6776-4B28-9D06-54D521E45237/data/Containers/Shared/AppGroup/8F44B401-AFFC-4219-ACFF-65142F2384AA/File Provider Storage/images (1)-536DD7B9-38CB-49E6-B42E-8FF33DB31BD5.JPEG
You can add a custom Fetcher like this:
class ByteArrayFetcher(
private val data: ByteArray,
) : Fetcher {
override suspend fun fetch(): FetchResult {
return FetchResult.OfSource(
source = Buffer().apply {
write(data)
}
)
}
class Factory : Fetcher.Factory {
override fun create(data: Any, options: Options): Fetcher? {
if (data !is ByteArray) return null
return ByteArrayFetcher(data)
}
}
}
and then:
ImageLoader {
components {
add(ByteArrayFetcher.Factory())
}
}
In the next version, I'll add to the default support #412
@qdsfdhvh And how we can use it?
Like this with custom request and imageLoader in rememberImagePainter:
` val imageLoader = ImageLoader { components { add(ByteArrayFetcher.Factory()) } }
Image(
painter = rememberImagePainter(request = ImageRequest(data = byteArray), imageLoader = imageLoader),
contentDescription = "",
modifier = Modifier
.padding(16.dp)
.size(50.dp)
)`
In addition to configuring it in ImageLoader, you can also configure it directly in ImageRequest, like this:
val request = remember {
ImageRequest(data = byteArray) {
components {
add(ByteArrayFetcher.Factory())
}
}
}
Image(
painter = rememberImagePainter(request),
// ...
)
in version 1.7.2
, default config is support ByteArray.
Ok @qdsfdhvh huge thanks.
Hi @qdsfdhvh i tried it, But its not working, not sure if issue is with compose-multiplatform-file-picker get byte array logic or its with compose image loader. Did u tried it yourself?
Hi @sunildhiman90 , ByteArray should work fine, but there seems to be something wrong with MPFile.getFileByteArray() when I test it, so i used MPFile.platformFile
, in #416, I supported android.net.Uri
in android, platform.Foundation.NSURL
in apple and java.io.File
in desktop, and also support okio.Path
, if some MPFile.platformFile
not support, you can convert it to okio.Path
in next verison 1.7.3
.
@qdsfdhvh I tried using platformFile as well, its also not working. So how can i load that image now from iOS file picker using compose image loader?
use version 1.7.3
and MPFile.platformFile
, here is my test code.
Thanks @qdsfdhvh, its working fine that way as u mentioned in version 1.7.3 and with MPFile.platformFile.
One question here, suppose i want to get the byte array of this image in base64 format, then how can i do that by any way or by any library in compose multiplatform, any idea?
Maybe need to manually extend MPFile
and implement ByteArray reading for each platform (due to the issue with the default getFileByteArray()
), and then perform base64 encoding.
Hi one question here, why didnt you made these changes with compose multiplatform version 1.5.11 instead of 1.6.0-dev1334 ?
Mainly because of the dependency on compose.components.resources
, I am currently using the new-resources-gradle-plugin from compose-multiplatform to manage resources. These changes have already been merged, so it is currently not convenient to downgrade the version of compose-multiplatform
.