pref: calculate image hash from raw bytes
This commit is contained in:
@@ -1,18 +1,18 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:lensai/extensions/image.dart';
|
|
||||||
|
|
||||||
class EquatableImage {
|
class EquatableImage {
|
||||||
final Image value;
|
final Image value;
|
||||||
final int? _imageHash;
|
final int? _imageHash;
|
||||||
|
|
||||||
EquatableImage(this.value, {required int? hash}) : _imageHash = hash;
|
EquatableImage(this.value, {required int? hash}) : _imageHash = hash;
|
||||||
|
|
||||||
static Future<EquatableImage> calculate(Image image) async {
|
//For now we only calculate the has from encoded image on decoding
|
||||||
final imageHash = await image.calculateHash();
|
|
||||||
|
|
||||||
return EquatableImage(image, hash: imageHash);
|
// static Future<EquatableImage> calculate(Image image) async {
|
||||||
}
|
// final imageHash = await image.calculateHash();
|
||||||
|
|
||||||
|
// return EquatableImage(image, hash: imageHash);
|
||||||
|
// }
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => _imageHash.hashCode;
|
int get hashCode => _imageHash.hashCode;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:lensai/domain/entities/equatable_image.dart';
|
|
||||||
import 'package:xxh3/xxh3.dart';
|
import 'package:xxh3/xxh3.dart';
|
||||||
|
|
||||||
extension ImageHash on Image {
|
extension ImageHash on Image {
|
||||||
@@ -14,7 +13,7 @@ extension ImageHash on Image {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<EquatableImage> toEquatable() {
|
// Future<EquatableImage> toEquatable() {
|
||||||
return EquatableImage.calculate(this);
|
// return EquatableImage.calculate(this);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ class BrowserIcon with FastEquatable {
|
|||||||
required Color? dominantColor,
|
required Color? dominantColor,
|
||||||
required IconSource source,
|
required IconSource source,
|
||||||
}) async {
|
}) async {
|
||||||
final image = await tryDecodeImage(
|
final image = await tryDecodeImage(bytes);
|
||||||
bytes,
|
|
||||||
).then((image) => image!.toEquatable());
|
|
||||||
|
|
||||||
return BrowserIcon(
|
return BrowserIcon(
|
||||||
image: image,
|
image: image!,
|
||||||
dominantColor: dominantColor,
|
dominantColor: dominantColor,
|
||||||
source: source,
|
source: source,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ class TabStates extends _$TabStates {
|
|||||||
Future<void> _onIconChange(IconChangeEvent event) async {
|
Future<void> _onIconChange(IconChangeEvent event) async {
|
||||||
final IconChangeEvent(:tabId, :bytes) = event;
|
final IconChangeEvent(:tabId, :bytes) = event;
|
||||||
|
|
||||||
final image = await bytes.mapNotNull(
|
final image = await bytes.mapNotNull((bytes) => tryDecodeImage(bytes));
|
||||||
(bytes) =>
|
|
||||||
tryDecodeImage(bytes).then((image) async => image?.toEquatable()),
|
|
||||||
);
|
|
||||||
|
|
||||||
final current = state[tabId] ?? TabState.$default(tabId);
|
final current = state[tabId] ?? TabState.$default(tabId);
|
||||||
state = {...state}..[tabId] = current.copyWith.icon(image);
|
state = {...state}..[tabId] = current.copyWith.icon(image);
|
||||||
@@ -51,10 +48,7 @@ class TabStates extends _$TabStates {
|
|||||||
Future<void> _onThumbnailChange(ThumbnailEvent event) async {
|
Future<void> _onThumbnailChange(ThumbnailEvent event) async {
|
||||||
final ThumbnailEvent(:tabId, :bytes) = event;
|
final ThumbnailEvent(:tabId, :bytes) = event;
|
||||||
|
|
||||||
final image = await bytes.mapNotNull(
|
final image = await bytes.mapNotNull((bytes) => tryDecodeImage(bytes));
|
||||||
(bytes) =>
|
|
||||||
tryDecodeImage(bytes).then((image) async => image?.toEquatable()),
|
|
||||||
);
|
|
||||||
|
|
||||||
final current = state[tabId] ?? TabState.$default(tabId);
|
final current = state[tabId] ?? TabState.$default(tabId);
|
||||||
state = {...state}..[tabId] = current.copyWith.thumbnail(image);
|
state = {...state}..[tabId] = current.copyWith.thumbnail(image);
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ final selectedTabStateProvider = AutoDisposeProvider<TabState?>.internal(
|
|||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef SelectedTabStateRef = AutoDisposeProviderRef<TabState?>;
|
typedef SelectedTabStateRef = AutoDisposeProviderRef<TabState?>;
|
||||||
String _$tabStatesHash() => r'c2169e467962d006015bf50d09e93b3f4bf596e6';
|
String _$tabStatesHash() => r'2f4af9df4d648f7fb940f02e14f4a6762bb21d8a';
|
||||||
|
|
||||||
/// See also [TabStates].
|
/// See also [TabStates].
|
||||||
@ProviderFor(TabStates)
|
@ProviderFor(TabStates)
|
||||||
|
|||||||
@@ -50,9 +50,7 @@ class WebExtensionsState extends _$WebExtensionsState {
|
|||||||
Future<void> _onIconChange(ExtensionIconEvent event) async {
|
Future<void> _onIconChange(ExtensionIconEvent event) async {
|
||||||
final ExtensionIconEvent(:extensionId, :bytes) = event;
|
final ExtensionIconEvent(:extensionId, :bytes) = event;
|
||||||
|
|
||||||
final image = await tryDecodeImage(
|
final image = await tryDecodeImage(bytes);
|
||||||
bytes,
|
|
||||||
).then((image) async => image?.toEquatable());
|
|
||||||
|
|
||||||
if (image != null) {
|
if (image != null) {
|
||||||
if (_imageCache[extensionId] != image) {
|
if (_imageCache[extensionId] != image) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'web_extensions_state.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$webExtensionsStateHash() =>
|
String _$webExtensionsStateHash() =>
|
||||||
r'7fd0cb313fb433f7896bfe0f89a4545f94f58793';
|
r'9382461e7e72c31946a5308642baaac307977a15';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ class HistorySuggestions extends HookConsumerWidget {
|
|||||||
return ListTile(
|
return ListTile(
|
||||||
leading: RepaintBoundary(
|
leading: RepaintBoundary(
|
||||||
child: RawImage(
|
child: RawImage(
|
||||||
image: icon.data,
|
image: icon.data?.value,
|
||||||
height: 24,
|
height: 24,
|
||||||
width: 24,
|
width: 24,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
|
import 'package:lensai/domain/entities/equatable_image.dart';
|
||||||
import 'package:lensai/utils/lru_cache.dart';
|
import 'package:lensai/utils/lru_cache.dart';
|
||||||
import 'package:xxh3/xxh3.dart';
|
import 'package:xxh3/xxh3.dart';
|
||||||
|
|
||||||
final _cache = LRUCache<int, Image>(100);
|
final _cache = LRUCache<int, EquatableImage>(100);
|
||||||
|
|
||||||
Future<Image?> tryDecodeImage(
|
Future<EquatableImage?> tryDecodeImage(
|
||||||
Uint8List bytes, {
|
Uint8List bytes, {
|
||||||
int? targetWidth,
|
int? targetWidth,
|
||||||
int? targetHeight,
|
int? targetHeight,
|
||||||
@@ -28,9 +29,9 @@ Future<Image?> tryDecodeImage(
|
|||||||
);
|
);
|
||||||
|
|
||||||
final frameInfo = await codec.getNextFrame();
|
final frameInfo = await codec.getNextFrame();
|
||||||
final image = frameInfo.image;
|
final image = EquatableImage(frameInfo.image, hash: digest);
|
||||||
|
|
||||||
if (image.width > 0) {
|
if (image.value.width > 0) {
|
||||||
_cache.set(digest, image);
|
_cache.set(digest, image);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user