mirror of
				https://github.com/elyby/accounts.git
				synced 2025-05-31 14:11:46 +05:30 
			
		
		
		
	
		
			
				
	
	
		
			117 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			117 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| namespace common\components\Qr;
 | |
| 
 | |
| use BaconQrCode\Common\ErrorCorrectionLevel;
 | |
| use BaconQrCode\Encoder\QrCode;
 | |
| use BaconQrCode\Renderer\Image\Decorator\DecoratorInterface;
 | |
| use BaconQrCode\Renderer\Image\RendererInterface;
 | |
| use BaconQrCode\Renderer\Image\Svg;
 | |
| use Imagick;
 | |
| use InvalidArgumentException;
 | |
| use ReflectionClass;
 | |
| 
 | |
| class ElyDecorator implements DecoratorInterface {
 | |
| 
 | |
|     private const LOGO = __DIR__ . '/resources/logo.svg';
 | |
| 
 | |
|     private const CORRECTION_MAP = [
 | |
|         ErrorCorrectionLevel::L => 7,
 | |
|         ErrorCorrectionLevel::M => 15,
 | |
|         ErrorCorrectionLevel::Q => 25,
 | |
|         ErrorCorrectionLevel::H => 30,
 | |
|     ];
 | |
| 
 | |
|     public function preProcess(
 | |
|         QrCode $qrCode,
 | |
|         RendererInterface $renderer,
 | |
|         $outputWidth,
 | |
|         $outputHeight,
 | |
|         $leftPadding,
 | |
|         $topPadding,
 | |
|         $multiple
 | |
|     ) {
 | |
|         if (!$renderer instanceof Svg) {
 | |
|             throw new InvalidArgumentException('$renderer must by instance of ' . Svg::class);
 | |
|         }
 | |
| 
 | |
|         $correctionLevel = self::CORRECTION_MAP[$qrCode->getErrorCorrectionLevel()->get()];
 | |
|         $sizeMultiplier = $correctionLevel + floor($correctionLevel / 3);
 | |
|         $count = $qrCode->getMatrix()->getWidth();
 | |
| 
 | |
|         $countToRemoveX = floor($count * $sizeMultiplier / 100);
 | |
|         $countToRemoveY = floor($count * $sizeMultiplier / 100);
 | |
| 
 | |
|         $startX = $leftPadding + round(($count - $countToRemoveX) / 2 * $multiple);
 | |
|         $startY = $topPadding + round(($count - $countToRemoveY) / 2 * $multiple);
 | |
|         $width = $countToRemoveX * $multiple;
 | |
|         $height = $countToRemoveY * $multiple;
 | |
| 
 | |
|         $reflection = new ReflectionClass($renderer);
 | |
|         $property = $reflection->getProperty('svg');
 | |
|         $property->setAccessible(true);
 | |
|         /** @var \SimpleXMLElement $svg */
 | |
|         $svg = $property->getValue($renderer);
 | |
| 
 | |
|         $image = $svg->addChild('image');
 | |
|         $image->addAttribute('x', $startX);
 | |
|         $image->addAttribute('y', $startY);
 | |
|         $image->addAttribute('width', $width);
 | |
|         $image->addAttribute('height', $height);
 | |
|         $image->addAttribute('xlink:href', $this->encodeSvgToBase64(self::LOGO));
 | |
| 
 | |
|         $logo = new Imagick();
 | |
|         $logo->readImage(self::LOGO);
 | |
|         $logo->scaleImage($width, $height);
 | |
| 
 | |
|         $foundedPixels = [];
 | |
|         foreach ($logo->getPixelIterator() as $row => $pixels) {
 | |
|             /** @var \ImagickPixel[] $pixels */
 | |
|             foreach ($pixels as $column => $pixel) {
 | |
|                 $color = $pixel->getColorAsString();
 | |
|                 if ($color !== 'srgb(255,255,255)') {
 | |
|                     $foundedPixels[] = [(int)($startX + $column), (int)($startY + $row)];
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         $logo->clear();
 | |
|         $logo->destroy();
 | |
| 
 | |
|         $padding = $multiple - 2;
 | |
|         if ($padding < 0) {
 | |
|             $padding = 1;
 | |
|         }
 | |
| 
 | |
|         foreach ($foundedPixels as $coordinates) {
 | |
|             [$x, $y] = $coordinates;
 | |
|             $x -= $leftPadding;
 | |
|             $y -= $topPadding;
 | |
| 
 | |
|             for ($i = $x - $padding; $i <= $x + $padding; $i++) {
 | |
|                 for ($j = $y - $padding; $j <= $y + $padding; $j++) {
 | |
|                     $matrixX = floor($i / $multiple);
 | |
|                     $matrixY = floor($j / $multiple);
 | |
|                     $qrCode->getMatrix()->set($matrixX, $matrixY, 0);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function postProcess(
 | |
|         QrCode $qrCode,
 | |
|         RendererInterface $renderer,
 | |
|         $outputWidth,
 | |
|         $outputHeight,
 | |
|         $leftPadding,
 | |
|         $topPadding,
 | |
|         $multiple
 | |
|     ) {
 | |
| 
 | |
|     }
 | |
| 
 | |
|     private function encodeSvgToBase64(string $filePath): string {
 | |
|         return 'data:image/svg+xml;base64,' . base64_encode(file_get_contents($filePath));
 | |
|     }
 | |
| 
 | |
| }
 |