imagickImageAsBackground.php 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. <?php
  2. /**
  3. * ImageMagick with image as background example
  4. *
  5. * @created 08.09.2023
  6. * @author smiley <smiley@chillerlan.net>
  7. * @copyright 2023 smiley
  8. * @license MIT
  9. */
  10. use chillerlan\QRCode\Common\EccLevel;
  11. use chillerlan\QRCode\Output\QRImagick;
  12. use chillerlan\QRCode\Output\QROutputInterface;
  13. use chillerlan\QRCode\QRCode;
  14. use chillerlan\QRCode\QRCodeException;
  15. use chillerlan\QRCode\QROptions;
  16. require_once __DIR__.'/../vendor/autoload.php';
  17. class QRImagickImageAsBackground extends QRImagick{
  18. /**
  19. * @inheritDoc
  20. */
  21. protected function getDefaultModuleValue(bool $isDark):ImagickPixel{
  22. // RGBA, adjust opacity to increase contrast
  23. return $this->prepareModuleValue(($isDark) ? '#00000040' : '#ffffffa0');
  24. }
  25. /**
  26. * @inheritDoc
  27. */
  28. protected function createImage():Imagick{
  29. $imagick = new Imagick($this->options->background);
  30. $width = $imagick->getImageWidth();
  31. $height = $imagick->getImageHeight();
  32. // crop the background if necessary
  33. if(($width / $height) !== 1){
  34. $cropsize = ($width > $height) ? $height : $width;
  35. $imagick->cropImage($cropsize, $cropsize, 0, 0);
  36. }
  37. // scale the background to fit the size of the QR Code
  38. if($imagick->getImageWidth() !== $this->length){
  39. $imagick->scaleImage($this->length, $this->length, true);
  40. }
  41. if($this->options->quality > -1){
  42. $imagick->setImageCompressionQuality(max(0, min(100, $this->options->quality)));
  43. }
  44. return $imagick;
  45. }
  46. }
  47. /**
  48. * augment the QROptions class
  49. */
  50. class ImageAsBackgroundOptions extends QROptions{
  51. protected string $background;
  52. /**
  53. * check background image
  54. *
  55. * @throws \chillerlan\QRCode\QRCodeException
  56. */
  57. protected function set_background(string $background):void{
  58. if(!file_exists($background) || !is_file($background) || !is_readable($background)){
  59. throw new QRCodeException('invalid background file');
  60. }
  61. // @todo: check/validate desired image format
  62. $this->background = $background;
  63. }
  64. }
  65. /*
  66. * Runtime
  67. */
  68. $options = new ImageAsBackgroundOptions;
  69. $options->background = __DIR__.'/background.jpg'; // setting from the augmented options
  70. $options->version = 5;
  71. $options->outputType = QROutputInterface::CUSTOM;
  72. $options->outputInterface = QRImagickImageAsBackground::class; // use the custom output class
  73. $options->eccLevel = EccLevel::H;
  74. $options->outputBase64 = false;
  75. $options->scale = 10;
  76. $options->drawLightModules = true;
  77. $options->svgUseFillAttributes = false;
  78. $options->invertMatrix = false;
  79. $options->quietzoneSize = 1;
  80. // dump the output, with an additional logo
  81. $out = (new QRCode($options))->render('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
  82. if(PHP_SAPI !== 'cli'){
  83. header('Content-type: image/png');
  84. echo $out;
  85. }
  86. exit;