Kotlin Compose Desktop 如何加载图像?

11
如何在桌面上使用Kotlin Compose时从硬盘加载图片?

1
我正在尝试弄清楚如何从URL加载... - Thomas Liao
7个回答

13

其他答案已经过时,根据Compose 1.0.0-beta5版本,您应该执行以下操作:

Image(painterResource("image.jpg"))

如果您只想加载位图,则可以使用以下代码:

val bitmap = useResource("image.jpg") { loadImageBitmap(it) }

只需要文件名(不需要完整路径),但请确保您的资源在 src/main/resources/image.jpg 中。


10

你可以使用这个函数获取 ImageAsset。

fun imageFromFile(file: File): ImageAsset {
    return org.jetbrains.skia.Image.makeFromEncoded(file.readBytes()).asImageAsset()
}

完整示例:

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()
}

它是Skia,不是Skija。 - Ovi Trif

5

试一试这个:

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
)

1
这是最简单和最好的答案。其他答案依赖于第三方库或仅适用于定义为资源的图像。 - PaulNUK

4

这对我有用。

 Image(bitmap = imageFromResource("image.png"),
       "image",
 )

contentDescription 是必需的,但可以是任何您喜欢的内容。您还可以添加修饰符,例如

val imageModifier = Modifier
   .height(240.dp)
   .fillMaxWidth()
   .clip(RoundedCornerShape(12.dp))

Image(bitmap = imageFromResource("header.png"),
      "image",
      imageModifier,
      contentScale = ContentScale.Fit
    )

3

Image.asImageBitmap() 已经过时。请使用新的 Image.toComposeImageBitmap()。截至目前 (2022年4月1日),它尚未被弃用:

@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()
}

2

从文档中得知:异步加载设备存储或网络图片

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))
}

 */

0
使用 compose-1.1.0,这对我有效。
import org.jetbrains.skia.Image
// ...
Image(
    contentDescription = "image",
    bitmap = Image.Companion.makeFromEncoded(imageBytes).toComposeImageBitmap()
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接