17
17
18
18
namespace Fisharebest \Webtrees \Http \Controllers ;
19
19
20
+ use BigV \ImageCompare ;
20
21
use DirectoryIterator ;
21
22
use Fisharebest \Algorithm \MyersDiff ;
22
23
use Fisharebest \Webtrees \Auth ;
40
41
use Fisharebest \Webtrees \Tree ;
41
42
use Fisharebest \Webtrees \User ;
42
43
use Fisharebest \Webtrees \View ;
44
+ use Intervention \Image \Image ;
45
+ use Intervention \Image \ImageManager ;
43
46
use RecursiveDirectoryIterator ;
44
47
use RecursiveIteratorIterator ;
45
- use stdClass ;
46
48
use Symfony \Component \HttpFoundation \JsonResponse ;
47
49
use Symfony \Component \HttpFoundation \RedirectResponse ;
48
50
use Symfony \Component \HttpFoundation \Request ;
49
51
use Symfony \Component \HttpFoundation \Response ;
50
52
use Symfony \Component \HttpFoundation \ResponseHeaderBag ;
53
+ use stdClass ;
51
54
52
55
/**
53
56
* Controller for the administration pages
@@ -1095,7 +1098,7 @@ public function webtrees1ThumbnailsData(Request $request): JsonResponse {
1095
1098
$ recordsTotal = count ($ thumbnails );
1096
1099
1097
1100
if ($ search !== '' ) {
1098
- $ thumbnails = array_filter ($ thumbnails , function (string $ thumbnail ) use ($ search ) {
1101
+ $ thumbnails = array_filter ($ thumbnails , function (string $ thumbnail ) use ($ search ) {
1099
1102
return stripos ($ thumbnail , $ search ) !== false ;
1100
1103
});
1101
1104
}
@@ -1146,10 +1149,10 @@ public function webtrees1ThumbnailsData(Request $request): JsonResponse {
1146
1149
1147
1150
1148
1151
return [
1149
- '<img src=" ' . e ($ thumbnail_url ) . '"><br> ' . str_replace ( ' / ' , ' /‌ ' , e ($ thumbnail_path )) ,
1150
- '<img src=" ' . e ($ original_url ) . '"><br> ' . str_replace ( ' / ' , ' /‌ ' , e ($ original_path )) ,
1152
+ '<img src=" ' . e ($ thumbnail_url ) . '" title=" ' . e ($ thumbnail_path ) . ' "> ' ,
1153
+ '<img src=" ' . e ($ original_url ) . '" title=" ' . e ($ original_path ) . ' "> ' ,
1151
1154
$ media ,
1152
- $ status . ' ' . $ import . ' ' . $ delete ,
1155
+ $ status . ' ' . $ import . ' ' . $ delete . ' ' . @ $ this -> imageDiff ( $ original , $ thumbnail ) ,
1153
1156
];
1154
1157
}, $ thumbnails );
1155
1158
@@ -1824,7 +1827,7 @@ private function findMediaObjectsForMediaFile(string $file): array {
1824
1827
/**
1825
1828
* Find the original image that corresponds to a (webtrees 1.x) thumbnail file.
1826
1829
*
1827
- * @param string $thumbanil
1830
+ * @param string $thumbnail
1828
1831
*
1829
1832
* @return string
1830
1833
*/
@@ -1833,7 +1836,7 @@ private function findOriginalFileFromThumbnail(string $thumbnail): string {
1833
1836
$ original = dirname (dirname ($ thumbnail )) . '/ ' . basename ($ thumbnail );
1834
1837
1835
1838
// Second option - a .PNG thumbnail for some other image type
1836
- if (substr_compare ($ original ,'.png ' , -4 , 4 ) === 0 ) {
1839
+ if (substr_compare ($ original , '.png ' , -4 , 4 ) === 0 ) {
1837
1840
$ pattern = substr ($ original , 0 , -3 ) . '* ' ;
1838
1841
$ matches = glob ($ pattern );
1839
1842
if (!empty ($ matches ) && is_file ($ matches [0 ])) {
@@ -1844,11 +1847,53 @@ private function findOriginalFileFromThumbnail(string $thumbnail): string {
1844
1847
return $ original ;
1845
1848
}
1846
1849
1850
+ /**
1851
+ * Compare two images, and return a quantified difference.
1852
+ *
1853
+ * 0 (different) ... 100 (same)
1854
+ *
1855
+ * @param $image1
1856
+ * @param $image2
1857
+ *
1858
+ * @return int
1859
+ */
1860
+ private function imageDiff ($ image1 , $ image2 ): int {
1861
+ $ size = 10 ;
1862
+
1863
+ // Convert images to 10x10
1864
+ try {
1865
+ $ manager = new ImageManager ;
1866
+ $ image1 = $ manager ->make ($ image1 )->resize ($ size , $ size );
1867
+ $ image2 = $ manager ->make ($ image2 )->resize ($ size , $ size );
1868
+ } catch (\Throwable $ ex ) {
1869
+ //var_dump($image1, $image2);
1870
+ //throw $ex;
1871
+ return -1 ;
1872
+ }
1873
+
1874
+ $ max_difference = 0 ;
1875
+ // Compare each pixel
1876
+ for ($ x = 0 ; $ x < $ size ; ++$ x ) {
1877
+ for ($ y = 0 ; $ y < $ size ; ++$ y ) {
1878
+ // Sum the RGB channels to convert to grayscale.
1879
+ $ pixel1 = $ image1 ->pickColor ($ x , $ y );
1880
+ $ pixel2 = $ image2 ->pickColor ($ x , $ y );
1881
+ $ value1 = $ pixel1 [0 ] + $ pixel1 [1 ] + $ pixel1 [2 ];
1882
+ $ value2 = $ pixel2 [0 ] + $ pixel2 [1 ] + $ pixel2 [2 ];
1883
+
1884
+ $ max_difference = max ($ max_difference , abs ($ value1 - $ value2 ));
1885
+ }
1886
+ }
1887
+
1888
+ // The maximum difference is 3 x 255 = 765 (black versus white).
1889
+
1890
+ return 100 - (int ) ($ max_difference * 100 / 765 );
1891
+ }
1847
1892
1848
1893
/**
1849
1894
* Does the thumbnail file appear to be custom generated.
1850
- * If yes, we should probably import it.
1851
- * If no, we should probably delete it.
1895
+ * If yes (true) , we should probably import it.
1896
+ * If no (false) , we should probably delete it.
1852
1897
*
1853
1898
* @param string $original
1854
1899
* @param string $thumbnail
@@ -1874,23 +1919,21 @@ private function isCustomWebtrees1Thumbnail(string $original, string $thumbnail)
1874
1919
return true ;
1875
1920
}
1876
1921
1877
- // The same size image?
1878
- if ($ original_attributes [3 ] === $ thumbnail_attributes [3 ]) {
1879
- return false ;
1880
- }
1881
-
1882
1922
// Different aspect ratio? Use exact same algorithm as webtrees 1.x
1883
1923
$ original_width = $ original_attributes [0 ];
1884
1924
$ original_height = $ original_attributes [1 ];
1885
1925
$ thumbnail_width = $ thumbnail_attributes [0 ];
1886
1926
$ thumbnail_height = $ thumbnail_attributes [1 ];
1887
1927
$ calculated_height = round ($ original_height * ($ thumbnail_width / $ original_width ));
1888
1928
1889
- if ($ calculated_height !== $ thumbnail_height ) {
1929
+ if (abs ( $ calculated_height - $ thumbnail_height) > 1 ) {
1890
1930
return true ;
1891
1931
}
1892
1932
1893
- return true ;
1933
+ // Do a pixel-by-pixel comparison
1934
+ $ image_compare = new ImageCompare ;
1935
+
1936
+ return $ image_compare ->compare ($ original , $ thumbnail ) >= 10 ;
1894
1937
}
1895
1938
1896
1939
/**
0 commit comments