Giter Club home page Giter Club logo

thumbhash's Introduction

Dart/Flutter implementation of ThumbHash algorithm — a very compact representation of an image placeholder.

Package Pub
thumbhash pub package
flutter_thumbhash pub package

Overview

  1. Source image converted to compact "ThumbHash" binary/base64 representation: 3OcRJYB4d3h/iIeHeEh3eIhw+j3A

  2. Having this representation, user can immediately see a preview placeholder:

resulting placeholder image

thumbhash's People

Contributors

pin73 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

thumbhash's Issues

Use Future or Isolate?

Hey,
I've been checking this project as I might potentially use it in the future to replace Blurhash. Thank you for your work.

One thing that caught my eye is that this implementation does not use any async features. For example, flutter_blurhash uses Future for its decoding function. All this processing is going to be done on the UI thread and from my understanding this could cause render janks. Is there any specific reason why you chose to do it the sync way? (I saw that the official implementations for other languages also omit async, though I don't know how concurrency works for them.)

I do not have knowledge of the algorithm for decoding thumbhash so if it's significantly faster than the blurhash, concurrency might not be necessary. I would love to hear your insight.

Otherwise I think it would be cool for performance reasons to use something like Isolate.run() to wrap the methods and force them into different "thread". I have not done any performance benchmarks so that should be done first though. (Though spawning isolates used to take additional time, I'm not sure if it's fixed yet.) Blurhash implementation for Flutter allows specifying background Container with a color before the placeholder gets decoded and renered.

Please let me know what you think. Potentially I could help with that when I have time 🙂

Update toImage for caching.

My app happened to load identical thumbhashes in a list, and I realized that the current version of thumbhash toImage() never got loaded from the cache. They blink every time you scroll up and down. (Already set gaplessPlayback: true)

The == operator and hashCode for Uint8List don't work as expected (see dart-lang/sdk#16335). The code provided below is a minimal example that you can use instead of toImage(). In the Flutter framework, images are cached, but if you use MemoryImage, it won't utilize the cache because it relies on the Uint8List hashCode, which means it will never be the same even if the content is identical.

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:thumbhash/thumbhash.dart' as thumb;
import 'dart:ui' as ui;

Future<ui.Image> thumbHashDecodeImage({
  required Uint8List thumbHash,
}) async {
  final completer = Completer<ui.Image>();

  final image = thumb.thumbHashToRGBA(thumbHash);
  ui.decodeImageFromPixels(image.rgba, image.width, image.height,
      ui.PixelFormat.rgba8888, completer.complete);

  return completer.future;
}

class ThumbHashImage extends ImageProvider<ThumbHashImage> {
  /// Creates an object that decodes a [thumbHash] as an image.
  ///
  /// The arguments must not be null.
  const ThumbHashImage(this.thumbHash, {this.scale = 1.0});

  /// The bytes to decode into an image.
  final Uint8List thumbHash;

  /// The scale to place in the [ImageInfo] object of the image.
  final double scale;

  @override
  Future<ThumbHashImage> obtainKey(ImageConfiguration configuration) =>
      SynchronousFuture<ThumbHashImage>(this);

  @override
  ImageStreamCompleter load(ThumbHashImage key, DecoderCallback decode) =>
      OneFrameImageStreamCompleter(_loadAsync(key));

  Future<ImageInfo> _loadAsync(ThumbHashImage key) async {
    assert(key == this);
    final image = await thumbHashDecodeImage(
      thumbHash: thumbHash,
    );
    return ImageInfo(image: image, scale: key.scale);
  }

  @override
  bool operator ==(Object other) => other.runtimeType != runtimeType
      ? false
      : other is ThumbHashImage &&
          memEquals(thumbHash, other.thumbHash) &&
          other.scale == scale;

  @override
  int get hashCode => thumbHash.reduce((value, element) => value + element.hashCode);

  @override
  String toString() => '$runtimeType($thumbHash, scale: $scale)';
}

bool memEquals(Uint8List bytes1, Uint8List bytes2) {
  if (identical(bytes1, bytes2)) {
    return true;
  }

  if (bytes1.lengthInBytes != bytes2.lengthInBytes) {
    return false;
  }

  // Treat the original byte lists as lists of 8-byte words.
  var numWords = bytes1.lengthInBytes ~/ 8;
  var words1 = bytes1.buffer.asUint64List(0, numWords);
  var words2 = bytes2.buffer.asUint64List(0, numWords);

  for (var i = 0; i < words1.length; i += 1) {
    if (words1[i] != words2[i]) {
      return false;
    }
  }

  // Compare any remaining bytes.
  for (var i = words1.lengthInBytes; i < bytes1.lengthInBytes; i += 1) {
    if (bytes1[i] != bytes2[i]) {
      return false;
    }
  }

  return true;
}

hashCode can be improved with a better hashCode implementation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.