Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Glide have a method for loading both PNG and SVG?

I'm using Glide to load some images asynchronously into some of my ImageViews, and I know it can handle images like PNG or JPG as it can handle SVG.

Thing is, As far as I know, the way I load those two kinds of image differs. Like:

Loading "normal" images

Glide.with(mContext)
                .load("URL")
                .into(cardHolder.iv_card);

Loading SVG

GenericRequestBuilder<Uri, InputStream, SVG, PictureDrawable> requestBuilder = Glide.with(mContext)
        .using(Glide.buildStreamModelLoader(Uri.class, mContext), InputStream.class)
        .from(Uri.class)
        .as(SVG.class)
        .transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
        .sourceEncoder(new StreamEncoder())
        .cacheDecoder(new FileToStreamDecoder<>(new SVGDecoder()))
        .decoder(new SVGDecoder())
        .listener(new SvgSoftwareLayerSetter<Uri>());

requestBuilder
        .diskCacheStrategy(DiskCacheStrategy.NONE)
        .load(Uri.parse("URL"))
        .into(cardHolder.iv_card);

And if I try to load SVG with the first method it won't work. If I try to load PNG or JPG with the second method, it won't work either.

Is there a generic way to load both image types using Glide?

The server where I'm fetching those images from don't tell me the image type before I download it. It's a REST server and the resource will be retrieved in a way like "http://foo.bar/resource". The only way to know the image type is reading the HEAD response.

like image 305
Mauker Avatar asked Feb 19 '16 14:02

Mauker


People also ask

Can we load SVG with Glide?

GlideToVectorYou enables you to easily load your remote vector images (only . svg are supported for now) like other image formats. The library is based on Glide and offers the same functionalities + svg support.

Are SVGs better than PNG?

SVGs offer lossless compression — which means they're compressible to smaller file sizes at no cost to their definition, detail, or quality. PNGs also benefit from lossless compression of 5-20%, which can help make up for their large file size. However, they're still likely to be larger than an SVG.

Are SVGs faster to load?

SVG code is loaded faster because there is no need for an HTTP request to load in an image file. The time taken for SVG code is only rendering time. There can be numerous editing and animating opportunities for SVG code like you said.

How do you download pictures from Glide?

To simply load an image to LinearLayout, we call the with() method of Glide class and pass the context, then we call the load() method, which contains the URL of the image to be downloaded and finally we call the into() method to display the downloaded image on our ImageView.


Video Answer


3 Answers

You can use Glide & AndroidSVG together to achieve your goal.

There is sample from Glide for SVG.Sample Example

Setup RequestBuilder

requestBuilder = Glide.with(mActivity)
    .using(Glide.buildStreamModelLoader(Uri.class, mActivity), InputStream.class)
    .from(Uri.class)
    .as(SVG.class)
    .transcode(new SvgDrawableTranscoder(), PictureDrawable.class)
    .sourceEncoder(new StreamEncoder())
    .cacheDecoder(new FileToStreamDecoder<SVG>(new SvgDecoder()))
    .decoder(new SvgDecoder())
    .placeholder(R.drawable.ic_facebook)
    .error(R.drawable.ic_web)
    .animate(android.R.anim.fade_in)
    .listener(new SvgSoftwareLayerSetter<Uri>());

Use RequestBuilder with uri

Uri uri = Uri.parse("http://upload.wikimedia.org/wikipedia/commons/e/e8/Svg_example3.svg");
requestBuilder
    .diskCacheStrategy(DiskCacheStrategy.SOURCE)
    // SVG cannot be serialized so it's not worth to cache it
    .load(uri)
    .into(mImageView);

This way you can achieve your goal. I hope this is helpful.

like image 153
Maheshwar Ligade Avatar answered Oct 17 '22 06:10

Maheshwar Ligade


I added a flexible decoding pipeline to decode an image or SVG, maybe can help! based on glide SVG example

Decoder

class SvgOrImageDecoder : ResourceDecoder<InputStream, SvgOrImageDecodedResource> {

override fun handles(source: InputStream, options: Options): Boolean {
    return true
}

@Throws(IOException::class)
override fun decode(
    source: InputStream, width: Int, height: Int,
    options: Options
): Resource<SvgOrImageDecodedResource>? {
    val array = source.readBytes()
    val svgInputStream = ByteArrayInputStream(array.clone())
    val pngInputStream = ByteArrayInputStream(array.clone())

    return try {
        val svg = SVG.getFromInputStream(svgInputStream)

        try {
            source.close()
            pngInputStream.close()
        } catch (e: IOException) {}

        SimpleResource(SvgOrImageDecodedResource(svg))
    } catch (ex: SVGParseException) {
        try {
            val bitmap = BitmapFactory.decodeStream(pngInputStream)
            SimpleResource(SvgOrImageDecodedResource(bitmap = bitmap))
        } catch (exception: Exception){
            try {
                source.close()
                pngInputStream.close()
            } catch (e: IOException) {}
            throw IOException("Cannot load SVG or Image from stream", ex)
        }
    }
}

Transcoder

class SvgOrImageDrawableTranscoder : ResourceTranscoder<SvgOrImageDecodedResource, PictureDrawable> {
override fun transcode(
    toTranscode: Resource<SvgOrImageDecodedResource>,
    options: Options
): Resource<PictureDrawable>? {
    val data = toTranscode.get()

    if (data.svg != null) {
        val picture = data.svg.renderToPicture()
        val drawable = PictureDrawable(picture)
        return SimpleResource(drawable)
    } else if (data.bitmap != null)
        return SimpleResource(PictureDrawable(renderToPicture(data.bitmap)))
    else return null
}

private fun renderToPicture(bitmap: Bitmap): Picture{
    val picture = Picture()
    val canvas = picture.beginRecording(bitmap.width, bitmap.height)
    canvas.drawBitmap(bitmap, null, RectF(0f, 0f, bitmap.width.toFloat(), bitmap.height.toFloat()), null)
    picture.endRecording();

    return picture
}

Decoded Resource

data class SvgOrImageDecodedResource(
val svg:SVG? = null,
val bitmap: Bitmap? = null)

Glide Module

class AppGlideModule : AppGlideModule() {
override fun registerComponents(
    context: Context, glide: Glide, registry: Registry
) {
    registry.register(SvgOrImageDecodedResource::class.java, PictureDrawable::class.java, SvgOrImageDrawableTranscoder())
        .append(InputStream::class.java, SvgOrImageDecodedResource::class.java, SvgOrImageDecoder())
}

// Disable manifest parsing to avoid adding similar modules twice.
override fun isManifestParsingEnabled(): Boolean {
    return false
}

}

like image 44
Josue Amador Avatar answered Oct 17 '22 06:10

Josue Amador


ALTERNATIVE WAY : kotlin + Coil

This solution will work well with .svg , .png , .jpg

add dependency:

//Coil (https://github.com/coil-kt/coil)
implementation("io.coil-kt:coil:1.2.0")
implementation("io.coil-kt:coil-svg:1.2.0")

add this function to your code:

fun ImageView.loadUrl(url: String) {

val imageLoader = ImageLoader.Builder(this.context)
    .componentRegistry { add(SvgDecoder([email protected])) }
    .build()

val request = ImageRequest.Builder(this.context)
    .crossfade(true)
    .crossfade(500)
    .placeholder(R.drawable.placeholder)
    .error(R.drawable.error)
    .data(url)
    .target(this)
    .build()

imageLoader.enqueue(request)
}

Then call this method in your activity or fragment:

  imageView.loadUrl(url)
  // url example : https://upload.wikimedia.org/wikipedia/commons/3/36/Red_jungle_fowl_white_background.png
like image 8
Sadegh Avatar answered Oct 17 '22 06:10

Sadegh