Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:magic_epaper_app/provider/color_adjustment_provider.dart';
import 'package:magic_epaper_app/provider/getitlocator.dart';
import 'package:magic_epaper_app/provider/image_loader.dart';
import 'package:provider/provider.dart';
Expand All @@ -8,6 +9,7 @@ void main() {
setupLocator();
runApp(MultiProvider(providers: [
ChangeNotifierProvider(create: (context) => ImageLoader()),
ChangeNotifierProvider(create: (context) => ColorAdjustmentProvider()),
], child: const MyApp()));
}

Expand Down
16 changes: 16 additions & 0 deletions lib/provider/color_adjustment_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'package:flutter/material.dart';

class ColorAdjustmentProvider extends ChangeNotifier {
Map<Color, double> _weights = {};

Map<Color, double> get weights => _weights;

void resetWeights(List<Color> colors) {
_weights = {for (var color in colors) color: 1.0};
Comment on lines +8 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): resetWeights does not notify listeners.

Since notifyListeners() is not called after updating _weights, UI components depending on this data may not refresh. Please add notifyListeners() after resetting the weights.

}

void updateWeights(Map<Color, double> newWeights) {
_weights = newWeights;
notifyListeners();
}
}
3 changes: 2 additions & 1 deletion lib/util/epd/epd.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import 'package:magic_epaper_app/util/image_processing/image_processing.dart';
abstract class Epd {
int get width;
int get height;
final processingMethods = <img.Image Function(img.Image)>[];
final processingMethods =
<img.Image Function(img.Image, Map<Color, double>)>[];
String get name;
String get modelId;
String get imgPath;
Expand Down
4 changes: 3 additions & 1 deletion lib/util/image_editor_utils.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import 'dart:ui';
import 'package:image/image.dart' as img;
import 'package:magic_epaper_app/util/epd/epd.dart';

List<img.Image> processImages({
required img.Image originalImage,
required Epd epd,
required Map<Color, double> weights,
}) {
final List<img.Image> processedImgs = [];

Expand All @@ -14,7 +16,7 @@ List<img.Image> processImages({
);

for (final method in epd.processingMethods) {
processedImgs.add(method(transformed));
processedImgs.add(method(transformed, weights));
}

return processedImgs;
Expand Down
51 changes: 33 additions & 18 deletions lib/util/image_processing/image_processing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,81 +5,95 @@ import 'extract_quantizer.dart';
import 'remap_quantizer.dart';

class ImageProcessing {
static img.Image bwFloydSteinbergDither(img.Image orgImg) {
static img.Image bwFloydSteinbergDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);
return img.ditherImage(image, quantizer: img.BinaryQuantizer());
}

static img.Image bwFalseFloydSteinbergDither(img.Image orgImg) {
static img.Image bwFalseFloydSteinbergDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);
return img.ditherImage(image,
quantizer: img.BinaryQuantizer(),
kernel: img.DitherKernel.falseFloydSteinberg);
}

static img.Image bwStuckiDither(img.Image orgImg) {
static img.Image bwStuckiDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);
return img.ditherImage(image,
quantizer: img.BinaryQuantizer(), kernel: img.DitherKernel.stucki);
}

static img.Image bwAtkinsonDither(img.Image orgImg) {
static img.Image bwAtkinsonDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);
return img.ditherImage(image,
quantizer: img.BinaryQuantizer(), kernel: img.DitherKernel.atkinson);
}

static img.Image bwThreshold(img.Image orgImg) {
static img.Image bwThreshold(img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);
return img.ditherImage(image,
quantizer: img.BinaryQuantizer(), kernel: img.DitherKernel.none);
}

static img.Image bwHalftoneDither(img.Image orgImg) {
static img.Image bwHalftoneDither(
img.Image orgImg, Map<Color, double> weights) {
final image = img.Image.from(orgImg);
img.grayscale(image);
img.colorHalftone(image, size: 3);
return img.ditherImage(image, quantizer: img.BinaryQuantizer());
}

static img.Image bwrHalftone(img.Image orgImg) {
static img.Image bwrHalftone(img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

img.colorHalftone(image, size: 3);
return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.floydSteinberg);
}

static img.Image bwrFloydSteinbergDither(img.Image orgImg) {
static img.Image bwrFloydSteinbergDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.floydSteinberg);
}

static img.Image bwrFalseFloydSteinbergDither(img.Image orgImg) {
static img.Image bwrFalseFloydSteinbergDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.falseFloydSteinberg);
}

static img.Image bwrStuckiDither(img.Image orgImg) {
static img.Image bwrStuckiDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.stucki);
}

static img.Image bwrTriColorAtkinsonDither(img.Image orgImg) {
static img.Image bwrTriColorAtkinsonDither(
img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.atkinson);
}

Expand All @@ -91,11 +105,12 @@ class ImageProcessing {
kernel: img.DitherKernel.none);
}

static img.Image bwrThreshold(img.Image orgImg) {
static img.Image bwrThreshold(img.Image orgImg, Map<Color, double> weights) {
var image = img.Image.from(orgImg);

return img.ditherImage(image,
quantizer: RemapQuantizer(palette: _createTriColorPalette()),
quantizer:
RemapQuantizer(palette: _createTriColorPalette(), weights: weights),
kernel: img.DitherKernel.none);
}
}
Expand Down
14 changes: 12 additions & 2 deletions lib/util/image_processing/remap_quantizer.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:image/image.dart' as img;
import 'dart:typed_data';
import 'package:flutter/material.dart';

class RemapQuantizer extends img.Quantizer {
@override
Expand All @@ -10,11 +11,12 @@ class RemapQuantizer extends img.Quantizer {
late final Uint8List _paletteR;
late final Uint8List _paletteG;
late final Uint8List _paletteB;
final Map<Color, double> weights;

final Map<int, int> _colorCache = {};
static const int _maxCacheSize = 1024;

RemapQuantizer({required this.palette}) {
RemapQuantizer({required this.palette, this.weights = const {}}) {
final numColors = palette.numColors;

_paletteR = Uint8List(numColors);
Expand Down Expand Up @@ -88,7 +90,15 @@ class RemapQuantizer extends img.Quantizer {
final dr = r - _paletteR[paletteIndex];
final dg = g - _paletteG[paletteIndex];
final db = b - _paletteB[paletteIndex];
return dr * dr + dg * dg + db * db;
final distanceSq = dr * dr + dg * dg + db * db;
final paletteColor = Color.fromARGB(255, _paletteR[paletteIndex],
_paletteG[paletteIndex], _paletteB[paletteIndex]);

final weight = weights[paletteColor] ?? 1.0;

if (weight <= 0) return 2147483647;

return (distanceSq / weight).round();
}

void _addToCache(int key, int value) {
Expand Down
Loading