Hi People! How do you load image resources in your...
# compose-ios
a
Hi People! How do you load image resources in your compose ios app ?
m
a
m
But the headline states: “This is a Kotlin MultiPlatform library that provides access to the resources on macOs, iOS, Android the JVM and JS/Browser with the support of the default system localization.”
a
right, but it doesn’t support compose ios
m
Ah, now I see what you mean. Again one of these incomplete multiplatform niceties. Sorry, I haven’t used this myself for compose yet.
a
nevermind thanks @Michael Paus 🙂
m
But looking at it again, do you really need the compose part? If you can just get at the image file as a ByteArray then you can do the conversion to a Compose image yourself.
a
yes, should be doable 👍 will keep this thread posted
m
Just in case you need it. This is the way I do the image conversion:
Copy code
package de.mpmediasoft.system.internal

import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asComposeImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import de.mpmediasoft.system.ImageFactory
import org.jetbrains.skia.Bitmap
import org.jetbrains.skia.ColorAlphaType
import org.jetbrains.skia.Image
import org.jetbrains.skia.ImageInfo

actual class ImageFactoryImpl actual constructor() : ImageFactory {

    override fun imageBitmapFromBytes(encodedImageData: ByteArray): ImageBitmap {
        return Image.makeFromEncoded(encodedImageData).toComposeImageBitmap()
    }

    override fun imageBitmapFromArgb(rawArgbImageData: IntArray, width: Int, height: Int): ImageBitmap {
        val bytesPerPixel = 4
        val pixels = ByteArray(width * height * bytesPerPixel)

        var k = 0
        for (y in 0 until height) {
            for (x in 0 until width) {
                val argb = rawArgbImageData[y * width + x]
                val a = (argb shr 24) and 0xff
                val r = (argb shr 16) and 0xff
                val g = (argb shr 8) and 0xff
                val b = (argb shr 0) and 0xff
                pixels[k++] = b.toByte()
                pixels[k++] = g.toByte()
                pixels[k++] = r.toByte()
                pixels[k++] = a.toByte()
            }
        }

        return imageBitmapFromArgb(pixels, width, height)
    }

    fun imageBitmapFromArgb(rawArgbImageData: ByteArray, width: Int, height: Int): ImageBitmap {
        val bitmap = Bitmap()
        bitmap.allocPixels(ImageInfo.makeS32(width, height, ColorAlphaType.UNPREMUL))
        bitmap.installPixels(rawArgbImageData)
        return bitmap.asComposeImageBitmap()
    }

}
Copy code
package de.mpmediasoft.system

import androidx.compose.ui.graphics.ImageBitmap

interface ImageFactory {
    fun imageBitmapFromBytes(encodedImageData: ByteArray): ImageBitmap
    fun imageBitmapFromArgb(rawArgbImageData: IntArray, width: Int, height: Int): ImageBitmap
}
You’ll only need the method
imageBitmapFromBytes
.
a
so a bitmappainter can load this bitmap 🤔 interesting!
m
Just for completeness. The above conversion code works for all Skia targets. For Android it looks like this:
Copy code
package de.mpmediasoft.system.internal

import android.graphics.BitmapFactory
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageBitmapConfig
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.colorspace.ColorSpaces
import de.mpmediasoft.system.ImageFactory

actual class ImageFactoryImpl actual constructor() : ImageFactory {
    
    // Android implementation

    override fun imageBitmapFromBytes(encodedImageData: ByteArray): ImageBitmap {
        return BitmapFactory.decodeByteArray(encodedImageData, 0, encodedImageData.size).asImageBitmap()
    }

    override fun imageBitmapFromArgb(rawArgbImageData: IntArray, width: Int, height: Int): ImageBitmap {
        val image = ImageBitmap(width, height, ImageBitmapConfig.Argb8888, true, ColorSpaces.Srgb)
        image.asAndroidBitmap().setPixels(rawArgbImageData, 0, width, 0, 0, width, height)
        return image
    }

}
a
something like this ?
Copy code
remember { BitmapPainter(ImageFactory.imageBitmapFromBytes(byte-array-from-moko-resource?)) }
and here byte-array will come from moko-resources ?
m
Yes, wherever you can use a regular Compose ImageBitmap.
Copy code
val painter = remember { UIImage.imageNamed(imageResourceName)?.toSkiaImage()?.toComposeImageBitmap()?.let(::BitmapPainter) }
looks like a good impl ?
m
Looks interesting. Do you know how the packaging is done and what the correct imageResourceName then is?
a
looking into it RN 🙂
looks like
UIImage.imageNamed
is from ios platform , and it uses the ios project resources , basically reading from the xcodeproject. blob thinking upside down
but looks like it won’t work for my compose-ios app, since it re-generates the xcode project during build 😑 , i will try to dig more into this later. thanks @Michael Paus 🙂
1218 Views