1

I have a set of images, loaded via Glide.

The NSFW ones are blurred using a glide (wasabeef) bitmap transformation, however some can be animated gifs, in which case the first frame is shown blurred, and then the animation starts looping (unblurred).

The following is what I have tried and does not work:

DrawableTypeRequest<String> builder = Glide.with(mImage.getContext()).load(...);

if (entry.isNsfw()) {
    builder.asBitmap();
}

builder.diskCacheStrategy(DiskCacheStrategy.SOURCE) //it's likely none of this is relevant
    .skipMemoryCache(true)
    .override(props.getWidth(), props.getHeight());

if (entry.isNsfw()) {
    //successfully blurs nsfw images, but still allows unblurred animation
    builder.dontAnimate().bitmapTransform(centreCrop, blur);
} else {
    builder.centerCrop();
}

builder.crossFade(500) //moving crossfade only into the sfw posts has no effect
       .into(mImage);

Also not working is intercepting the load:

builder.listener(new RequestListener<String, GlideDrawable>() {
    @Override
    public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
        return false;
    }

    @Override
    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
        if (entry.isNsfw()) {
            target.onResourceReady(resource, null); //If I add this and return true the image is static, but unblurred
            resource.stop(); //if this is called before target, it has no effect
            return true;
        }
        return false; //returning true without calling the target stops any of the images being set on the view
    }
});

How can I turn off the gif playback for individual images while still keeping the blur transformation?

Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
  • Have you tried returning `true` on the `onResourceReady` method? Returning `false` will execute the default behaviour. Also check [this](https://github.com/bumptech/glide/issues/1107#issuecomment-205735933) – Much Overflow Nov 17 '16 at 13:55
  • Returning true stops the image being set on the target. Using asBitmap also had no effect, I'll update the code in my example to show the other things i've tried now – Nick Cardoso Nov 17 '16 at 16:12

2 Answers2

2

In the end mixing a few of the steps I outlined in my question, fixed the issue. Animated NSFW gifs now display only the first frame, which is successfully blurred.

DrawableRequestBuilder<String> builder = Glide.with(ctx).load(...);
if (nsfw) {
    builder.bitmapTransform(new BlurTransformation(ctx, 8, 16), new CentreCrop(...));
} else {
    builder.centerCrop();
}
builder.listener(new RequestListener<String, GlideDrawable>() {
    ... //onException method
    @Override
    public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
        boolean handled = false;
        if (nsfw && resource.isAnimated()) {
            target.onResourceReady(new GlideBitmapDrawable(null, ((GifDrawable) resource).getFirstFrame()), null);
            handled = true; //glide now won't set the resource on the target itself
        }
        return handled;
    }
});
builder.crossFade(500).into(mImageView);
Nick Cardoso
  • 20,807
  • 14
  • 73
  • 124
0

I have a set of images, loaded via Glide

From the above, I assume you are using RecyclerView to show these images and my answer is based on this assumption.

Try it with a custom Glide target of your own that stops the animation if NSFW like this

public class CustomTarget extends GlideDrawableImageViewTarget {

    private boolean isNSFW;

    public CustomTarget(ImageView view) {
        super(view);
    }

    public void setNSFW(boolean isNSFW){
        this.isNSFW = isNSFW;
    }

    @Override
    public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {

        // this super call loads the image, sets it to the ImageView and starts
        // animating if it is Gif
        super.onResourceReady(resource, animation); 

        if(isNSFW){
            onStop(); // stop playing the animation if NSFW
        }
    }
}

And in your View Holder class, create and keep a reference to this target as you would do for other views

public class MyViewHolder extends RecyclerView.ViewHolder {

    ImageView myImageView;
    CustomTarget myCustomTarget;

    public MyViewHolder(View itemView) {
        super(itemView);
        myImageView = (ImageView) itemView.findViewById(R.id.myIv);
        myCustomTarget = new CustomTarget(myImageView);
    }
}

Then in onBindViewHolder do the following

public void onBindViewHolder(MyViewHolder holder, int position) {

    // get the current entry in your image set
    final Entry entry = entries.get(position); 

    // call this before loading the resource
    holder.myCustomTarget.setNSFW(entry.isNSFW()); 

    // No need to specify asGif()
    // Refer http://stackoverflow.com/a/34870817/3533289
    Glide.with(context)
            .load(entry.getURL())
            .into(holder.myCustomTarget);

}

I haven't tested this solution myself. But I hope it will give you an idea of how to tackle this issue.

Much Overflow
  • 3,142
  • 1
  • 23
  • 40
  • Thanks, unfortunately this won't do the trick. It's not that I have no access to the NSFW flag, it's that stop() is not working. The custom target here does not help as even if stop() works, we'll be past the blurred frame – Nick Cardoso Nov 18 '16 at 13:32