Signed-off-by: Louis Chemineau <louis@chmn.me>
This commit is contained in:
Louis Chemineau 2024-01-04 10:13:36 +01:00
Родитель 5b8a5fc015
Коммит 26ff57067f
Не найден ключ, соответствующий данной подписи
14 изменённых файлов: 412 добавлений и 3 удалений

4
.gitignore поставляемый
Просмотреть файл

@ -145,3 +145,7 @@ symfony/process/Tests
thecodingmachine/safe/rector-migrate-0.7.php
wapmorgan/mp3info/_config.yml
kornrunner/blurhash/test
kornrunner/blurhash/.coveralls.yml
kornrunner/blurhash/infection.json.dist

Просмотреть файл

@ -29,6 +29,7 @@
"guzzlehttp/guzzle": "^7.5.0",
"icewind/searchdav": "^3.1.0",
"icewind/streams": "^0.7.7",
"kornrunner/blurhash": "^1.2",
"laravel/serializable-closure": "^1.2.2",
"mexitek/phpcolors": "^1.0",
"microsoft/azure-storage-blob": "^1.5.4",

50
composer.lock сгенерированный
Просмотреть файл

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c3013c5c52fded238303c4254923bb03",
"content-hash": "240cb2ea01f958680bf88737a3d64a45",
"packages": [
{
"name": "aws/aws-crt-php",
@ -1782,6 +1782,54 @@
},
"time": "2023-09-26T02:20:38+00:00"
},
{
"name": "kornrunner/blurhash",
"version": "v1.2.2",
"source": {
"type": "git",
"url": "https://github.com/kornrunner/php-blurhash.git",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kornrunner/php-blurhash/zipball/bc8a4596cb0a49874f0158696a382ab3933fefe4",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"require-dev": {
"ext-gd": "*",
"ocramius/package-versions": "^1.4|^2.0",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4.3"
},
"type": "library",
"autoload": {
"psr-4": {
"kornrunner\\Blurhash\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Boris Momčilović",
"email": "boris.momcilovic@gmail.com"
}
],
"description": "Pure PHP implementation of Blurhash",
"homepage": "https://github.com/kornrunner/php-blurhash",
"support": {
"issues": "https://github.com/kornrunner/php-blurhash/issues",
"source": "https://github.com/kornrunner/php-blurhash.git"
},
"time": "2022-07-13T19:38:39+00:00"
},
{
"name": "laravel/serializable-closure",
"version": "v1.2.2",

Просмотреть файл

@ -3440,6 +3440,11 @@ return array(
'cweagans\\Composer\\PatchEvent' => $vendorDir . '/cweagans/composer-patches/src/PatchEvent.php',
'cweagans\\Composer\\PatchEvents' => $vendorDir . '/cweagans/composer-patches/src/PatchEvents.php',
'cweagans\\Composer\\Patches' => $vendorDir . '/cweagans/composer-patches/src/Patches.php',
'kornrunner\\Blurhash\\AC' => $vendorDir . '/kornrunner/blurhash/src/AC.php',
'kornrunner\\Blurhash\\Base83' => $vendorDir . '/kornrunner/blurhash/src/Base83.php',
'kornrunner\\Blurhash\\Blurhash' => $vendorDir . '/kornrunner/blurhash/src/Blurhash.php',
'kornrunner\\Blurhash\\Color' => $vendorDir . '/kornrunner/blurhash/src/Color.php',
'kornrunner\\Blurhash\\DC' => $vendorDir . '/kornrunner/blurhash/src/DC.php',
'libphonenumber\\CountryCodeSource' => $vendorDir . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeSource.php',
'libphonenumber\\CountryCodeToRegionCodeMap' => $vendorDir . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeToRegionCodeMap.php',
'libphonenumber\\CountryCodeToRegionCodeMapForTesting' => $vendorDir . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeToRegionCodeMapForTesting.php',

Просмотреть файл

@ -10,6 +10,7 @@ return array(
'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
'ownCloud\\TarStreamer\\' => array($vendorDir . '/deepdiver1975/tarstreamer/src'),
'libphonenumber\\' => array($vendorDir . '/giggsey/libphonenumber-for-php-lite/src'),
'kornrunner\\Blurhash\\' => array($vendorDir . '/kornrunner/blurhash/src'),
'cweagans\\Composer\\' => array($vendorDir . '/cweagans/composer-patches/src'),
'bantu\\IniGetWrapper\\' => array($vendorDir . '/bantu/ini-get-wrapper/src'),
'ZipStreamer\\' => array($vendorDir . '/deepdiver/zipstreamer/src'),

Просмотреть файл

@ -141,6 +141,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652
array (
'libphonenumber\\' => 15,
),
'k' =>
array (
'kornrunner\\Blurhash\\' => 20,
),
'c' =>
array (
'cweagans\\Composer\\' => 18,
@ -301,6 +305,10 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652
array (
0 => __DIR__ . '/..' . '/giggsey/libphonenumber-for-php-lite/src',
),
'kornrunner\\Blurhash\\' =>
array (
0 => __DIR__ . '/..' . '/kornrunner/blurhash/src',
),
'cweagans\\Composer\\' =>
array (
0 => __DIR__ . '/..' . '/cweagans/composer-patches/src',
@ -4089,6 +4097,11 @@ class ComposerStaticInit2f23f73bc0cc116b4b1eee1521aa8652
'cweagans\\Composer\\PatchEvent' => __DIR__ . '/..' . '/cweagans/composer-patches/src/PatchEvent.php',
'cweagans\\Composer\\PatchEvents' => __DIR__ . '/..' . '/cweagans/composer-patches/src/PatchEvents.php',
'cweagans\\Composer\\Patches' => __DIR__ . '/..' . '/cweagans/composer-patches/src/Patches.php',
'kornrunner\\Blurhash\\AC' => __DIR__ . '/..' . '/kornrunner/blurhash/src/AC.php',
'kornrunner\\Blurhash\\Base83' => __DIR__ . '/..' . '/kornrunner/blurhash/src/Base83.php',
'kornrunner\\Blurhash\\Blurhash' => __DIR__ . '/..' . '/kornrunner/blurhash/src/Blurhash.php',
'kornrunner\\Blurhash\\Color' => __DIR__ . '/..' . '/kornrunner/blurhash/src/Color.php',
'kornrunner\\Blurhash\\DC' => __DIR__ . '/..' . '/kornrunner/blurhash/src/DC.php',
'libphonenumber\\CountryCodeSource' => __DIR__ . '/..' . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeSource.php',
'libphonenumber\\CountryCodeToRegionCodeMap' => __DIR__ . '/..' . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeToRegionCodeMap.php',
'libphonenumber\\CountryCodeToRegionCodeMapForTesting' => __DIR__ . '/..' . '/giggsey/libphonenumber-for-php-lite/src/CountryCodeToRegionCodeMapForTesting.php',

Просмотреть файл

@ -1851,6 +1851,57 @@
},
"install-path": "../justinrainbow/json-schema"
},
{
"name": "kornrunner/blurhash",
"version": "v1.2.2",
"version_normalized": "1.2.2.0",
"source": {
"type": "git",
"url": "https://github.com/kornrunner/php-blurhash.git",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/kornrunner/php-blurhash/zipball/bc8a4596cb0a49874f0158696a382ab3933fefe4",
"reference": "bc8a4596cb0a49874f0158696a382ab3933fefe4",
"shasum": ""
},
"require": {
"php": "^7.3|^8.0"
},
"require-dev": {
"ext-gd": "*",
"ocramius/package-versions": "^1.4|^2.0",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^9",
"vimeo/psalm": "^4.3"
},
"time": "2022-07-13T19:38:39+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
"psr-4": {
"kornrunner\\Blurhash\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Boris Momčilović",
"email": "boris.momcilovic@gmail.com"
}
],
"description": "Pure PHP implementation of Blurhash",
"homepage": "https://github.com/kornrunner/php-blurhash",
"support": {
"issues": "https://github.com/kornrunner/php-blurhash/issues",
"source": "https://github.com/kornrunner/php-blurhash.git"
},
"install-path": "../kornrunner/blurhash"
},
{
"name": "laravel/serializable-closure",
"version": "v1.2.2",

Просмотреть файл

@ -3,7 +3,7 @@
'name' => 'nextcloud/3rdparty',
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '8417c6d97148318316957adc082f7f50e5ea6e0e',
'reference' => '5b8a5fc015968956a000d269561cb5ec9d931870',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),
@ -235,6 +235,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
'kornrunner/blurhash' => array(
'pretty_version' => 'v1.2.2',
'version' => '1.2.2.0',
'reference' => 'bc8a4596cb0a49874f0158696a382ab3933fefe4',
'type' => 'library',
'install_path' => __DIR__ . '/../kornrunner/blurhash',
'aliases' => array(),
'dev_requirement' => false,
),
'laravel/serializable-closure' => array(
'pretty_version' => 'v1.2.2',
'version' => '1.2.2.0',
@ -310,7 +319,7 @@
'nextcloud/3rdparty' => array(
'pretty_version' => 'dev-master',
'version' => 'dev-master',
'reference' => '8417c6d97148318316957adc082f7f50e5ea6e0e',
'reference' => '5b8a5fc015968956a000d269561cb5ec9d931870',
'type' => 'library',
'install_path' => __DIR__ . '/../',
'aliases' => array(),

Просмотреть файл

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2019 Boris Momčilović
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Просмотреть файл

@ -0,0 +1,34 @@
<?php
namespace kornrunner\Blurhash;
final class AC {
public static function encode(array $value, float $max_value): float {
$quant_r = static::quantise($value[0] / $max_value);
$quant_g = static::quantise($value[1] / $max_value);
$quant_b = static::quantise($value[2] / $max_value);
return $quant_r * 19 * 19 + $quant_g * 19 + $quant_b;
}
public static function decode(int $value, float $max_value): array {
$quant_r = intdiv($value, 19 * 19);
$quant_g = intdiv($value, 19) % 19;
$quant_b = $value % 19;
return [
static::signPow(($quant_r - 9) / 9, 2) * $max_value,
static::signPow(($quant_g - 9) / 9, 2) * $max_value,
static::signPow(($quant_b - 9) / 9, 2) * $max_value
];
}
private static function quantise(float $value): float {
return floor(max(0, min(18, floor(static::signPow($value, 0.5) * 9 + 9.5))));
}
private static function signPow(float $base, float $exp): float {
$sign = $base <=> 0;
return $sign * pow(abs($base), $exp);
}
}

Просмотреть файл

@ -0,0 +1,39 @@
<?php
namespace kornrunner\Blurhash;
use InvalidArgumentException;
class Base83 {
private const ALPHABET = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z', '#', '$', '%', '*', '+', ',', '-', '.',
':', ';', '=', '?', '@', '[', ']', '^', '_', '{', '|', '}', '~'
];
private const BASE = 83;
public static function encode(int $value, int $length): string {
if (intdiv($value, self::BASE ** $length) != 0) {
throw new InvalidArgumentException('Specified length is too short to encode given value.');
}
$result = '';
for ($i = 1; $i <= $length; $i++) {
$digit = intdiv($value, self::BASE ** ($length - $i)) % self::BASE;
$result .= self::ALPHABET[$digit];
}
return $result;
}
public static function decode(string $hash): int {
$result = 0;
foreach (str_split($hash) as $char) {
$result = $result * self::BASE + (int) array_search($char, self::ALPHABET, true);
}
return $result;
}
}

Просмотреть файл

@ -0,0 +1,139 @@
<?php
namespace kornrunner\Blurhash;
use InvalidArgumentException;
class Blurhash {
public static function encode(array $image, int $components_x = 4, int $components_y = 4, bool $linear = false): string {
if (($components_x < 1 || $components_x > 9) || ($components_y < 1 || $components_y > 9)) {
throw new InvalidArgumentException("x and y component counts must be between 1 and 9 inclusive.");
}
$height = count($image);
$width = count($image[0]);
$image_linear = $image;
if (!$linear) {
$image_linear = [];
for ($y = 0; $y < $height; $y++) {
$line = [];
for ($x = 0; $x < $width; $x++) {
$pixel = $image[$y][$x];
$line[] = [
Color::toLinear($pixel[0]),
Color::toLinear($pixel[1]),
Color::toLinear($pixel[2])
];
}
$image_linear[] = $line;
}
}
$components = [];
$scale = 1 / ($width * $height);
for ($y = 0; $y < $components_y; $y++) {
for ($x = 0; $x < $components_x; $x++) {
$normalisation = $x == 0 && $y == 0 ? 1 : 2;
$r = $g = $b = 0;
for ($i = 0; $i < $width; $i++) {
for ($j = 0; $j < $height; $j++) {
$color = $image_linear[$j][$i];
$basis = $normalisation
* cos(M_PI * $i * $x / $width)
* cos(M_PI * $j * $y / $height);
$r += $basis * $color[0];
$g += $basis * $color[1];
$b += $basis * $color[2];
}
}
$components[] = [
$r * $scale,
$g * $scale,
$b * $scale
];
}
}
$dc_value = DC::encode(array_shift($components) ?: []);
$max_ac_component = 0;
foreach ($components as $component) {
$component[] = $max_ac_component;
$max_ac_component = max ($component);
}
$quant_max_ac_component = (int) max(0, min(82, floor($max_ac_component * 166 - 0.5)));
$ac_component_norm_factor = ($quant_max_ac_component + 1) / 166;
$ac_values = [];
foreach ($components as $component) {
$ac_values[] = AC::encode($component, $ac_component_norm_factor);
}
$blurhash = Base83::encode($components_x - 1 + ($components_y - 1) * 9, 1);
$blurhash .= Base83::encode($quant_max_ac_component, 1);
$blurhash .= Base83::encode($dc_value, 4);
foreach ($ac_values as $ac_value) {
$blurhash .= Base83::encode((int) $ac_value, 2);
}
return $blurhash;
}
public static function decode (string $blurhash, int $width, int $height, float $punch = 1.0, bool $linear = false): array {
if (empty($blurhash) || strlen($blurhash) < 6) {
throw new InvalidArgumentException("Blurhash string must be at least 6 characters");
}
$size_info = Base83::decode($blurhash[0]);
$size_y = intdiv($size_info, 9) + 1;
$size_x = ($size_info % 9) + 1;
$length = strlen($blurhash);
$expected_length = (int) (4 + (2 * $size_y * $size_x));
if ($length !== $expected_length) {
throw new InvalidArgumentException("Blurhash length mismatch: length is {$length} but it should be {$expected_length}");
}
$colors = [DC::decode(Base83::decode(substr($blurhash, 2, 4)))];
$quant_max_ac_component = Base83::decode($blurhash[1]);
$max_value = ($quant_max_ac_component + 1) / 166;
for ($i = 1; $i < $size_x * $size_y; $i++) {
$value = Base83::decode(substr($blurhash, 4 + $i * 2, 2));
$colors[$i] = AC::decode($value, $max_value * $punch);
}
$pixels = [];
for ($y = 0; $y < $height; $y++) {
$row = [];
for ($x = 0; $x < $width; $x++) {
$r = $g = $b = 0;
for ($j = 0; $j < $size_y; $j++) {
for ($i = 0; $i < $size_x; $i++) {
$color = $colors[$i + $j * $size_x];
$basis =
cos((M_PI * $x * $i) / $width) *
cos((M_PI * $y * $j) / $height);
$r += $color[0] * $basis;
$g += $color[1] * $basis;
$b += $color[2] * $basis;
}
}
$row[] = $linear ? [$r, $g, $b] : [
Color::toSRGB($r),
Color::toSRGB($g),
Color::toSRGB($b)
];
}
$pixels[] = $row;
}
return $pixels;
}
}

Просмотреть файл

@ -0,0 +1,20 @@
<?php
namespace kornrunner\Blurhash;
final class Color {
public static function toLinear(int $value): float {
$value = $value / 255;
return ($value <= 0.04045)
? $value / 12.92
: pow(($value + 0.055) / 1.055, 2.4);
}
public static function tosRGB(float $value): int {
$normalized = max(0, min(1, $value));
$result = ($normalized <= 0.0031308)
? (int) round($normalized * 12.92 * 255 + 0.5)
: (int) round((1.055 * pow($normalized, 1 / 2.4) - 0.055) * 255 + 0.5);
return max(0, min($result, 255));
}
}

Просмотреть файл

@ -0,0 +1,24 @@
<?php
namespace kornrunner\Blurhash;
final class DC {
public static function encode(array $value): int {
$rounded_r = Color::tosRGB($value[0]);
$rounded_g = Color::tosRGB($value[1]);
$rounded_b = Color::tosRGB($value[2]);
return ($rounded_r << 16) + ($rounded_g << 8) + $rounded_b;
}
public static function decode(int $value): array {
$r = $value >> 16;
$g = ($value >> 8) & 255;
$b = $value & 255;
return [
Color::toLinear($r),
Color::toLinear($g),
Color::toLinear($b)
];
}
}