Compose Image library for Kotlin Multiplatform.

Overview

Compose ImageLoader

Maven Central

Compose Image library for Kotlin Multiplatform.

Setup

Add the dependency in your common module's commonMain sourceSet

kotlin {
    // ...
    sourceSets {
        val commonMain by getting {
            dependencies {
                api("io.github.qdsfdhvh:image-loader:$last_version")
            }
        }
    }
}

How to Use

@Composeable
fun Content() {
    CompositionLocalProvider(
        LocalImageLoader provides generateImageLoader(),
    ) {
        val url = "https://....."
        val painter = rememberAsyncImagePainter(url)
        Image(painter, null)
    }
}

fun generateImageLoader(): ImageLoader {
    return ImageLoaderBuilder().build()
}

Thx

Coil

Comments
  • Fails to load images on old Android Versions when using ImageConfig.HARDWARE

    Fails to load images on old Android Versions when using ImageConfig.HARDWARE

    I was using the ImageConfig.HARDWARE configuation for thumbnails since it seemed to help perfomance, but I got this exception when I was testing on a older emulator(API 24).

    I did some research and it seems like Bitmap.Config.HARDWARE wasn't added until API 26. I changed what I use for ImageConfig to a variable that changes based on the API level, but I think this should be handled at the library level or at least give a warning.

    2022-11-08 00:12:12.982 11097-11097/ca.gosyer.jui.android.debug W/ImageLoaderImageKt: Caused by: java.lang.NoSuchFieldError: No field HARDWARE of type Landroid/graphics/Bitmap$Config; in class Landroid/graphics/Bitmap$Config; or its superclasses (declaration of 'android.graphics.Bitmap$Config' appears in /system/framework/framework.jar)
            at com.seiko.imageloader.util.BitmapKt.toBitmapConfig(Bitmap.kt:19)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder.configureConfig(BitmapFactoryDecoder.kt:86)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder.decode(BitmapFactoryDecoder.kt:59)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder.access$decode(BitmapFactoryDecoder.kt:26)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder$decode$2$1.invoke(BitmapFactoryDecoder.kt:34)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder$decode$2$1.invoke(BitmapFactoryDecoder.kt:34)
            at kotlinx.coroutines.InterruptibleKt.runInterruptibleInExpectedContext(Interruptible.kt:51)
            at kotlinx.coroutines.InterruptibleKt.access$runInterruptibleInExpectedContext(Interruptible.kt:1)
            at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invokeSuspend(Interruptible.kt:43)
            at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invoke(Interruptible.kt)
            at kotlinx.coroutines.InterruptibleKt$runInterruptible$2.invoke(Interruptible.kt)
            at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
            at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:161)
            at kotlinx.coroutines.BuildersKt.withContext(Unknown Source)
            at kotlinx.coroutines.InterruptibleKt.runInterruptible(Interruptible.kt:42)
            at kotlinx.coroutines.InterruptibleKt.runInterruptible$default(Interruptible.kt:39)
            at com.seiko.imageloader.component.decoder.BitmapFactoryDecoder.decode(BitmapFactoryDecoder.kt:34)
            at com.seiko.imageloader.intercept.DecodeInterceptor.decode(DecodeInterceptor.kt:45)
            at com.seiko.imageloader.intercept.DecodeInterceptor.intercept(DecodeInterceptor.kt:19)
            at com.seiko.imageloader.intercept.RealInterceptorChain.proceed(RealInterceptorChain.kt:37)
            at com.seiko.imageloader.intercept.MemoryCacheInterceptor.intercept(MemoryCacheInterceptor.kt:31)
            at com.seiko.imageloader.intercept.RealInterceptorChain.proceed(RealInterceptorChain.kt:37)
            at com.seiko.imageloader.intercept.MappedInterceptor.intercept(MappedInterceptor.kt:12)
            at com.seiko.imageloader.intercept.RealInterceptorChain.proceed(RealInterceptorChain.kt:37)
            at com.seiko.imageloader.RealImageLoader.executeMain(ImageLoader.kt:64)
            at com.seiko.imageloader.RealImageLoader.access$executeMain(ImageLoader.kt:29)
            at com.seiko.imageloader.RealImageLoader$execute$2.invokeSuspend(ImageLoader.kt:50)
            at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
            at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
            at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
            at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
            at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
            at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
    
    opened by Syer10 3
  • Cache blocks re-loading of images after failed attempts

    Cache blocks re-loading of images after failed attempts

    If the image loader cannot successfully download an image on the first try, then, when caching is enabled, it does not make any attempt to download the image again at a later time. When the disk cache is enabled it does not even retry this when the application is terminated and started again. It seems that even in case of a download error something is stored in the cache which then blocks any further attempts. I tested this by removing my images from my server, then start the application, then copy the images back to the server while the application is still running. Switching screens or restarting the application does not force a re-load of the images. This all works when no caching is configured but this is no option for me.

    I have configured caching like this:

        fun generateImageLoader(): ImageLoader {
            return ImageLoaderBuilder().apply {
                diskCache {
                    DiskCacheBuilder()
                        .directory("... path to some cache directory ...".toPath())
                        .maxSizeBytes(1024 * 1024 * 50) // 50 MB
                        .build()
                }
                memoryCache {
                    MemoryCacheBuilder()
                        .build()
                }
            }.build()
        }
    
    
    enhancement 
    opened by mipastgt 3
  • Expected class ImageLoaderBuilder does not have default constructor

    Expected class ImageLoaderBuilder does not have default constructor

    For this part of your example usage code

    private fun generateImageLoader(): ImageLoader {
        return ImageLoaderBuilder().build()
    }
    

    IntelliJ is giving me the error message

    Expected class ImageLoaderBuilder does not have default constructor
    

    This must be an IntelliJ issue because the code compiles and runs just well but maybe this error message could be avoided if you would just provide that default constructor in your code.

    Otherwise your code seems to work nicely. Great job!

    opened by mipastgt 3
  • Disk Cache not being used

    Disk Cache not being used

    I have a ImageLoader with DiskCache and MemoryCache configured but it seems to only be using the MemoryCache. My images use a custom class that I have Mappers and Keyers setup for but it doesnt seem to allow them to be inserted into the DiskCache even though they are loading the images. This happens on both Desktop and Android.

    I have tried with multiple configurations using the builder and even disabling the memory cache, which does not seem to help. It doesnt seem like its hitting the DiskCacheInterceptor at all and Napier says nothing about errors.

    In general I cannot figure out whats wrong.

    opened by Syer10 3
  • Changelog

    Changelog

    Please provide a changelog, or some other means, so we know what version of Compose each version matches with and which version of ktor it uses as well.

    opened by ScottPierce 2
  • Why use Batik based SVG renderer on desktop

    Why use Batik based SVG renderer on desktop

    For the desktop version you are using the Batik based twelvemonkeys SVG renderer. Why do you do that? All desktop versions are also Skia versions and thus have the Skia SVG built in. It would save people from a lot of dependency downloads if you would drop that. The Skia SVG renderer works nicely on desktop so I don't see any reason to use the Batik one. It would make the final distribution bundles smaller.

    opened by mipastgt 1
  • Error: compiled by a pre-release version of Kotlin

    Error: compiled by a pre-release version of Kotlin

    Class 'com.seiko.imageloader.ImageLoader' is compiled by a pre-release version of Kotlin and cannot be loaded by this version of the compiler

    I'm using: Kotlin 1.7.0 Compose JB 1.2.0-alpha01-dev753

    opened by ScottPierce 1
  • NPE in Android SVG decoder

    NPE in Android SVG decoder

    This code in your Android SVG decoder

        if (svg.documentSVGVersion.startsWith("2")) {
            throw RuntimeException("Un support SVG version '2.0'")
        }
    
    

    results in an NPE for many of my icons because documentSVGVersion returns null. After replacing this with

        if (svg.documentSVGVersion != null && svg.documentSVGVersion.startsWith("2")) {
            throw RuntimeException("Un support SVG version '2.0'")
        }
    
    

    everything was good again.

    opened by mipastgt 0
  • Add arm64 iOS simulator target.

    Add arm64 iOS simulator target.

    Hi, this should add arm64 simulator target for iOS, so that people can run iOS apps on the arm64 simulator on M1/M2 Macs. I couldn't test it unfortunately as my machine fails to run iOS simulator from the IntelliJ IDEA (only works with Xcode and I couldn't get it working), but it should just work.

    opened by TadeasKriz 0
  • Improve support for locally provided image data

    Improve support for locally provided image data

    Thank you for producing and sharing this library; the power of the Compose/Multiplatform ecosystem is beginning to show!

    While the cross-platform ability is great; I noticed you have focused API's on loading resources asynchronously. My use case is for showing SVG (and potentially other format) files from local bytes which are much faster to load and so the overhead of managing a progress 'spinner' etc. is undesirable.

    If you are planning any major new features for this library; please consider building API's intended for local resources: that take byte data for images directly, and minimise overhead to display.

    opened by chris-hatton 1
  • Improve Documentation

    Improve Documentation

    Thank you for maintaining this library! We desperately need something like this in the community.

    The documentation is a little lacking, primarily on compatibility with what versions of Kotlin and Compose. I'm about to try out your library and I'm not confident whether it will work with my version of Kotlin / Compose.

    There are also other things that seem to be lacking in the documentation around the configurability of the memory and disk caches.

    opened by ScottPierce 0
Releases(1.2.6)
Owner
Seiko
easy is best.
Seiko
ZoomableComposeImage - A zoomable image for jetpack compose

ZoomableComposeImage - A zoomable image for jetpack compose

RERERE 10 Dec 11, 2022
ComposeImageBlurhash is a Jetpack Compose component with the necessary implementation to display a blurred image

compose-image-blurhash ComposeImageBlurhash is a Jetpack Compose component with the necessary implementation to display a blurred image while the real

Orlando Novas Rodriguez 24 Nov 18, 2022
load-the-image Apply to compose-jb(desktop), Used to load network and local pictures.

load-the-image load-the-image Apply to compose-jb(desktop), Used to load network and local pictures. ?? Under construction It may change incompatibly

lt_taozi 13 Dec 29, 2022
An image loading and caching library for Android focused on smooth scrolling

Glide | View Glide's documentation | 简体中文文档 | Report an issue with Glide Glide is a fast and efficient open source media management and image loading

Bump Technologies 33.2k Jan 7, 2023
A powerful image downloading and caching library for Android

Picasso A powerful image downloading and caching library for Android For more information please see the website Download Download the latest AAR from

Square 18.4k Jan 6, 2023
An Android transformation library providing a variety of image transformations for Glide.

Glide Transformations An Android transformation library providing a variety of image transformations for Glide. Please feel free to use this. Are you

Daichi Furiya 9.7k Dec 30, 2022
An android image compression library.

Compressor Compressor is a lightweight and powerful android image compression library. Compressor will allow you to compress large photos into smaller

Zetra 6.7k Jan 9, 2023
An Android transformation library providing a variety of image transformations for Picasso

Picasso Transformations An Android transformation library providing a variety of image transformations for Picasso. Please feel free to use this. Are

Daichi Furiya 1.7k Jan 5, 2023
Library to handle asynchronous image loading on Android.

WebImageLoader WebImageLoader is a library designed to take to hassle out of handling images on the web. It has the following features: Images are dow

Alexander Blom 102 Dec 22, 2022
Image loading for Android backed by Kotlin Coroutines.

An image loading library for Android backed by Kotlin Coroutines. Coil is: Fast: Coil performs a number of optimizations including memory and disk cac

Coil 8.8k Jan 8, 2023
Android Asynchronous Networking and Image Loading

Android Asynchronous Networking and Image Loading Download Maven Git Features Kotlin coroutine/suspend support Asynchronously download: Images into Im

Koushik Dutta 6.3k Dec 27, 2022
Luban(鲁班)—Image compression with efficiency very close to WeChat Moments/可能是最接近微信朋友圈的图片压缩算法

Luban ?? English Documentation Luban(鲁班) —— Android图片压缩工具,仿微信朋友圈压缩策略。 Luban-turbo —— 鲁班项目的turbo版本,查看trubo分支。 写在前面 家境贫寒,工作繁忙。只能不定期更新,还望网友们见谅! 项目描述 目前做A

郑梓斌 13.1k Jan 7, 2023
Image Picker for Android 🤖

Image Picker for Android ??

Esa Firman 1k Dec 31, 2022
Easy to use, lightweight custom image view with rounded corners.

RoundedImageView Easy to use, lightweight custom image view with rounded corners. Explore the docs » View Demo · Report Bug · Request Feature About Th

Melik Mehmet Özyildirim 6 Dec 23, 2021
Powerful and flexible library for loading, caching and displaying images on Android.

Universal Image Loader The great ancestor of modern image-loading libraries :) UIL aims to provide a powerful, flexible and highly customizable instru

Sergey Tarasevich 16.8k Jan 8, 2023
An Android library for managing images and the memory they use.

Fresco Fresco is a powerful system for displaying images in Android applications. Fresco takes care of image loading and display, so you don't have to

Facebook 16.9k Jan 8, 2023
Glide Bitmap Pool is a memory management library for reusing the bitmap memory

Glide Bitmap Pool About Glide Bitmap Pool Glide Bitmap Pool is a memory management library for reusing the bitmap memory. As it reuses bitmap memory ,

AMIT SHEKHAR 573 Dec 31, 2022
Photo picker library for android. Let's you pick photos directly from files, or navigate to camera or gallery.

ChiliPhotoPicker Made with ❤️ by Chili Labs. Library made without DataBinding, RxJava and image loading libraries, to give you opportunity to use it w

Chili Labs 394 Jan 2, 2023
Andorid library that loads images asynchronously into cache using a thread pool

AndroidImageLoader AndroidImageLoader is a fork of the Image Loader component in libs-for-android. The AndroidImageLoader is an Android library that h

David Wu 63 Feb 19, 2019