How to load images from the hard disk when using Kotlin compose on the desktop?
Asked
Active
Viewed 7,237 times
11

Phil Dukhov
- 67,741
- 15
- 184
- 220

Haseeb Pavaratty
- 554
- 3
- 17
-
1I'm trying to figuring out how to load from a url... – Thomas Liao Feb 01 '21 at 12:59
7 Answers
13
other answers are outdated, as per Compose 1.0.0-beta5 you should do the following:
Image(painterResource("image.jpg"))
if you want to load a bitmap only
val bitmap = useResource("image.jpg") { loadImageBitmap(it) }
Only the file name is required (not full path), but make sure that your resources are in src/main/resources/image.jpg

sonique
- 4,539
- 2
- 30
- 39
10
You can get ImageAsset with this function
fun imageFromFile(file: File): ImageAsset {
return org.jetbrains.skia.Image.makeFromEncoded(file.readBytes()).asImageAsset()
}
Full example:
import androidx.compose.desktop.Window
import androidx.compose.foundation.Image
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.ImageAsset
import androidx.compose.ui.graphics.asImageAsset
import java.io.File
fun main() = Window {
val file = File("D:\\images\\my_image.PNG")
val image = remember { imageFromFile(file) }
Image(asset = image)
}
fun imageFromFile(file: File): ImageAsset {
return org.jetbrains.skia.Image.makeFromEncoded(file.readBytes()).asImageAsset()
}

GuilhE
- 11,591
- 16
- 75
- 116

Haseeb Pavaratty
- 554
- 3
- 17
5
Try this one:
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.res.loadImageBitmap
import java.io.File
val file = File(path)
val imageBitmap: ImageBitmap = remember(file) {
loadImageBitmap(file.inputStream())
}
Image(
painter = BitmapPainter(image = imageBitmap),
contentDescription = null
)

beigirad
- 4,986
- 2
- 29
- 52
-
1This is the simplest and best answer. Other answers rely on 3rd part libraries or only work for images defined as resources. – PaulNUK Apr 17 '22 at 13:18
4
This worked for me.
Image(bitmap = imageFromResource("image.png"),
"image",
)
contentDescription
is necessary, but can be anything you'd like. You can also add modifiers such as
val imageModifier = Modifier
.height(240.dp)
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
Image(bitmap = imageFromResource("header.png"),
"image",
imageModifier,
contentScale = ContentScale.Fit
)

John Conde
- 217,595
- 99
- 455
- 496

Bryan
- 49
- 1
- 2
3
Image.asImageBitmap() is deprecated. Use new Image.toComposeImageBitmap(). For now (01.04.2022) it's not deprecated yet:
@Composable
fun CanvasArea2() {
val image = remember { imageFromFile(File("C:/Users/Admin/Desktop/banana.png")) }
Canvas(modifier = Modifier.background(color = Color(0xFFFFFFFF))) {
drawImage(image)
}
}
fun imageFromFile(file: File): ImageBitmap {
return org.jetbrains.skia.Image.makeFromEncoded(file.readBytes()).toComposeImageBitmap()
}

badadin
- 507
- 1
- 5
- 18
2
from the docs : Loading images from device storage or network asynchronously
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.painter.BitmapPainter
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.loadImageBitmap
import androidx.compose.ui.res.loadSvgPainter
import androidx.compose.ui.res.loadXmlImageVector
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.singleWindowApplication
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.xml.sax.InputSource
import java.io.File
import java.io.IOException
import java.net.URL
fun main() = singleWindowApplication {
val density = LocalDensity.current
Column {
AsyncImage(
load = { loadImageBitmap(File("sample.png")) },
painterFor = { remember { BitmapPainter(it) } },
contentDescription = "Sample",
modifier = Modifier.width(200.dp)
)
AsyncImage(
load = { loadSvgPainter("https://github.com/JetBrains/compose-jb/raw/master/artwork/idea-logo.svg", density) },
painterFor = { it },
contentDescription = "Idea logo",
contentScale = ContentScale.FillWidth,
modifier = Modifier.width(200.dp)
)
AsyncImage(
load = { loadXmlImageVector(File("compose-logo.xml"), density) },
painterFor = { rememberVectorPainter(it) },
contentDescription = "Compose logo",
contentScale = ContentScale.FillWidth,
modifier = Modifier.width(200.dp)
)
}
}
@Composable
fun <T> AsyncImage(
load: suspend () -> T,
painterFor: @Composable (T) -> Painter,
contentDescription: String,
modifier: Modifier = Modifier,
contentScale: ContentScale = ContentScale.Fit,
) {
val image: T? by produceState<T?>(null) {
value = withContext(Dispatchers.IO) {
try {
load()
} catch (e: IOException) {
// instead of printing to console, you can also write this to log,
// or show some error placeholder
e.printStackTrace()
null
}
}
}
if (image != null) {
Image(
painter = painterFor(image!!),
contentDescription = contentDescription,
contentScale = contentScale,
modifier = modifier
)
}
}
/* Loading from file with java.io API */
fun loadImageBitmap(file: File): ImageBitmap =
file.inputStream().buffered().use(::loadImageBitmap)
fun loadSvgPainter(file: File, density: Density): Painter =
file.inputStream().buffered().use { loadSvgPainter(it, density) }
fun loadXmlImageVector(file: File, density: Density): ImageVector =
file.inputStream().buffered().use { loadXmlImageVector(InputSource(it), density) }
/* Loading from network with java.net API */
fun loadImageBitmap(url: String): ImageBitmap =
URL(url).openStream().buffered().use(::loadImageBitmap)
fun loadSvgPainter(url: String, density: Density): Painter =
URL(url).openStream().buffered().use { loadSvgPainter(it, density) }
fun loadXmlImageVector(url: String, density: Density): ImageVector =
URL(url).openStream().buffered().use { loadXmlImageVector(InputSource(it), density) }
/* Loading from network with Ktor client API (https://ktor.io/docs/client.html). */
/*
suspend fun loadImageBitmap(url: String): ImageBitmap =
urlStream(url).use(::loadImageBitmap)
suspend fun loadSvgPainter(url: String, density: Density): Painter =
urlStream(url).use { loadSvgPainter(it, density) }
suspend fun loadXmlImageVector(url: String, density: Density): ImageVector =
urlStream(url).use { loadXmlImageVector(InputSource(it), density) }
@OptIn(KtorExperimentalAPI::class)
private suspend fun urlStream(url: String) = HttpClient(CIO).use {
ByteArrayInputStream(it.get(url))
}
*/

yazan sayed
- 777
- 7
- 24
0
Using compose-1.1.0, this works for me.
import org.jetbrains.skia.Image
// ...
Image(
contentDescription = "image",
bitmap = Image.Companion.makeFromEncoded(imageBytes).toComposeImageBitmap()
)

Simsim
- 121
- 1
- 2