diff --git a/.gitignore b/.gitignore index efa3e41..06601c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -.gitignore - # Files and directories created by pub .dart_tool/ .packages diff --git a/.idea/image_compare_2.iml b/.idea/image_compare_2.iml new file mode 100644 index 0000000..6155e93 --- /dev/null +++ b/.idea/image_compare_2.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..639900d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..3434ff3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b62a71..5233063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,23 @@ +## 1.1.7 + +- took care of some lints + +## 1.1.6 + +- took care of some lints + +## 1.1.5 + +- took care of some lints + +## 1.1.4 + +- upgraded image dependency and formatted dart + +## 1.1.3 + +- forked as image_compare_2 with up to date dependencies and running example + ## 1.1.2 - Handle transparency with alpha channel option diff --git a/LICENSE b/LICENSE index 57adf77..881838d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2021 dart package: image_compare authors +Copyright 2021-2023 dart packages: image_compare and image_compre_2 authors Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/README.md b/README.md index cd9d829..e3ead01 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,13 @@ ![image1](https://github.com/nitinramadoss/image_compare/blob/main/images/seven2.PNG) ![image2](https://github.com/nitinramadoss/image_compare/blob/main/images/seven.PNG) -## What's New? +## Why image_compare_2 instead of image_compare? + +As a dependency, the great image_compare package was breaking some requirements and updates were not being published. +Thus, it has been updated as image_compare_2. +If image_compare ever becomes more up to date than image_compare_2, please prefer image_compare as it is the original package. + +## What was New? - Handle transparency with the alpha channel option - Set `ignoreAlpha` to `true` to ignore alpha channel - Available for EuclideanColorDistance, PixelMatching, and the histogram algorithms @@ -14,12 +20,12 @@ Add to pubspec.yaml ``` dependencies: - image_compare: ^1.1.1 + image_compare_2: ^1.1.3 ``` Import: ``` -import 'package:image_compare/image_compare.dart'; +import 'package:image_compare_2/image_compare_2.dart'; ``` ## Classes: @@ -51,8 +57,8 @@ var b = Uri.parse('https://hs.sbcounty.gov/cn/Photo%20Gallery/Sample%20Picture%2 ``` File example: ``` -var a = File('../images/tiger.jpg'); -var b = File('../images/leopard.png'); +var a = File('images/tiger.jpg'); +var b = File('images/leopard.png'); ``` Bytes example: ``` diff --git a/example/main.dart b/example/main.dart index 51d44c4..a628dca 100644 --- a/example/main.dart +++ b/example/main.dart @@ -1,26 +1,26 @@ import 'dart:io'; import 'package:image/image.dart'; -import 'package:image_compare/image_compare.dart'; +import 'package:image_compare_2/image_compare_2.dart'; void main(List arguments) async { var url1 = - 'https://www.tompetty.com/sites/g/files/g2000007521/f/sample_01.jpg'; + 'https://www.tompetty.com/sites/g/files/g2000014681/files/2022-06/TP%2520skateboard%25205.14.jpg'; var url2 = 'https://fujifilm-x.com/wp-content/uploads/2019/08/x-t30_sample-images03.jpg'; - var file1 = File('../images/drawings/kolam1.png'); - var file2 = File('../images/drawings/scribble1.png'); + var file1 = File('images/drawings/kolam1.png'); + var file2 = File('images/drawings/scribble1.png'); - var bytes1 = File('../images/animals/koala.jpg').readAsBytesSync(); - var bytes2 = File('../images/animals/komodo.jpg').readAsBytesSync(); + var bytes1 = File('images/animals/koala.jpg').readAsBytesSync(); + var bytes2 = File('images/animals/komodo.jpg').readAsBytesSync(); var image1 = decodeImage(bytes1); var image2 = decodeImage(bytes2); var assetImages = [ - File('../images/animals/bunny.jpg'), - File('../images/objects/red_apple.png'), - File('../images/animals/tiger.jpg') + File('images/animals/bunny.jpg'), + File('images/objects/red_apple.png'), + File('images/animals/tiger.jpg') ]; var networkImages = [ @@ -54,13 +54,17 @@ void main(List arguments) async { // Calculate euclidean color distance between two images var imageResult = await compareImages( - src1: file1, src2: file2, algorithm: EuclideanColorDistance(ignoreAlpha: true)); + src1: file1, + src2: file2, + algorithm: EuclideanColorDistance(ignoreAlpha: true)); print('Difference: ${imageResult * 100}%'); // Calculate pixel matching between one network and one asset image - var networkAssetResult = - await compareImages(src1: Uri.parse(url2), src2: image2, algorithm: PixelMatching(tolerance: 0.1)); + var networkAssetResult = await compareImages( + src1: Uri.parse(url2), + src2: image2, + algorithm: PixelMatching(tolerance: 0.1)); print('Difference: ${networkAssetResult * 100}%'); diff --git a/lib/image_compare.dart b/lib/image_compare_2.dart similarity index 70% rename from lib/image_compare.dart rename to lib/image_compare_2.dart index c8bd287..679502e 100644 --- a/lib/image_compare.dart +++ b/lib/image_compare_2.dart @@ -1,4 +1,4 @@ -library image_compare; +library image_compare_2; export 'src/algorithms.dart'; export 'src/functions.dart'; diff --git a/lib/src/algorithms.dart b/lib/src/algorithms.dart index cb205c7..fdbba64 100644 --- a/lib/src/algorithms.dart +++ b/lib/src/algorithms.dart @@ -4,7 +4,7 @@ import 'package:image/image.dart'; /// Abstract class for all algorithms abstract class Algorithm { /// [Pair] of [Pixel] lists for [src1] and [src2] - var _pixelListPair; + Pair _pixelListPair = Pair([], []); /// Default constructor gets implicitly called on subclass instantiation Algorithm(); @@ -97,7 +97,7 @@ abstract class DirectAlgorithm extends Algorithm { /// * Returns percentage difference (0.0 - no difference, 1.0 - 100% difference) class EuclideanColorDistance extends DirectAlgorithm { /// Ignores alpha channel when computing difference - var ignoreAlpha; + bool ignoreAlpha; EuclideanColorDistance({bool this.ignoreAlpha = false}); @@ -157,7 +157,7 @@ class EuclideanColorDistance extends DirectAlgorithm { /// * Returns percentage diffence (0.0 - no difference, 1.0 - 100% difference) class PixelMatching extends DirectAlgorithm { /// Ignores alpha channel when computing difference - var ignoreAlpha; + bool ignoreAlpha; /// Percentage tolerance value between 0.0 and 1.0 /// of the range of RGB values, 256, used when directly @@ -165,7 +165,7 @@ class PixelMatching extends DirectAlgorithm { /// /// A value of 0.05 means that one RGB value can be + or - /// (0.05 * 256) of another RGB value. - var tolerance; + double tolerance; PixelMatching({bool this.ignoreAlpha = false, this.tolerance = 0.05}); @@ -193,17 +193,17 @@ class PixelMatching extends DirectAlgorithm { _withinRange(delta, _pixelListPair._first[i]._green, _pixelListPair._second[i]._green)) { if (ignoreAlpha || - _withinRange(delta, _pixelListPair._first[i]._alpha, - _pixelListPair._second[i]._alpha)) { - count++; - } + _withinRange(delta, _pixelListPair._first[i]._alpha, + _pixelListPair._second[i]._alpha)) { + count++; + } } } return 1 - (count / numPixels); } - bool _withinRange(var delta, var value, var target) { + bool _withinRange(double delta, int value, int target) { return (target - delta <= value && value <= target + delta); } @@ -229,7 +229,7 @@ class PixelMatching extends DirectAlgorithm { /// * Returns percentage difference (0.0 - no difference, 1.0 - 100% difference) class IMED extends DirectAlgorithm { /// Width parameter of the guassian function - var sigma; + double sigma; /// Percentage of the smaller image's width representing a /// component of the window (box) width used for the gaussian blur. @@ -240,7 +240,7 @@ class IMED extends DirectAlgorithm { /// /// Note: Large [blurRatio] values can lead to a long computation time /// for comparisons. - var blurRatio; + double blurRatio; IMED({double this.sigma = 1, double this.blurRatio = 0.005}); @@ -310,12 +310,12 @@ class IMED extends DirectAlgorithm { /// Helper function to return grayscale value of a pixel int _grayValue(Pixel p) { - return getLuminanceRgb(p._red, p._green, p._blue); + return getLuminanceRgb(p._red, p._green, p._blue).round(); } /// Helper function to return distance between two pixels at /// indices [i] and [j] - double _distance(var i, var j, var width) { + double _distance(int i, int j, int width) { var distance = 0.0; var pointA = Pair((i % width), (i / width)); var pointB = Pair((j % width), (j / width)); @@ -602,10 +602,10 @@ class MedianHash extends HashAlgorithm { /// Abstract class for all histogram algorithms abstract class HistogramAlgorithm extends Algorithm { /// Number of bins in each histogram - var _binSize; + int _binSize = 256; /// Normalized histograms for [src1] and [src2] stored in a [Pair] - var _histograms; + Pair _histograms = Pair(RGBAHistogram(256), RGBAHistogram(256)); /// Default constructor gets implicitly called on subclass instantiation HistogramAlgorithm() { @@ -650,7 +650,7 @@ abstract class HistogramAlgorithm extends Algorithm { /// Organizational class for storing [src1] and [src2] data. /// Fields are RGBA histograms (256 element lists) class RGBAHistogram { - final _binSize; + final int _binSize; late List redHist; late List greenHist; late List blueHist; @@ -660,7 +660,7 @@ class RGBAHistogram { redHist = List.filled(_binSize, 0.0); greenHist = List.filled(_binSize, 0.0); blueHist = List.filled(_binSize, 0.0); - alphaHist = List.filled(_binSize, 0.0); + alphaHist = List.filled(_binSize, 0.0); } } @@ -678,7 +678,7 @@ class RGBAHistogram { /// * Returns percentage difference (0.0 - no difference, 1.0 - 100% difference) class ChiSquareDistanceHistogram extends HistogramAlgorithm { /// Ignores alpha channel when computing difference - var ignoreAlpha; + bool ignoreAlpha; ChiSquareDistanceHistogram({bool this.ignoreAlpha = false}); @@ -694,8 +694,9 @@ class ChiSquareDistanceHistogram extends HistogramAlgorithm { sum += _diff(_histograms._first.redHist, _histograms._second.redHist) + _diff(_histograms._first.greenHist, _histograms._second.greenHist) + - _diff(_histograms._first.blueHist, _histograms._second.blueHist) + - (alphaBit * _diff(_histograms._first.alphaHist, _histograms._second.alphaHist)); + _diff(_histograms._first.blueHist, _histograms._second.blueHist) + + (alphaBit * + _diff(_histograms._first.alphaHist, _histograms._second.alphaHist)); return sum / (3 + alphaBit); } @@ -740,7 +741,7 @@ class ChiSquareDistanceHistogram extends HistogramAlgorithm { /// * Returns percentage diffence (0.0 - no difference, 1.0 - 100% difference) class IntersectionHistogram extends HistogramAlgorithm { /// Ignores alpha channel when computing difference - var ignoreAlpha; + bool ignoreAlpha; IntersectionHistogram({bool this.ignoreAlpha = false}); @@ -756,8 +757,9 @@ class IntersectionHistogram extends HistogramAlgorithm { sum += _diff(_histograms._first.redHist, _histograms._second.redHist) + _diff(_histograms._first.greenHist, _histograms._second.greenHist) + - _diff(_histograms._first.blueHist, _histograms._second.blueHist) + - (alphaBit * _diff(_histograms._first.alphaHist, _histograms._second.alphaHist)); + _diff(_histograms._first.blueHist, _histograms._second.blueHist) + + (alphaBit * + _diff(_histograms._first.alphaHist, _histograms._second.alphaHist)); return 1 - (sum / (3 + alphaBit)); } diff --git a/lib/src/functions.dart b/lib/src/functions.dart index b9ff66d..afe3e6a 100644 --- a/lib/src/functions.dart +++ b/lib/src/functions.dart @@ -1,3 +1,4 @@ +import 'dart:typed_data'; import 'algorithms.dart'; import 'package:image/image.dart'; import 'package:universal_io/io.dart'; @@ -14,8 +15,8 @@ import 'package:universal_io/io.dart'; /// * [List]- list of integers (bytes representing the image) /// * [Image] - image buffer (Image class) Future compareImages({ - required var src1, - required var src2, + required dynamic src1, + required dynamic src2, Algorithm? algorithm, }) async { algorithm ??= PixelMatching(); // default algorithm @@ -48,7 +49,7 @@ Future compareImages({ /// * [List]- list of integers (bytes representing the image) /// * [Image] - image buffer (Image class) Future> listCompare({ - required var target, + required dynamic target, required List list, Algorithm? algorithm, }) async { @@ -64,7 +65,7 @@ Future> listCompare({ return results; } -Future _getImageFromDynamic(var src) async { +Future _getImageFromDynamic(dynamic src) async { // Error message if image format can't be identified var err = 'A valid image could not be identified from '; var bytes = []; @@ -88,9 +89,11 @@ Future _getImageFromDynamic(var src) async { err += '$list<...>'; } else if (src is Image) { - err += '$src. $src.data.length != width * height'; + err += + '${src.width}x${src.height}!=${src.data?.length ?? 0} length != width * height'; - if (src.height * src.width != src.data.length) { + if (src.height * src.width != (src.data?.length ?? 0) && + src.height * src.width * 3 != (src.data?.length ?? 0)) { throw FormatException(err); } @@ -109,10 +112,10 @@ Future _getImageFromDynamic(var src) async { /// of bytes format and return [Image]. /// Throws exception if format is invalid. Image _getValidImage(List bytes, String err) { - var image; + Image? image; try { - image = decodeImage(bytes); - } catch (Exception) { + image = decodeImage(Uint8List.fromList(bytes)); + } catch (e) { throw FormatException("Insufficient data provided to identify image."); } diff --git a/pubspec.lock b/pubspec.lock index 0e94cc2..6fa59d4 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,78 +5,113 @@ packages: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: e0902a06f0e00414e4e3438a084580161279f137aeb862274710f29ec10cf01e + url: "https://pub.dev" source: hosted - version: "3.1.2" + version: "3.3.9" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "3.0.3" image: dependency: "direct main" description: name: image - url: "https://pub.dartlang.org" + sha256: a72242c9a0ffb65d03de1b7113bc4e189686fc07c7147b8b41811d0dd0e0d9bf + url: "https://pub.dev" + source: hosted + version: "4.0.17" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "0.6.7" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452" + url: "https://pub.dev" + source: hosted + version: "2.1.1" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + url: "https://pub.dev" source: hosted - version: "1.4.0" + version: "1.10.0" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.0" - pedantic: - dependency: "direct dev" - description: - name: pedantic - url: "https://pub.dartlang.org" + sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.8.3" petitparser: dependency: transitive description: name: petitparser - url: "https://pub.dartlang.org" + sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 + url: "https://pub.dev" + source: hosted + version: "6.0.1" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + url: "https://pub.dev" source: hosted - version: "4.1.0" + version: "3.7.3" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.3.2" universal_io: dependency: "direct main" description: name: universal_io - url: "https://pub.dartlang.org" + sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" + url: "https://pub.dev" source: hosted - version: "2.0.4" + version: "2.2.2" xml: dependency: transitive description: name: xml - url: "https://pub.dartlang.org" + sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556 + url: "https://pub.dev" source: hosted - version: "5.1.2" + version: "6.4.2" sdks: - dart: ">=2.12.0 <3.0.0" + dart: ">=3.0.0 <4.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 5bf0fc5..e22608d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,20 +1,17 @@ -name: image_compare -description: Dart package for image comparison. Compare images for difference using a variety of algorithms. -repository: https://github.com/nitinramadoss/image_compare -version: 1.1.2 +name: image_compare_2 +description: Package maintained based on image_compare. Compare images using a variety of algorithms. +repository: https://github.com/lcuis/image_compare +version: 1.1.7 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.12.0 <4.0.0" dependencies: - image: ^3.0.0 - universal_io: ^2.0.0 + image: '>=4.0.17 <6.0.0' + universal_io: '>=2.0.0 <4.0.0' dev_dependencies: - pedantic: ^1.9.0 + lints: '>=1.0.0 <4.0.0' assets: - - assets/ - - assets/drawings/ - - assets/animals/ - - assets/objects/ + - images/