whoami7 - Manager
:
/
home
/
kckglobal
/
www
/
portal
/
vendor
/
bacon
/
bacon-qr-code
/
src
/
Renderer
/
Upload File:
files >> //home/kckglobal/www/portal/vendor/bacon/bacon-qr-code/src/Renderer/GDLibRenderer.php
<?php declare(strict_types=1); namespace BaconQrCode\Renderer; use BaconQrCode\Encoder\ByteMatrix; use BaconQrCode\Encoder\MatrixUtil; use BaconQrCode\Encoder\QrCode; use BaconQrCode\Exception\InvalidArgumentException; use BaconQrCode\Exception\RuntimeException; use BaconQrCode\Renderer\Color\Alpha; use BaconQrCode\Renderer\Color\ColorInterface; use BaconQrCode\Renderer\RendererStyle\EyeFill; use BaconQrCode\Renderer\RendererStyle\Fill; use GdImage; final class GDLibRenderer implements RendererInterface { private ?GdImage $image; /** * @var array<string, int> */ private array $colors; public function __construct( private int $size, private int $margin = 4, private string $imageFormat = 'png', private int $compressionQuality = 9, private ?Fill $fill = null ) { if (! extension_loaded('gd') || ! function_exists('gd_info')) { throw new RuntimeException('You need to install the GD extension to use this back end'); } if ($this->fill === null) { $this->fill = Fill::default(); } if ($this->fill->hasGradientFill()) { throw new InvalidArgumentException('GDLibRenderer does not support gradients'); } } /** * @throws InvalidArgumentException if matrix width doesn't match height */ public function render(QrCode $qrCode): string { $matrix = $qrCode->getMatrix(); $matrixSize = $matrix->getWidth(); if ($matrixSize !== $matrix->getHeight()) { throw new InvalidArgumentException('Matrix must have the same width and height'); } MatrixUtil::removePositionDetectionPatterns($matrix); $this->newImage(); $this->draw($matrix); return $this->renderImage(); } private function newImage(): void { $img = imagecreatetruecolor($this->size, $this->size); if ($img === false) { throw new RuntimeException('Failed to create image of that size'); } $this->image = $img; imagealphablending($this->image, false); imagesavealpha($this->image, true); $bg = $this->getColor($this->fill->getBackgroundColor()); imagefilledrectangle($this->image, 0, 0, $this->size, $this->size, $bg); imagealphablending($this->image, true); } private function draw(ByteMatrix $matrix): void { $matrixSize = $matrix->getWidth(); $pointsOnSide = $matrix->getWidth() + $this->margin * 2; $pointInPx = $this->size / $pointsOnSide; $this->drawEye(0, 0, $pointInPx, $this->fill->getTopLeftEyeFill()); $this->drawEye($matrixSize - 7, 0, $pointInPx, $this->fill->getTopRightEyeFill()); $this->drawEye(0, $matrixSize - 7, $pointInPx, $this->fill->getBottomLeftEyeFill()); $rows = $matrix->getArray()->toArray(); $color = $this->getColor($this->fill->getForegroundColor()); for ($y = 0; $y < $matrixSize; $y += 1) { for ($x = 0; $x < $matrixSize; $x += 1) { if (! $rows[$y][$x]) { continue; } $points = $this->normalizePoints([ ($this->margin + $x) * $pointInPx, ($this->margin + $y) * $pointInPx, ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y) * $pointInPx, ($this->margin + $x + 1) * $pointInPx, ($this->margin + $y + 1) * $pointInPx, ($this->margin + $x) * $pointInPx, ($this->margin + $y + 1) * $pointInPx, ]); imagefilledpolygon($this->image, $points, $color); } } } private function drawEye(int $xOffset, int $yOffset, float $pointInPx, EyeFill $eyeFill): void { $internalColor = $this->getColor($eyeFill->inheritsInternalColor() ? $this->fill->getForegroundColor() : $eyeFill->getInternalColor()); $externalColor = $this->getColor($eyeFill->inheritsExternalColor() ? $this->fill->getForegroundColor() : $eyeFill->getExternalColor()); for ($y = 0; $y < 7; $y += 1) { for ($x = 0; $x < 7; $x += 1) { if ((($y === 1 || $y === 5) && $x > 0 && $x < 6) || (($x === 1 || $x === 5) && $y > 0 && $y < 6)) { continue; } $points = $this->normalizePoints([ ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx, ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset) * $pointInPx, ($this->margin + $x + $xOffset + 1) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx, ($this->margin + $x + $xOffset) * $pointInPx, ($this->margin + $y + $yOffset + 1) * $pointInPx, ]); if ($y > 1 && $y < 5 && $x > 1 && $x < 5) { imagefilledpolygon($this->image, $points, $internalColor); } else { imagefilledpolygon($this->image, $points, $externalColor); } } } } /** * Normalize points will trim right and bottom line by 1 pixel. * Otherwise pixels of neighbors are overlapping which leads to issue with transparency and small QR codes. */ private function normalizePoints(array $points): array { $maxX = $maxY = 0; for ($i = 0; $i < count($points); $i += 2) { // Do manual round as GD just removes decimal part $points[$i] = $newX = round($points[$i]); $points[$i + 1] = $newY = round($points[$i + 1]); $maxX = max($maxX, $newX); $maxY = max($maxY, $newY); } // Do trimming only if there are 4 points (8 coordinates), assumes this is square. for ($i = 0; $i < count($points); $i += 2) { $points[$i] = min($points[$i], $maxX - 1); $points[$i + 1] = min($points[$i + 1], $maxY - 1); } return $points; } private function renderImage(): string { ob_start(); $quality = $this->compressionQuality; switch ($this->imageFormat) { case 'png': if ($quality > 9 || $quality < 0) { $quality = 9; } imagepng($this->image, null, $quality); break; case 'gif': imagegif($this->image, null); break; case 'jpeg': case 'jpg': if ($quality > 100 || $quality < 0) { $quality = 85; } imagejpeg($this->image, null, $quality); break; default: ob_end_clean(); throw new InvalidArgumentException( 'Supported image formats are jpeg, png and gif, got: ' . $this->imageFormat ); } imagedestroy($this->image); $this->colors = []; $this->image = null; return ob_get_clean(); } private function getColor(ColorInterface $color): int { $alpha = 100; if ($color instanceof Alpha) { $alpha = $color->getAlpha(); $color = $color->getBaseColor(); } $rgb = $color->toRgb(); $colorKey = sprintf('%02X%02X%02X%02X', $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue(), $alpha); if (! isset($this->colors[$colorKey])) { $colorId = imagecolorallocatealpha( $this->image, $rgb->getRed(), $rgb->getGreen(), $rgb->getBlue(), (int)((100 - $alpha) / 100 * 127) // Alpha for GD is in range 0 (opaque) - 127 (transparent) ); if ($colorId === false) { throw new RuntimeException('Failed to create color: #' . $colorKey); } $this->colors[$colorKey] = $colorId; } return $this->colors[$colorKey]; } }
Copyright ©2021 || Defacer Indonesia