Skip to content

Commit

Permalink
Merge pull request #536 from qdsfdhvh/master
Browse files Browse the repository at this point in the history
Version 1.8.1
  • Loading branch information
qdsfdhvh authored May 28, 2024
2 parents e76e983 + 6bd072d commit 52d38f5
Show file tree
Hide file tree
Showing 10 changed files with 690 additions and 414 deletions.
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,19 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
+ api("io.github.qdsfdhvh:image-loader:1.7.8")
+ api("io.github.qdsfdhvh:image-loader:1.8.1")
// optional - Compose Multiplatform Resources Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-compose-resources:1.8.1")
// optional - Moko Resources Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-moko-resources:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-moko-resources:1.8.1")
// optional - Blur Interceptor (only support bitmap)
+ api("io.github.qdsfdhvh:image-loader-extension-blur:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-blur:1.8.1")
}
}
val jvmMain by getting {
dependencies {
// optional - ImageIO Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-imageio:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-imageio:1.8.1")
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ object ProjectVersion {
private const val monir = "8"

// backwards compatible bug fixes
private const val path = "0"
private const val path = "1"
const val version = "$major.$monir.$path"
}

Expand Down
10 changes: 5 additions & 5 deletions docs/docs/setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ kotlin {
sourceSets {
val commonMain by getting {
dependencies {
+ api("io.github.qdsfdhvh:image-loader:1.7.8")
+ api("io.github.qdsfdhvh:image-loader:1.8.1")
// optional - Moko Resources Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-moko-resources:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-moko-resources:1.8.1")
// optional - Blur Interceptor (only support bitmap)
+ api("io.github.qdsfdhvh:image-loader-extension-blur:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-blur:1.8.1")
}
}
val jvmMain by getting {
dependencies {
// optional - ImageIO Decoder
+ api("io.github.qdsfdhvh:image-loader-extension-imageio:1.7.8")
+ api("io.github.qdsfdhvh:image-loader-extension-imageio:1.8.1")
}
}
}
Expand All @@ -38,7 +38,7 @@ Copy the following snippets if you are using [gradle version catalog](https://do

```xml title="libs.versions.toml"
[versions]
image-loader = "1.7.8"
image-loader = "1.8.1"

[libraries]
image-loader = { module = "io.github.qdsfdhvh:image-loader", version.ref = "image-loader" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.seiko.imageloader.component.fetcher
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.ColorPainter
import com.seiko.imageloader.option.Options
import com.seiko.imageloader.util.toSkiaImage
import dev.icerock.moko.resources.AssetResource
import dev.icerock.moko.resources.ColorResource
import dev.icerock.moko.resources.FileResource
Expand All @@ -18,7 +19,6 @@ import okio.FileSystem
import okio.Path.Companion.toPath
import okio.buffer
import platform.CoreGraphics.CGFloat
import platform.CoreGraphics.CGImageRef
import platform.UIKit.UIImage

internal actual suspend fun AssetResource.toFetchResult(options: Options): FetchResult? {
Expand Down Expand Up @@ -62,14 +62,11 @@ internal actual suspend fun FileResource.toFetchResult(options: Options): FetchR
)
}

@OptIn(ExperimentalForeignApi::class)
@Suppress("INVISIBLE_MEMBER")
internal actual suspend fun ImageResource.toFetchResult(options: Options): FetchResult? {
val uiImage: UIImage = this.toUIImage()
?: throw IllegalArgumentException("can't read UIImage of $this")
val cgImage: CGImageRef = uiImage.CGImage()
?: throw IllegalArgumentException("can't read CGImage of $this")
return FetchResult.OfImage(
image = cgImage.toSkiaImage(),
image = uiImage.toSkiaImage(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ package com.seiko.imageloader.component.fetcher
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.ColorPainter
import com.seiko.imageloader.option.Options
import com.seiko.imageloader.util.toSkiaImage
import dev.icerock.moko.resources.AssetResource
import dev.icerock.moko.resources.ColorResource
import dev.icerock.moko.resources.FileResource
import dev.icerock.moko.resources.ImageResource
import dev.icerock.moko.resources.getNSColor
import kotlinx.cinterop.ExperimentalForeignApi
import okio.FileSystem
import okio.Path.Companion.toPath
import okio.buffer
import platform.AppKit.NSColorSpace.Companion.deviceRGBColorSpace
import platform.AppKit.NSImage
import platform.CoreGraphics.CGImageRef

internal actual suspend fun AssetResource.toFetchResult(options: Options): FetchResult? {
return (this as FileResource).toFetchResult(options)
Expand Down Expand Up @@ -47,17 +46,11 @@ internal actual suspend fun FileResource.toFetchResult(options: Options): FetchR
)
}

@OptIn(ExperimentalForeignApi::class)
@Suppress("INVISIBLE_MEMBER")
internal actual suspend fun ImageResource.toFetchResult(options: Options): FetchResult? {
val nsImage: NSImage = this.toNSImage()
?: throw IllegalArgumentException("can't read NSImage of $this")
val cgImage: CGImageRef = nsImage.CGImageForProposedRect(
proposedDestRect = null,
context = null,
hints = null,
) ?: throw IllegalArgumentException("can't read CGImage of $this")
return FetchResult.OfImage(
image = cgImage.toSkiaImage(),
image = nsImage.toSkiaImage(),
)
}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ androidx-test-junit = "1.1.5"
androidx-test-espresso = "3.5.1"
androidx-test-uiautomator = "2.3.0"
profileinstaller = "1.3.1"
roborazzi = "1.16.1"
roborazzi = "1.19.0"
robolectric = "4.12.2"
poko = "0.16.0-beta01"
turbine = "1.0.0"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,87 +1,88 @@
package com.seiko.imageloader.component.fetcher
package com.seiko.imageloader.util

import cnames.structs.CGColorSpace
import cnames.structs.CGImage
import kotlinx.cinterop.CPointed
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.CValue
import kotlinx.cinterop.ExperimentalForeignApi
import kotlinx.cinterop.readBytes
import kotlinx.cinterop.addressOf
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.CoreGraphics.CGBitmapContextCreate
import platform.CoreGraphics.CGColorSpaceCreateDeviceRGB
import platform.CoreGraphics.CGColorSpaceRef
import platform.CoreGraphics.CGColorSpaceRelease
import platform.CoreGraphics.CGContextClearRect
import platform.CoreGraphics.CGContextDrawImage
import platform.CoreGraphics.CGContextRef
import platform.CoreGraphics.CGContextRelease
import platform.CoreGraphics.CGImageAlphaInfo
import platform.CoreGraphics.CGImageGetHeight
import platform.CoreGraphics.CGImageGetWidth
import platform.CoreGraphics.CGImageRef
import platform.CoreGraphics.CGRect
import platform.CoreGraphics.CGRectMake
import platform.posix.free
import platform.posix.malloc
import platform.posix.size_t
import platform.posix.uint32_t

@OptIn(ExperimentalForeignApi::class)
internal fun CGImageRef.toSkiaImage(): Image {
fun CGImageRef.toSkiaImage(): Image {
val cgImage: CPointer<CGImage> = this
val width: size_t = CGImageGetWidth(cgImage)
val height: size_t = CGImageGetHeight(cgImage)
val space: CPointer<CGColorSpace>? = CGColorSpaceCreateDeviceRGB()
val space: CGColorSpaceRef? = CGColorSpaceCreateDeviceRGB()
val bitsPerComponent: ULong = 8u
val bitsPerPixel: ULong = bitsPerComponent * 4u
val bytesPerPixel: ULong = bitsPerPixel / bitsPerComponent
val bytesPerRow: ULong = width * bytesPerPixel
val bufferSize: ULong = width * height * bytesPerPixel
val bitmapInfo: uint32_t = CGImageAlphaInfo.kCGImageAlphaPremultipliedLast.value
val bitmapInfo: uint32_t = platform.CoreGraphics.CGImageAlphaInfo.kCGImageAlphaPremultipliedLast.value

check(bufferSize != 0UL) { "image can't be 0 bytes" }
check(width > 0UL) { "width should be more then 0 px ($width)" }
check(height > 0UL) { "height should be more then 0 px ($height)" }

val data: CPointer<out CPointed> = malloc(bufferSize)
?: throw IllegalArgumentException("can't allocate memory for render bitmap of $cgImage")

val rect: CValue<CGRect> = CGRectMake(
x = 0.0,
y = 0.0,
width = width.toDouble(),
height = height.toDouble(),
)

val ctx: CGContextRef = CGBitmapContextCreate(
data = data,
width = width,
height = height,
bitsPerComponent = bitsPerComponent,
bytesPerRow = bytesPerRow,
space = space,
bitmapInfo = bitmapInfo,
) ?: throw IllegalArgumentException("can't create bitmap context for $cgImage")
val bytes = ByteArray(bufferSize.toInt())

CGContextClearRect(c = ctx, rect = rect)
CGContextDrawImage(c = ctx, rect = rect, image = cgImage)
bytes.usePinned { pinnedArray ->
val data = pinnedArray.addressOf(0)

CGContextRelease(ctx)
val ctx: CGContextRef = CGBitmapContextCreate(
data = data,
width = width,
height = height,
bitsPerComponent = bitsPerComponent,
bytesPerRow = bytesPerRow,
space = space,
bitmapInfo = bitmapInfo,
) ?: throw IllegalArgumentException("can't create bitmap context for $cgImage")

val bytes: ByteArray = data.readBytes(bufferSize.toInt())
CGContextClearRect(c = ctx, rect = rect)
CGContextDrawImage(c = ctx, rect = rect, image = cgImage)

free(data)
CGContextRelease(ctx)

return Image.makeRaster(
imageInfo = ImageInfo(
width = width.toInt(),
height = height.toInt(),
colorType = ColorType.RGBA_8888,
alphaType = ColorAlphaType.PREMUL,
),
bytes = bytes,
rowBytes = bytesPerRow.toInt(),
)
if (space != null) {
CGColorSpaceRelease(space)
}

return Image.makeRaster(
imageInfo = ImageInfo(
width = width.toInt(),
height = height.toInt(),
colorType = ColorType.RGBA_8888,
alphaType = ColorAlphaType.PREMUL,
),
bytes = bytes,
rowBytes = bytesPerRow.toInt(),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.seiko.imageloader.util

import kotlinx.cinterop.ExperimentalForeignApi
import org.jetbrains.skia.Image
import platform.CoreGraphics.CGImageRef
import platform.UIKit.UIImage

@OptIn(ExperimentalForeignApi::class)
fun UIImage.toSkiaImage(): Image {
val cgImage: CGImageRef = this.CGImage()
?: throw IllegalArgumentException("can't read CGImage of $this")
return cgImage.toSkiaImage()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.seiko.imageloader.util

import kotlinx.cinterop.ExperimentalForeignApi
import org.jetbrains.skia.Image
import platform.AppKit.NSImage
import platform.CoreGraphics.CGImageRef

@OptIn(ExperimentalForeignApi::class)
fun NSImage.toSkiaImage(): Image {
val cgImage: CGImageRef = this.CGImageForProposedRect(
proposedDestRect = null,
context = null,
hints = null,
) ?: throw IllegalArgumentException("can't read CGImage of $this")
return cgImage.toSkiaImage()
}
Loading

0 comments on commit 52d38f5

Please sign in to comment.