mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
PoC for qr code gneration 2
This commit is contained in:
@@ -8,6 +8,8 @@ use Appwrite\SDK\MethodType;
|
||||
use Appwrite\SDK\Response as SDKResponse;
|
||||
use Appwrite\URL\URL as URLParse;
|
||||
use Appwrite\Utopia\Response;
|
||||
use chillerlan\QRCode\Common\EccLevel;
|
||||
use chillerlan\QRCode\Output\QRImagick;
|
||||
use chillerlan\QRCode\QRCode;
|
||||
use chillerlan\QRCode\QROptions;
|
||||
use Utopia\App;
|
||||
@@ -485,17 +487,28 @@ App::get('/v1/avatars/qr')
|
||||
contentType: ContentType::IMAGE_PNG
|
||||
))
|
||||
->param('text', '', new Text(512), 'Plain text to be converted to QR code image.')
|
||||
->param('size', 400, new Range(1, 1000), 'QR code size. Pass an integer between 1 to 1000. Defaults to 400.', true)
|
||||
->param('margin', 1, new Range(0, 10), 'Margin from edge. Pass an integer between 0 to 10. Defaults to 1.', true)
|
||||
->param('size', 512, new Range(32, 1024), 'QR code size. Pass an integer between 32 to 1024. Defaults to 512.', true)
|
||||
->param('margin', 1, new Range(0, 128), 'Margin from edge. Pass an integer between 0 to 128. Defaults to 1.', true)
|
||||
->param('download', false, new Boolean(true), 'Return resulting image with \'Content-Disposition: attachment \' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.', true)
|
||||
->inject('response')
|
||||
->action(function (string $text, int $size, int $margin, bool $download, Response $response) {
|
||||
|
||||
->action(function (string $text, int $size, int $margin, mixed $download, Response $response) {
|
||||
$download = ($download === '1' || $download === 'true' || $download === 1 || $download === true);
|
||||
|
||||
$options = new QROptions([
|
||||
'addQuietzone' => true,
|
||||
'quietzoneSize' => $margin,
|
||||
'outputType' => QRCode::OUTPUT_IMAGICK,
|
||||
'addQuietzone' => $margin > 0,
|
||||
'readerUseImagickIfAvailable' => true,
|
||||
'outputInterface' => QRGdRounded::class,
|
||||
'returnResource' => true,
|
||||
'outputBase64' => false,
|
||||
'scale' => 64,
|
||||
'quality' => 75,
|
||||
'imagickFormat' => 'png',
|
||||
'drawCircularModules' => true,
|
||||
'addLogoSpace' => true,
|
||||
'eccLevel' => EccLevel::H, // Needed for addLogoSpace
|
||||
'logoSpaceWidth' => 10,
|
||||
'logoSpaceHeight' => 10,
|
||||
]);
|
||||
|
||||
$qrcode = new QRCode($options);
|
||||
@@ -507,10 +520,33 @@ App::get('/v1/avatars/qr')
|
||||
$image = new Image($qrcode->render($text));
|
||||
$image->crop((int) $size, (int) $size);
|
||||
|
||||
$logo = \file_get_contents('https://appwrite.io/assets/logomark/logo.png');
|
||||
$logoImg = new Image($logo);
|
||||
$logoImg->crop(128 + 16, 128);
|
||||
|
||||
$image->image->setImageColorspace($logoImg->image->getImageColorspace());
|
||||
|
||||
$image->image->compositeImage($logoImg->image, Imagick::COMPOSITE_OVER, 192 - 8, 192);
|
||||
|
||||
$markerUrl = 'https://cloud.appwrite.io/v1/storage/buckets/67c4487d0010bd67a4f4/files/marker3/view?project=67c2cb23003706429442';
|
||||
$marker = \file_get_contents($markerUrl);
|
||||
|
||||
$markerImg = new Image($marker);
|
||||
$markerImg->crop(120, 120);
|
||||
$image->image->compositeImage($markerImg->image, Imagick::COMPOSITE_OVER, 16, 16);
|
||||
|
||||
$markerImg->image->rotateImage('transparent', 90);
|
||||
$image->image->compositeImage($markerImg->image, Imagick::COMPOSITE_OVER, 376, 16);
|
||||
|
||||
$markerImg->image->rotateImage('transparent', 180);
|
||||
$image->image->compositeImage($markerImg->image, Imagick::COMPOSITE_OVER, 16, 376);
|
||||
|
||||
// TODO: Overlay last small marker too
|
||||
|
||||
$response
|
||||
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
|
||||
->setContentType('image/png')
|
||||
->send($image->output('png', 9));
|
||||
->send($image->output('png', 75));
|
||||
});
|
||||
|
||||
App::get('/v1/avatars/initials')
|
||||
@@ -1277,3 +1313,81 @@ App::get('/v1/cards/cloud-og')
|
||||
->setContentType('image/png')
|
||||
->file($baseImage->getImageBlob());
|
||||
});
|
||||
|
||||
class QRGdRounded extends QRImagick
|
||||
{
|
||||
protected function module(int $x, int $y, int $M_TYPE): void
|
||||
{
|
||||
if (!$this->matrix->isDark($M_TYPE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->imagickDraw->setFillColor($this->getModuleValue($M_TYPE));
|
||||
|
||||
|
||||
/*
|
||||
$this->imagickDraw->circle(
|
||||
(($x + 0.5) * $this->scale),
|
||||
(($y + 0.5) * $this->scale),
|
||||
((($x + 0.5 + $this->circleRadius) * $this->scale) - 8),
|
||||
((($y + 0.5) * $this->scale) - 8)
|
||||
);
|
||||
|
||||
return;
|
||||
*/
|
||||
|
||||
$neighbours = $this->matrix->checkNeighbours($x, $y);
|
||||
$x1 = ($x * $this->scale);
|
||||
$y1 = ($y * $this->scale);
|
||||
$x2 = (($x + 1) * $this->scale);
|
||||
$y2 = (($y + 1) * $this->scale);
|
||||
$rectsize = (int)($this->scale / 2);
|
||||
|
||||
// ------------------
|
||||
// Outer rounding
|
||||
// ------------------
|
||||
|
||||
if (($neighbours & (1 << 7))) { // neighbour left
|
||||
// top left
|
||||
$this->imagickDraw->rectangle($x1, $y1, ($x1 + $rectsize), ($y1 + $rectsize));
|
||||
// bottom left
|
||||
$this->imagickDraw->rectangle($x1, ($y2 - $rectsize), ($x1 + $rectsize), $y2);
|
||||
}
|
||||
|
||||
if (($neighbours & (1 << 3))) { // neighbour right
|
||||
// top right
|
||||
$this->imagickDraw->rectangle(($x2 - $rectsize), $y1, $x2, ($y1 + $rectsize));
|
||||
// bottom right
|
||||
$this->imagickDraw->rectangle(($x2 - $rectsize), ($y2 - $rectsize), $x2, $y2);
|
||||
}
|
||||
|
||||
if (($neighbours & (1 << 1))) { // neighbour top
|
||||
// top left
|
||||
$this->imagickDraw->rectangle($x1, $y1, ($x1 + $rectsize), ($y1 + $rectsize));
|
||||
// top right
|
||||
$this->imagickDraw->rectangle(($x2 - $rectsize), $y1, $x2, ($y1 + $rectsize));
|
||||
}
|
||||
|
||||
if (($neighbours & (1 << 5))) { // neighbour bottom
|
||||
// bottom left
|
||||
$this->imagickDraw->rectangle($x1, ($y2 - $rectsize), ($x1 + $rectsize), $y2);
|
||||
// bottom right
|
||||
$this->imagickDraw->rectangle(($x2 - $rectsize), ($y2 - $rectsize), $x2, $y2);
|
||||
}
|
||||
|
||||
$this->imagickDraw->circle(
|
||||
(($x + 0.5) * $this->scale),
|
||||
(($y + 0.5) * $this->scale),
|
||||
((($x + 0.5 + $this->circleRadius) * $this->scale) + 2),
|
||||
((($y + 0.5) * $this->scale) + 2)
|
||||
);
|
||||
|
||||
/*
|
||||
$this->imagickDraw->rectangle(
|
||||
$x1, $y1, $x2, $y2
|
||||
);
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@
|
||||
"matomo/device-detector": "6.1.*",
|
||||
"dragonmantank/cron-expression": "3.3.2",
|
||||
"phpmailer/phpmailer": "6.9.1",
|
||||
"chillerlan/php-qrcode": "4.3.4",
|
||||
"chillerlan/php-qrcode": "dev-main",
|
||||
"adhocore/jwt": "1.1.2",
|
||||
"spomky-labs/otphp": "^10.0",
|
||||
"webonyx/graphql-php": "14.11.*",
|
||||
|
||||
Generated
+79
-72
@@ -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": "6883b3e81cfb0c5355997def668d5df2",
|
||||
"content-hash": "4e5e640d4909991707c193d0e348d677",
|
||||
"packages": [
|
||||
{
|
||||
"name": "adhocore/jwt",
|
||||
@@ -279,16 +279,16 @@
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.12.2",
|
||||
"version": "0.12.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/brick/math.git",
|
||||
"reference": "901eddb1e45a8e0f689302e40af871c181ecbe40"
|
||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/901eddb1e45a8e0f689302e40af871c181ecbe40",
|
||||
"reference": "901eddb1e45a8e0f689302e40af871c181ecbe40",
|
||||
"url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba",
|
||||
"reference": "866551da34e9a618e64a819ee1e01c20d8a588ba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -327,7 +327,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/brick/math/issues",
|
||||
"source": "https://github.com/brick/math/tree/0.12.2"
|
||||
"source": "https://github.com/brick/math/tree/0.12.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -335,50 +335,70 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-26T10:21:45+00:00"
|
||||
"time": "2025-02-28T13:11:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "chillerlan/php-qrcode",
|
||||
"version": "4.3.4",
|
||||
"version": "dev-main",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chillerlan/php-qrcode.git",
|
||||
"reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d"
|
||||
"reference": "b5ff1258a9a8bf6eff15d8c12365400ba60d652c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d",
|
||||
"reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/b5ff1258a9a8bf6eff15d8c12365400ba60d652c",
|
||||
"reference": "b5ff1258a9a8bf6eff15d8c12365400ba60d652c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"chillerlan/php-settings-container": "^2.1.4",
|
||||
"chillerlan/php-settings-container": "^3.2.1",
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.4 || ^8.0"
|
||||
"php": "^8.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"phan/phan": "^5.3",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"setasign/fpdf": "^1.8.2"
|
||||
"chillerlan/php-authenticator": "^5.2.1",
|
||||
"ext-fileinfo": "*",
|
||||
"intervention/image": "^3.8",
|
||||
"phpbench/phpbench": "^1.3",
|
||||
"phpmd/phpmd": "^2.15",
|
||||
"phpstan/phpstan": "^2.0",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0",
|
||||
"phpunit/phpunit": "^11.3",
|
||||
"setasign/fpdf": "^1.8.2",
|
||||
"slevomat/coding-standard": "^8.15",
|
||||
"squizlabs/php_codesniffer": "^3.10"
|
||||
},
|
||||
"suggest": {
|
||||
"chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.",
|
||||
"setasign/fpdf": "Required to use the QR FPDF output."
|
||||
"intervention/image": "More advanced GD and ImageMagick output.",
|
||||
"setasign/fpdf": "Required to use the QR FPDF output.",
|
||||
"simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code"
|
||||
},
|
||||
"default-branch": true,
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"chillerlan\\QRCode\\": "src/"
|
||||
"chillerlan\\QRCode\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
"MIT",
|
||||
"Apache-2.0"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kazuhiko Arase",
|
||||
"homepage": "https://github.com/kazuhikoarase"
|
||||
"homepage": "https://github.com/kazuhikoarase/qrcode-generator"
|
||||
},
|
||||
{
|
||||
"name": "ZXing Authors",
|
||||
"homepage": "https://github.com/zxing/zxing"
|
||||
},
|
||||
{
|
||||
"name": "Ashot Khanamiryan",
|
||||
"homepage": "https://github.com/khanamiryan/php-qrcode-detector-decoder"
|
||||
},
|
||||
{
|
||||
"name": "Smiley",
|
||||
@@ -390,54 +410,53 @@
|
||||
"homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "A QR code generator. PHP 7.4+",
|
||||
"description": "A QR Code generator and reader with a user-friendly API. PHP 8.2+",
|
||||
"homepage": "https://github.com/chillerlan/php-qrcode",
|
||||
"keywords": [
|
||||
"phpqrcode",
|
||||
"qr",
|
||||
"qr code",
|
||||
"qr-reader",
|
||||
"qrcode",
|
||||
"qrcode-generator"
|
||||
"qrcode-generator",
|
||||
"qrcode-reader"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://php-qrcode.readthedocs.io",
|
||||
"issues": "https://github.com/chillerlan/php-qrcode/issues",
|
||||
"source": "https://github.com/chillerlan/php-qrcode/tree/4.3.4"
|
||||
"source": "https://github.com/chillerlan/php-qrcode"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://ko-fi.com/codemasher",
|
||||
"type": "ko_fi"
|
||||
"type": "Ko-Fi"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-25T09:12:45+00:00"
|
||||
"time": "2024-11-27T19:19:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "chillerlan/php-settings-container",
|
||||
"version": "2.1.6",
|
||||
"version": "3.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/chillerlan/php-settings-container.git",
|
||||
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb"
|
||||
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb",
|
||||
"reference": "5553558bd381fce5108c6d0343c12e488cfec6bb",
|
||||
"url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
|
||||
"reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": "^7.4 || ^8.0"
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpmd/phpmd": "^2.15",
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.2",
|
||||
"phpunit/phpunit": "^9.6",
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"squizlabs/php_codesniffer": "^3.10"
|
||||
},
|
||||
"type": "library",
|
||||
@@ -457,10 +476,9 @@
|
||||
"homepage": "https://github.com/codemasher"
|
||||
}
|
||||
],
|
||||
"description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+",
|
||||
"description": "A container class for immutable settings objects. Not a DI container.",
|
||||
"homepage": "https://github.com/chillerlan/php-settings-container",
|
||||
"keywords": [
|
||||
"PHP7",
|
||||
"Settings",
|
||||
"configuration",
|
||||
"container",
|
||||
@@ -480,7 +498,7 @@
|
||||
"type": "ko_fi"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-17T01:04:28+00:00"
|
||||
"time": "2024-07-16T11:13:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
@@ -2371,16 +2389,16 @@
|
||||
},
|
||||
{
|
||||
"name": "ramsey/collection",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ramsey/collection.git",
|
||||
"reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5"
|
||||
"reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
|
||||
"reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5",
|
||||
"url": "https://api.github.com/repos/ramsey/collection/zipball/3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
|
||||
"reference": "3c5990b8a5e0b79cd1cf11c2dc1229e58e93f109",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2388,25 +2406,22 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"captainhook/plugin-composer": "^5.3",
|
||||
"ergebnis/composer-normalize": "^2.28.3",
|
||||
"fakerphp/faker": "^1.21",
|
||||
"ergebnis/composer-normalize": "^2.45",
|
||||
"fakerphp/faker": "^1.24",
|
||||
"hamcrest/hamcrest-php": "^2.0",
|
||||
"jangregor/phpstan-prophecy": "^1.0",
|
||||
"mockery/mockery": "^1.5",
|
||||
"jangregor/phpstan-prophecy": "^2.1",
|
||||
"mockery/mockery": "^1.6",
|
||||
"php-parallel-lint/php-console-highlighter": "^1.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.3",
|
||||
"phpcsstandards/phpcsutils": "^1.0.0-rc1",
|
||||
"phpspec/prophecy-phpunit": "^2.0",
|
||||
"phpstan/extension-installer": "^1.2",
|
||||
"phpstan/phpstan": "^1.9",
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.3",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"psalm/plugin-mockery": "^1.1",
|
||||
"psalm/plugin-phpunit": "^0.18.4",
|
||||
"ramsey/coding-standard": "^2.0.3",
|
||||
"ramsey/conventional-commits": "^1.3",
|
||||
"vimeo/psalm": "^5.4"
|
||||
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||
"phpspec/prophecy-phpunit": "^2.3",
|
||||
"phpstan/extension-installer": "^1.4",
|
||||
"phpstan/phpstan": "^2.1",
|
||||
"phpstan/phpstan-mockery": "^2.0",
|
||||
"phpstan/phpstan-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^10.5",
|
||||
"ramsey/coding-standard": "^2.3",
|
||||
"ramsey/conventional-commits": "^1.6",
|
||||
"roave/security-advisories": "dev-latest"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
@@ -2444,19 +2459,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/ramsey/collection/issues",
|
||||
"source": "https://github.com/ramsey/collection/tree/2.0.0"
|
||||
"source": "https://github.com/ramsey/collection/tree/2.1.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ramsey",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/ramsey/collection",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-31T21:50:55+00:00"
|
||||
"time": "2025-03-02T04:48:29+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ramsey/uuid",
|
||||
@@ -8806,7 +8811,9 @@
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": [],
|
||||
"stability-flags": {
|
||||
"chillerlan/php-qrcode": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
|
||||
@@ -85,6 +85,7 @@ services:
|
||||
- ./public:/usr/src/code/public
|
||||
- ./src:/usr/src/code/src
|
||||
- ./dev:/usr/src/code/dev
|
||||
- ./vendor/utopia-php/image:/usr/src/code/vendor/utopia-php/image # Exposed private image to do Imagick operations
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
|
||||
Reference in New Issue
Block a user