Javokhir Savriev
05/25/2023, 2:28 PMDima Avdeev
05/25/2023, 2:54 PMimport androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import kotlinx.cinterop.addressOf
import kotlinx.cinterop.get
import kotlinx.cinterop.usePinned
import org.jetbrains.skia.ColorAlphaType
import org.jetbrains.skia.ColorType
import org.jetbrains.skia.Image
import org.jetbrains.skia.ImageInfo
import platform.CoreFoundation.CFDataGetBytePtr
import platform.CoreFoundation.CFDataGetLength
import platform.CoreFoundation.CFRelease
import platform.CoreGraphics.CGColorSpaceCreateDeviceRGB
import platform.CoreGraphics.CGDataProviderCopyData
import platform.CoreGraphics.CGImageAlphaInfo
import platform.CoreGraphics.CGImageCreateCopyWithColorSpace
import platform.CoreGraphics.CGImageGetAlphaInfo
import platform.CoreGraphics.CGImageGetBytesPerRow
import platform.CoreGraphics.CGImageGetDataProvider
import platform.CoreGraphics.CGImageGetHeight
import platform.CoreGraphics.CGImageGetWidth
import platform.UIKit.UIImage
import platform.UIKit.UIImagePNGRepresentation
import platform.posix.memcpy
internal fun UIImage.toSkiaImage(): Image? {
val imageRef = CGImageCreateCopyWithColorSpace(this.CGImage, CGColorSpaceCreateDeviceRGB()) ?: return null
val width = CGImageGetWidth(imageRef).toInt()
val height = CGImageGetHeight(imageRef).toInt()
val bytesPerRow = CGImageGetBytesPerRow(imageRef)
val data = CGDataProviderCopyData(CGImageGetDataProvider(imageRef))
val bytePointer = CFDataGetBytePtr(data)
val length = CFDataGetLength(data)
val alphaInfo = CGImageGetAlphaInfo(imageRef)
val alphaType = when (alphaInfo) {
CGImageAlphaInfo.kCGImageAlphaPremultipliedFirst, CGImageAlphaInfo.kCGImageAlphaPremultipliedLast -> ColorAlphaType.PREMUL
CGImageAlphaInfo.kCGImageAlphaFirst, CGImageAlphaInfo.kCGImageAlphaLast -> ColorAlphaType.UNPREMUL
CGImageAlphaInfo.kCGImageAlphaNone, CGImageAlphaInfo.kCGImageAlphaNoneSkipFirst, CGImageAlphaInfo.kCGImageAlphaNoneSkipLast -> ColorAlphaType.OPAQUE
else -> ColorAlphaType.UNKNOWN
}
val byteArray = ByteArray(length.toInt()) { index ->
bytePointer!![index].toByte()
}
CFRelease(data)
CFRelease(imageRef)
return Image.makeRaster(
imageInfo = ImageInfo(width = width, height = height, colorType = ColorType.RGBA_8888, alphaType = alphaType),
bytes = byteArray,
rowBytes = bytesPerRow.toInt(),
)
}
fun UIImage.toImageBitmap(): ImageBitmap {
return this.toSkiaImage()!!.toComposeImageBitmap()
//todo <https://github.com/touchlab/DroidconKotlin/blob/fe5b7e8bb6cdf5d00eeaf7ee13f1f96b71857e8f/shared-ui/src/iosMain/kotlin/co/touchlab/droidcon/ui/util/ToSkiaImage.kt>
val pngRepresentation = UIImagePNGRepresentation(this)!!
val byteArray = ByteArray(pngRepresentation.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), pngRepresentation.bytes, pngRepresentation.length)
}
}
return org.jetbrains.skia.Image.makeFromEncoded(byteArray).toComposeImageBitmap()
}
Javokhir Savriev
05/25/2023, 3:26 PM