From 0f0db8d102d29d2a0b55d6618d1e0dcd9ed651a6 Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 16 Dec 2016 21:36:07 -0800 Subject: [PATCH 1/2] Add SVG output support --- README.md | 2 +- src/Output/QRImage.php | 64 ++++++++++++++++++++++++++++++++++++++++++ src/QRCode.php | 1 + 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c9d9a67ec..9db51a419 100644 --- a/README.md +++ b/README.md @@ -218,7 +218,7 @@ property | type | default | allowed | description property | type | default | allowed | description -------- | ---- | ------- | ------- | ----------- -`$type` | string | PNG | QRCode::OUTPUT_IMAGE_XXX | XXX = PNG, JPG, GIF +`$type` | string | PNG | QRCode::OUTPUT_IMAGE_XXX | XXX = PNG, JPG, GIF, SVG `$base64` | bool | true | - | wether to return the image data as base64 or raw like from `file_get_contents()` `$cachefile` | string | null | * | optional cache file path, null returns the image data `$pixelSize` | int | 5 | 1 ... 25 | size of a QR code pixel (25 is HUGE!) diff --git a/src/Output/QRImage.php b/src/Output/QRImage.php index 61ebec1ec..7a5d1cdae 100644 --- a/src/Output/QRImage.php +++ b/src/Output/QRImage.php @@ -48,6 +48,11 @@ class QRImage extends QROutputAbstract{ * @return string */ public function dump(){ + // svg doesn't need all this GD business + if($this->options->type === QRCode::OUTPUT_IMAGE_SVG){ + return $this->toSVG(); + } + $length = $this->pixelCount * $this->options->pixelSize + $this->options->marginSize * 2; $image = imagecreatetruecolor($length, $length); $foreground = imagecolorallocate($image, $this->options->fgRed, $this->options->fgGreen, $this->options->fgBlue); @@ -112,4 +117,63 @@ class QRImage extends QROutputAbstract{ return $imageData; } + /** + * @return string + */ + protected function toSVG(){ + $length = $this->pixelCount * $this->options->pixelSize + $this->options->marginSize * 2; + $class = 'f' . hash('crc32', microtime(true)); + $foreground = 'rgb(' . $this->options->fgRed . ',' . $this->options->fgGreen . ',' . $this->options->fgBlue . ')'; + $background = (bool)$this->options->transparent + ? 'transparent' + : 'rgb(' . $this->options->bgRed . ',' . $this->options->bgGreen . ',' . $this->options->bgBlue . ')'; + + ob_start(); + + // svg header + echo ''; + + // svg body + foreach($this->matrix AS $r=>$row){ + //we'll combine active blocks within a single row as a lightweight compression technique + $from = -1; + $count = 0; + + foreach($row AS $c=>$pixel){ + if($pixel){ + $count++; + if($from < 0) + $from = $c; + } + else if($from >= 0){ + echo ''; + + // reset count + $from = -1; + $count = 0; + } + } + + // close off the row, if applicable + if($from >= 0){ + echo ''; + } + } + + // close svg + echo ''; + $imageData = ob_get_clean(); + + // if saving to file, append the correct headers + if($this->options->cachefile){ + @file_put_contents($this->options->cachefile, '' . "\n" . $imageData); + } + + if((bool)$this->options->base64){ + $imageData = 'data:image/svg+xml;base64,'.base64_encode($imageData); + } + + return $imageData; + } + } diff --git a/src/QRCode.php b/src/QRCode.php index 0e5255e6c..8ca3cfb69 100644 --- a/src/QRCode.php +++ b/src/QRCode.php @@ -34,6 +34,7 @@ class QRCode{ const OUTPUT_IMAGE_PNG = 'png'; const OUTPUT_IMAGE_JPG = 'jpg'; const OUTPUT_IMAGE_GIF = 'gif'; + const OUTPUT_IMAGE_SVG = 'svg'; const ERROR_CORRECT_LEVEL_L = 1; // 7%. const ERROR_CORRECT_LEVEL_M = 0; // 15%. From f55859ceba856e3890e1e2775b68d1d60e6c258d Mon Sep 17 00:00:00 2001 From: Josh Date: Fri, 16 Dec 2016 22:18:14 -0800 Subject: [PATCH 2/2] Throw Exception on cachefile write error --- src/Output/QRImage.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Output/QRImage.php b/src/Output/QRImage.php index 7a5d1cdae..0691d124e 100644 --- a/src/Output/QRImage.php +++ b/src/Output/QRImage.php @@ -166,7 +166,9 @@ class QRImage extends QROutputAbstract{ // if saving to file, append the correct headers if($this->options->cachefile){ - @file_put_contents($this->options->cachefile, '' . "\n" . $imageData); + if(false === @file_put_contents($this->options->cachefile, '' . "\n" . $imageData)){ + throw new QRCodeOutputException('Could not write to cache file.'); + } } if((bool)$this->options->base64){