Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load image using bytearray #411

Open
sunildhiman90 opened this issue Jan 6, 2024 · 14 comments
Open

Load image using bytearray #411

sunildhiman90 opened this issue Jan 6, 2024 · 14 comments

Comments

@sunildhiman90
Copy link

Hi,

Can we load image from ByteArray in compose imageloader?
if yes how we can do that?

Thanks

@sunildhiman90
Copy link
Author

Actually it is not loading image from ios uri, I used compose-multiplatform-file-picker for picking the file from iOS files, then i use rememberImagePainter, it does not load image. I gets this error in the logs:

2024-01-06 14:37:54.858217+0530 KMPAppExample[9447:410797] [DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}

And this is the path of image which im getting from file picker and using in rememberImagePainter:
/Users/sunil/Library/Developer/CoreSimulator/Devices/F38BFB2D-6776-4B28-9D06-54D521E45237/data/Containers/Shared/AppGroup/8F44B401-AFFC-4219-ACFF-65142F2384AA/File Provider Storage/images (1)-536DD7B9-38CB-49E6-B42E-8FF33DB31BD5.JPEG

@qdsfdhvh
Copy link
Owner

qdsfdhvh commented Jan 6, 2024

You can add a custom Fetcher like this:

class ByteArrayFetcher(
    private val data: ByteArray,
) : Fetcher {
    override suspend fun fetch(): FetchResult {
        return FetchResult.OfSource(
            source = Buffer().apply {
                write(data)
            }
        )
    }

    class Factory : Fetcher.Factory {
        override fun create(data: Any, options: Options): Fetcher? {
            if (data !is ByteArray) return null
            return ByteArrayFetcher(data)
        }
    }
}

and then:

ImageLoader {
    components {
        add(ByteArrayFetcher.Factory())
    }
}

@qdsfdhvh
Copy link
Owner

qdsfdhvh commented Jan 6, 2024

In the next version, I'll add to the default support #412

@sunildhiman90
Copy link
Author

@qdsfdhvh And how we can use it?

Like this with custom request and imageLoader in rememberImagePainter:

` val imageLoader = ImageLoader {
components {
add(ByteArrayFetcher.Factory())
}
}

    Image(
        painter = rememberImagePainter(request = ImageRequest(data = byteArray), imageLoader = imageLoader),
        contentDescription = "",
        modifier = Modifier
            .padding(16.dp)
            .size(50.dp)
    )`

@qdsfdhvh
Copy link
Owner

qdsfdhvh commented Jan 8, 2024

In addition to configuring it in ImageLoader, you can also configure it directly in ImageRequest, like this:

val request = remember {
    ImageRequest(data = byteArray) {
        components {
            add(ByteArrayFetcher.Factory())
        }
    }
}
Image(
    painter = rememberImagePainter(request),
    // ...
)

in version 1.7.2, default config is support ByteArray.

@sunildhiman90
Copy link
Author

Ok @qdsfdhvh huge thanks.

@sunildhiman90
Copy link
Author

Hi @qdsfdhvh i tried it, But its not working, not sure if issue is with compose-multiplatform-file-picker get byte array logic or its with compose image loader. Did u tried it yourself?

@qdsfdhvh qdsfdhvh linked a pull request Jan 8, 2024 that will close this issue
@qdsfdhvh
Copy link
Owner

qdsfdhvh commented Jan 8, 2024

Hi @sunildhiman90 , ByteArray should work fine, but there seems to be something wrong with MPFile.getFileByteArray() when I test it, so i used MPFile.platformFile, in #416, I supported android.net.Uri in android, platform.Foundation.NSURL in apple and java.io.File in desktop, and also support okio.Path, if some MPFile.platformFile not support, you can convert it to okio.Path in next verison 1.7.3.

@qdsfdhvh qdsfdhvh removed a link to a pull request Jan 8, 2024
@sunildhiman90
Copy link
Author

@qdsfdhvh I tried using platformFile as well, its also not working. So how can i load that image now from iOS file picker using compose image loader?

@qdsfdhvh
Copy link
Owner

use version 1.7.3 and MPFile.platformFile, here is my test code.

@sunildhiman90
Copy link
Author

Thanks @qdsfdhvh, its working fine that way as u mentioned in version 1.7.3 and with MPFile.platformFile.

One question here, suppose i want to get the byte array of this image in base64 format, then how can i do that by any way or by any library in compose multiplatform, any idea?

@qdsfdhvh
Copy link
Owner

Maybe need to manually extend MPFile and implement ByteArray reading for each platform (due to the issue with the default getFileByteArray()), and then perform base64 encoding.

@sunildhiman90
Copy link
Author

Hi one question here, why didnt you made these changes with compose multiplatform version 1.5.11 instead of 1.6.0-dev1334 ?

@qdsfdhvh
Copy link
Owner

Mainly because of the dependency on compose.components.resources, I am currently using the new-resources-gradle-plugin from compose-multiplatform to manage resources. These changes have already been merged, so it is currently not convenient to downgrade the version of compose-multiplatform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants