Просмотр исходного кода

Merge pull request #5 from joshstoik1/master

Add SVG output support
smiley 9 лет назад
Родитель
Сommit
102ef4fce3
3 измененных файлов с 68 добавлено и 1 удалено
  1. 1 1
      README.md
  2. 66 0
      src/Output/QRImage.php
  3. 1 0
      src/QRCode.php

+ 1 - 1
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!)

+ 66 - 0
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,65 @@ 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 xmlns="http://www.w3.org/2000/svg" version="1.1" width="' . $length . '" height="' . $length . '" viewBox="0 0 ' . $length . ' ' . $length . '" style="background-color:' . $background . '"><defs><style>.' . $class . '{fill:' . $foreground . '} rect{shape-rendering:crispEdges}</style></defs>';
+
+		// 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 '<rect x="' . ($from * $this->options->pixelSize + $this->options->marginSize) . '" y="' . ($r * $this->options->pixelSize + $this->options->marginSize) . '" width="' . ($this->options->pixelSize * $count) . '" height="' . $this->options->pixelSize . '" class="' . $class . '" />';
+
+					// reset count
+					$from = -1;
+					$count = 0;
+				}
+			}
+
+			// close off the row, if applicable
+			if($from >= 0){
+				echo '<rect x="' . ($from * $this->options->pixelSize + $this->options->marginSize) . '" y="' . ($r * $this->options->pixelSize + $this->options->marginSize) . '" width="' . ($this->options->pixelSize * $count) . '" height="' . $this->options->pixelSize . '" class="' . $class . '" />';
+			}
+		}
+
+		// close svg
+		echo '</svg>';
+		$imageData = ob_get_clean();
+
+		// if saving to file, append the correct headers
+		if($this->options->cachefile){
+			if(false === @file_put_contents($this->options->cachefile, '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' . "\n" . $imageData)){
+				throw new QRCodeOutputException('Could not write to cache file.');
+			}
+		}
+
+		if((bool)$this->options->base64){
+			$imageData = 'data:image/svg+xml;base64,'.base64_encode($imageData);
+		}
+
+		return $imageData;
+	}
+
 }

+ 1 - 0
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%.