smiley 8 tahun lalu
induk
melakukan
88f800c50b

+ 0 - 27
examples/authenticator.php

@@ -1,27 +0,0 @@
-<?php
-/**
- *
- * @filesource   authenticator.php
- * @created      10.11.2017
- * @author       Smiley <smiley@chillerlan.net>
- * @copyright    2017 Smiley
- * @license      MIT
- */
-
-require_once '../vendor/autoload.php';
-
-use chillerlan\{
-	GoogleAuth\Authenticator,
-	QRCode\QRCode,
-	QRCode\Output\QRMarkup
-};
-
-$authenticator = new Authenticator;
-
-$secret = $authenticator->createSecret(); // -> userdata
-$data   = $authenticator->getUri($secret, 'label', 'example.com');
-
-// markup - svg
-echo '<!DOCTYPE html><html><head><meta charset="UTF-8"/></head><body><div>'.(new QRCode($data, new QRMarkup))->output().'</div></body>';
-
-

+ 0 - 37
examples/custom.php

@@ -1,37 +0,0 @@
-<?php
-
-require_once '../vendor/autoload.php';
-
-use chillerlan\QRCode\QRCode;
-use chillerlan\QRCode\Output\QROutputAbstract;
-
-
-/**
- * Class MyCustomOutput
- */
-class MyCustomOutput extends QROutputAbstract{
-
-	/**
-	 * @return mixed
-	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
-	 */
-	public function dump(){
-
-		$output = '';
-
-		for($row = 0; $row < $this->pixelCount; $row++){
-			for($col = 0; $col < $this->pixelCount; $col++){
-				$output .= (string)(int)$this->matrix[$row][$col];
-			}
-		}
-
-		return $output;
-	}
-
-}
-
-$starttime = microtime(true);
-
-echo (new QRCode('otpauth://totp/test?secret=B3JX4VCVJDVNXNZ5&issuer=chillerlan.net', new MyCustomOutput))->output();
-
-echo PHP_EOL.'QRCode: '.round((microtime(true)-$starttime), 5);

+ 0 - 88
examples/example.php

@@ -1,88 +0,0 @@
-<?php
-/**
- * @filesource   example.php
- * @created      10.12.2015
- * @author       Smiley <smiley@chillerlan.net>
- * @copyright    2015 Smiley
- * @license      MIT
- */
-
-require_once '../vendor/autoload.php';
-
-use chillerlan\QRCode\Output\{
-	QRMarkup, QRMarkupOptions, QRImage, QRString, QRStringOptions
-};
-use chillerlan\QRCode\QRCode;
-
-$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
-
-?>
-<!DOCTYPE html>
-<html lang="en">
-<head>
-	<meta charset="UTF-8"/>
-	<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
-	<title>QRCode test</title>
-	<style>
-		body{
-			margin: 0;
-			padding: 0;
-		}
-
-		div.qrcode{
-			margin: 0 5px;
-		}
-
-		/* row element */
-		div.qrcode > p {
-			margin: 0;
-			padding: 0;
-			height: 5px;
-		}
-
-		/* column element(s) */
-		div.qrcode > p > b,
-		div.qrcode > p > i {
-			display: inline-block;
-			width: 5px;
-			height: 5px;
-		}
-
-		div.qrcode > p > b {
-			background-color: #000;
-		}
-
-		div.qrcode > p > i {
-			background-color: #fff;
-		}
-	</style>
-</head>
-<body>
-<?php
-
-// image
-echo '<img alt="qrcode" src="'.(new QRCode($data, new QRImage))->output().'" />';
-
-// markup - svg
-echo '<div>'.(new QRCode($data, new QRMarkup))->output().'</div>';
-
-// markup - html
-$outputOptions = new QRMarkupOptions;
-$outputOptions->type = QRCode::OUTPUT_MARKUP_HTML;
-
-echo '<div class="qrcode">'.(new QRCode($data, new QRMarkup($outputOptions)))->output().'</div>';
-
-// string - json
-echo '<pre>'.(new QRCode($data, new QRString))->output().'<pre>';
-
-// string - text
-$outputOptions = new QRStringOptions;
-$outputOptions->type = QRCode::OUTPUT_STRING_TEXT;
-$outputOptions->textDark = '🔴';
-$outputOptions->textLight = '⭕';
-
-echo '<pre>'.(new QRCode($data, new QRString($outputOptions)))->output().'</pre>';
-
-?>
-</body>
-</html>

TEMPAT SAMPAH
examples/example_image.png


+ 0 - 54
examples/html.php

@@ -1,54 +0,0 @@
-<?php
-
-require_once '../vendor/autoload.php';
-
-use chillerlan\QRCode\Output\QRMarkup;
-use chillerlan\QRCode\Output\QRMarkupOptions;
-use chillerlan\QRCode\QRCode;
-use chillerlan\QRCode\QROptions;
-
-//---------------------------------------------------------
-
-echo '<style>
-
-.qrcode,
-.qrcode > p,
-.qrcode > p > b,
-.qrcode > p > i {
-	margin:0;
-	padding:0;
-}
-
-/* row element */
-.qrcode > p {
-	height: 1.25mm;
-	display: block;
-}
-
-/* column element(s) */
-.qrcode > p > b, .qrcode > p > i{
-	display: inline-block;
-	width: 1.25mm;
-	height: 1.25mm;
-}
-
-.qrcode > p > b{
-	background-color: #000;
-}
-
-.qrcode > p > i{
-	background-color: #fff;
-}
-
-</style>';
-
-$qrStringOptions = new QRMarkupOptions;
-$qrStringOptions->type = QRCode::OUTPUT_MARKUP_HTML;
-
-$qrOptions = new QROptions;
-$qrOptions->typeNumber = QRCode::TYPE_05;
-$qrOptions->errorCorrectLevel = QRCode::ERROR_CORRECT_LEVEL_L;
-
-$qr = new QRCode('skype://callto:echo123', new QRMarkup($qrStringOptions), $qrOptions);
-
-echo '<div class="qrcode">'.$qr->output().'</div>';

+ 0 - 15
examples/image.php

@@ -1,15 +0,0 @@
-<?php
-
-require_once '../vendor/autoload.php';
-
-use chillerlan\QRCode\Output\QRImage;
-use chillerlan\QRCode\Output\QRImageOptions;
-use chillerlan\QRCode\QRCode;
-
-$qrImageOptions = new QRImageOptions;
-$qrImageOptions->pixelSize = 10;
-$qrImageOptions->cachefile = 'example_image.png';
-
-(new QRCode('https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s', new QRImage($qrImageOptions)))->output();
-
-echo '<img src="'.$qrImageOptions->cachefile.'" />';

+ 18 - 19
public/index.html

@@ -10,10 +10,9 @@
 		input:focus, textarea:focus, select:focus{ border: 1px solid #ccc; }
 		input:focus, textarea:focus, select:focus{ border: 1px solid #ccc; }
 		label{ cursor: pointer; }
 		label{ cursor: pointer; }
 		#qrcode-settings, div#qrcode-output{ text-align: center; }
 		#qrcode-settings, div#qrcode-output{ text-align: center; }
-		div#qrcode-output > p {margin: 0;padding: 0;height: 3px;}
-		div#qrcode-output > p > b, div#qrcode-output > p > i {display: inline-block;width: 3px;height: 3px;}
-		div#qrcode-output > p > b {background-color: lightseagreen;}
-		div#qrcode-output > p > i {background-color: #fff;}
+		div#qrcode-output > div {margin: 0;padding: 0;height: 3px;}
+		div#qrcode-output > div > span {display: inline-block;width: 3px;height: 3px;}
+		div#qrcode-output > div > span {background-color: lightgrey;}
 	</style >
 	</style >
 </head >
 </head >
 <body >
 <body >
@@ -63,50 +62,50 @@
 
 
 	<div>Finder</div>
 	<div>Finder</div>
 	<label for="m_finder_light" >
 	<label for="m_finder_light" >
-		<input type="text" readonly="readonly" id="m_finder_light" name="m_finder_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_finder_light" name="m_finder_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_finder_dark" >
 	<label for="m_finder_dark" >
-		<input type="text" readonly="readonly" id="m_finder_dark" name="m_finder_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_finder_dark" name="m_finder_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Alignment</div>
 	<div>Alignment</div>
 	<label for="m_alignment_light" >
 	<label for="m_alignment_light" >
-		<input type="text" readonly="readonly" id="m_alignment_light" name="m_alignment_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_alignment_light" name="m_alignment_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_alignment_dark" >
 	<label for="m_alignment_dark" >
-		<input type="text" readonly="readonly" id="m_alignment_dark" name="m_alignment_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_alignment_dark" name="m_alignment_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Timing</div>
 	<div>Timing</div>
 	<label for="m_timing_light" >
 	<label for="m_timing_light" >
-		<input type="text" readonly="readonly" id="m_timing_light" name="m_timing_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_timing_light" name="m_timing_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_timing_dark" >
 	<label for="m_timing_dark" >
-		<input type="text" readonly="readonly" id="m_timing_dark" name="m_timing_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_timing_dark" name="m_timing_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Format</div>
 	<div>Format</div>
 	<label for="m_format_light" >
 	<label for="m_format_light" >
-		<input type="text" readonly="readonly" id="m_format_light" name="m_format_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_format_light" name="m_format_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_format_dark" >
 	<label for="m_format_dark" >
-		<input type="text" readonly="readonly" id="m_format_dark" name="m_format_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_format_dark" name="m_format_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Version</div>
 	<div>Version</div>
 	<label for="m_version_light" >
 	<label for="m_version_light" >
-		<input type="text" readonly="readonly" id="m_version_light" name="m_version_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_version_light" name="m_version_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_version_dark" >
 	<label for="m_version_dark" >
-		<input type="text" readonly="readonly" id="m_version_dark" name="m_version_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_version_dark" name="m_version_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Data</div>
 	<div>Data</div>
 	<label for="m_data_light" >
 	<label for="m_data_light" >
-		<input type="text" readonly="readonly" id="m_data_light" name="m_data_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_data_light" name="m_data_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_data_dark" >
 	<label for="m_data_dark" >
-		<input type="text" readonly="readonly" id="m_data_dark" name="m_data_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_data_dark" name="m_data_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Dark Module</div>
 	<div>Dark Module</div>
@@ -114,12 +113,12 @@
 		<input disabled="disabled" type="text" id="m_darkmodule_light" class="options" value="" autocomplete="off" spellcheck="false" />
 		<input disabled="disabled" type="text" id="m_darkmodule_light" class="options" value="" autocomplete="off" spellcheck="false" />
 	</label >
 	</label >
 	<label for="m_darkmodule_dark" >
 	<label for="m_darkmodule_dark" >
-		<input type="text" readonly="readonly" id="m_darkmodule_dark" name="m_darkmodule_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_darkmodule_dark" name="m_darkmodule_dark" class="jscolor options" value="000000" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 
 
 	<div>Separator</div>
 	<div>Separator</div>
 	<label for="m_separator_light" >
 	<label for="m_separator_light" >
-		<input type="text" readonly="readonly" id="m_separator_light" name="m_separator_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_separator_light" name="m_separator_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_separator_dark" >
 	<label for="m_separator_dark" >
 		<input disabled="disabled" type="text" id="m_separator_dark" class="options" value="" autocomplete="off" spellcheck="false" />
 		<input disabled="disabled" type="text" id="m_separator_dark" class="options" value="" autocomplete="off" spellcheck="false" />
@@ -127,7 +126,7 @@
 
 
 	<div>Quiet Zone</div>
 	<div>Quiet Zone</div>
 	<label for="m_quietzone_light" >
 	<label for="m_quietzone_light" >
-		<input type="text" readonly="readonly" id="m_quietzone_light" name="m_quietzone_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" />
+		<input type="text" id="m_quietzone_light" name="m_quietzone_light" class="jscolor options" value="ffffff" autocomplete="off" spellcheck="false" minlength="6" maxlength="6" />
 	</label >
 	</label >
 	<label for="m_quietzone_dark" >
 	<label for="m_quietzone_dark" >
 		<input disabled="disabled" type="text" id="m_quietzone_dark" class="options" value="" autocomplete="off" spellcheck="false" />
 		<input disabled="disabled" type="text" id="m_quietzone_dark" class="options" value="" autocomplete="off" spellcheck="false" />

+ 23 - 16
public/qrcode.php

@@ -44,16 +44,12 @@ try{
 	];
 	];
 
 
 	$moduleValues = array_map(function($v){
 	$moduleValues = array_map(function($v){
-		#var_dump(array_map('hexdec', unpack('a2r/a2g/a2b','ff00ff')));
-
 		if(preg_match('/[a-f\d]{6}/i', $v) === 1){
 		if(preg_match('/[a-f\d]{6}/i', $v) === 1){
-			return '#'.$v;
+			return in_array($_POST['output_type'], ['png', 'jpg', 'gif'])
+				? array_map('hexdec', str_split($v, 2))
+				: '#'.$v ;
 		}
 		}
-
-		return strpos($v, '_dark') !== false
-			? '#111111'
-			: '#eeeeee';
-
+		return null;
 	}, $moduleValues);
 	}, $moduleValues);
 
 
 
 
@@ -61,17 +57,28 @@ try{
 
 
 	$qro = new QROptions;
 	$qro = new QROptions;
 
 
-	$qro->version       = (int)$_POST['version'];
-	$qro->eccLevel      = constant('chillerlan\\QRCode\\QRCode::ECC_'.$ecc);
-	$qro->moduleValues  = $moduleValues;
-	$qro->outputType    = $_POST['output_type'];
-	$qro->maskPattern   = (int)$_POST['maskpattern'];
-	$qro->addQuietzone  = isset($_POST['quietzone']);
-	$qro->quietzoneSize = (int)$_POST['quietzonesize'];
-	$qro->scale         = (int)$_POST['scale'];
+	$qro->version          = (int)$_POST['version'];
+	$qro->eccLevel         = constant('chillerlan\\QRCode\\QRCode::ECC_'.$ecc);
+	$qro->maskPattern      = (int)$_POST['maskpattern'];
+	$qro->addQuietzone     = isset($_POST['quietzone']);
+	$qro->quietzoneSize    = (int)$_POST['quietzonesize'];
+	$qro->moduleValues     = $moduleValues;
+	$qro->outputType       = $_POST['output_type'];
+	$qro->scale            = (int)$_POST['scale'];
+	$qro->imageTransparent = false;
 
 
 	$qrcode = (new QRCode($qro))->render($_POST['inputstring']);
 	$qrcode = (new QRCode($qro))->render($_POST['inputstring']);
 
 
+	if(in_array($_POST['output_type'], ['png', 'jpg', 'gif'])){
+		$qrcode = '<img src="'.$qrcode.'" />';
+	}
+	elseif($_POST['output_type'] === 'text'){
+		$qrcode = '<pre style="font-size: 75%; line-height: 1;">'.$qrcode.'</pre>';
+	}
+	elseif($_POST['output_type'] === 'json'){
+		$qrcode = '<pre style="font-size: 75%; overflow-x: auto;">'.$qrcode.'</pre>';
+	}
+
 	send_response(['qrcode' => $qrcode]);
 	send_response(['qrcode' => $qrcode]);
 }
 }
 // Pokémon exception handler
 // Pokémon exception handler

+ 2 - 2
src/Data/AlphaNum.php

@@ -29,12 +29,12 @@ class AlphaNum extends QRDataAbstract{
 	];
 	];
 
 
 	/**
 	/**
-	 * @var int
+	 * @inheritdoc
 	 */
 	 */
 	protected $datamode = QRCode::DATA_ALPHANUM;
 	protected $datamode = QRCode::DATA_ALPHANUM;
 
 
 	/**
 	/**
-	 * @var array
+	 * @inheritdoc
 	 */
 	 */
 	protected $lengthBits = [9, 11, 13];
 	protected $lengthBits = [9, 11, 13];
 
 

+ 2 - 2
src/Data/Byte.php

@@ -20,12 +20,12 @@ use chillerlan\QRCode\QRCode;
 class Byte extends QRDataAbstract{
 class Byte extends QRDataAbstract{
 
 
 	/**
 	/**
-	 * @var int
+	 * @inheritdoc
 	 */
 	 */
 	protected $datamode = QRCode::DATA_BYTE;
 	protected $datamode = QRCode::DATA_BYTE;
 
 
 	/**
 	/**
-	 * @var array
+	 * @inheritdoc
 	 */
 	 */
 	protected $lengthBits = [8, 16, 16];
 	protected $lengthBits = [8, 16, 16];
 
 

+ 2 - 2
src/Data/Kanji.php

@@ -20,12 +20,12 @@ use chillerlan\QRCode\QRCode;
 class Kanji extends QRDataAbstract{
 class Kanji extends QRDataAbstract{
 
 
 	/**
 	/**
-	 * @var int
+	 * @inheritdoc
 	 */
 	 */
 	protected $datamode = QRCode::DATA_KANJI;
 	protected $datamode = QRCode::DATA_KANJI;
 
 
 	/**
 	/**
-	 * @var array
+	 * @inheritdoc
 	 */
 	 */
 	protected $lengthBits = [8, 10, 12];
 	protected $lengthBits = [8, 10, 12];
 
 

+ 35 - 32
src/Data/MaskPatternTester.php

@@ -13,6 +13,8 @@
 namespace chillerlan\QRCode\Data;
 namespace chillerlan\QRCode\Data;
 
 
 /**
 /**
+ * The sole purpose of this class is to receive a QRMatrix object and run the pattern tests on it.
+ *
  * @link http://www.thonky.com/qr-code-tutorial/data-masking
  * @link http://www.thonky.com/qr-code-tutorial/data-masking
  */
  */
 class MaskPatternTester{
 class MaskPatternTester{
@@ -28,16 +30,24 @@ class MaskPatternTester{
 	protected $moduleCount;
 	protected $moduleCount;
 
 
 	/**
 	/**
+	 * Receives the matrix an sets the module count
+	 *
+	 * @see \chillerlan\QRCode\QROptions::$maskPattern
+	 * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
+	 * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
+	 *
 	 * @param \chillerlan\QRCode\Data\QRMatrix $matrix
 	 * @param \chillerlan\QRCode\Data\QRMatrix $matrix
 	 */
 	 */
 	public function setMatrix(QRMatrix $matrix){
 	public function setMatrix(QRMatrix $matrix){
-		$this->matrix = $matrix;
+		$this->matrix      = $matrix;
 		$this->moduleCount = $this->matrix->size();
 		$this->moduleCount = $this->matrix->size();
 	}
 	}
 
 
 	/**
 	/**
 	 * Returns the penalty for the given mask pattern
 	 * Returns the penalty for the given mask pattern
 	 *
 	 *
+	 * @see \chillerlan\QRCode\QROptions::$maskPattern
+	 * @see \chillerlan\QRCode\Data\QRMatrix::$maskPattern
 	 * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
 	 * @see \chillerlan\QRCode\QRCode::getBestMaskPattern()
 	 *
 	 *
 	 * @return float
 	 * @return float
@@ -152,38 +162,32 @@ class MaskPatternTester{
 		foreach($this->matrix->matrix() as $y => $row){
 		foreach($this->matrix->matrix() as $y => $row){
 			foreach($row as $x => $val){
 			foreach($row as $x => $val){
 
 
-				if($x > $this->moduleCount - 7){
-					break;
-				}
-
-				if(
-					$val >> 8 > 0
-					&& !$this->matrix->check($x + 1, $y)
-					&&  $this->matrix->check($x + 2, $y)
-					&&  $this->matrix->check($x + 3, $y)
-					&&  $this->matrix->check($x + 4, $y)
-					&& !$this->matrix->check($x + 5, $y)
-					&&  $this->matrix->check($x + 6, $y)
-				){
-					$penalty += 40;
+				if($x <= $this->moduleCount - 7){
+					if(
+						    $this->matrix->check($x    , $y)
+						&& !$this->matrix->check($x + 1, $y)
+						&&  $this->matrix->check($x + 2, $y)
+						&&  $this->matrix->check($x + 3, $y)
+						&&  $this->matrix->check($x + 4, $y)
+						&& !$this->matrix->check($x + 5, $y)
+						&&  $this->matrix->check($x + 6, $y)
+					){
+						$penalty += 40;
+					}
 				}
 				}
 
 
-			}
-		}
-
-		for ($x = 0; $x < $this->moduleCount; $x++) {
-			for ($y = 0; $y < $this->moduleCount - 6; $y++) {
-
-				if(
-					$this->matrix->check($x, $y    )
-					&& !$this->matrix->check($x, $y + 1)
-					&&  $this->matrix->check($x, $y + 2)
-					&&  $this->matrix->check($x, $y + 3)
-					&&  $this->matrix->check($x, $y + 4)
-					&& !$this->matrix->check($x, $y + 5)
-					&&  $this->matrix->check($x, $y + 6)
-				){
-					$penalty += 40;
+				if($y <= $this->moduleCount - 7){
+					if(
+						    $this->matrix->check($x, $y)
+						&& !$this->matrix->check($x, $y + 1)
+						&&  $this->matrix->check($x, $y + 2)
+						&&  $this->matrix->check($x, $y + 3)
+						&&  $this->matrix->check($x, $y + 4)
+						&& !$this->matrix->check($x, $y + 5)
+						&&  $this->matrix->check($x, $y + 6)
+					){
+						$penalty += 40;
+					}
 				}
 				}
 
 
 			}
 			}
@@ -211,5 +215,4 @@ class MaskPatternTester{
 		return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
 		return (abs(100 * $count / $this->moduleCount / $this->moduleCount - 50) / 5) * 10;
 	}
 	}
 
 
-
 }
 }

+ 2 - 2
src/Data/Number.php

@@ -20,12 +20,12 @@ use chillerlan\QRCode\QRCode;
 class Number extends QRDataAbstract{
 class Number extends QRDataAbstract{
 
 
 	/**
 	/**
-	 * @var int
+	 * @inheritdoc
 	 */
 	 */
 	protected $datamode = QRCode::DATA_NUMBER;
 	protected $datamode = QRCode::DATA_NUMBER;
 
 
 	/**
 	/**
-	 * @var array
+	 * @inheritdoc
 	 */
 	 */
 	protected $lengthBits = [10, 12, 14];
 	protected $lengthBits = [10, 12, 14];
 
 

+ 37 - 11
src/Data/QRDataAbstract.php

@@ -21,45 +21,59 @@ use chillerlan\QRCode\Helpers\{
 use chillerlan\Traits\ClassLoader;
 use chillerlan\Traits\ClassLoader;
 
 
 /**
 /**
- *
+ * Processes the binary data and maps it on a matrix which is then being returned
  */
  */
 abstract class QRDataAbstract implements QRDataInterface{
 abstract class QRDataAbstract implements QRDataInterface{
 	use ClassLoader;
 	use ClassLoader;
 
 
 	/**
 	/**
+	 * the string byte count
+	 *
 	 * @var int
 	 * @var int
 	 */
 	 */
 	protected $strlen;
 	protected $strlen;
 
 
 	/**
 	/**
+	 * the current data mode: Num, Alphanum, Kanji, Byte
+	 *
 	 * @var int
 	 * @var int
 	 */
 	 */
 	protected $datamode;
 	protected $datamode;
 
 
 	/**
 	/**
+	 * mode length bits for the version breakpoints 1-9, 10-26 and 27-40
+	 *
 	 * @var array
 	 * @var array
 	 */
 	 */
 	protected $lengthBits = [0, 0, 0];
 	protected $lengthBits = [0, 0, 0];
 
 
 	/**
 	/**
+	 * current QR Code version
+	 *
 	 * @var int
 	 * @var int
 	 */
 	 */
 	protected $version;
 	protected $version;
 
 
 	/**
 	/**
+	 * the raw data that's being passed to QRMatrix::mapData()
+	 *
 	 * @var array
 	 * @var array
 	 */
 	 */
-	protected $ecdata;
+	protected $matrixdata;
 
 
 	/**
 	/**
+	 * ECC temp data
+	 *
 	 * @var array
 	 * @var array
 	 */
 	 */
-	protected $dcdata;
+	protected $ecdata;
 
 
 	/**
 	/**
+	 * ECC temp data
+	 *
 	 * @var array
 	 * @var array
 	 */
 	 */
-	protected $matrixdata;
+	protected $dcdata;
 
 
 	/**
 	/**
 	 * @var \chillerlan\QRCode\QROptions
 	 * @var \chillerlan\QRCode\QROptions
@@ -86,6 +100,8 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
+	 * Sets the data string (internally called by the constructor)
+	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Data\QRDataInterface
 	 * @return \chillerlan\QRCode\Data\QRDataInterface
@@ -110,6 +126,8 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
+	 * returns a fresh matrix object with the data written for the given $maskPattern
+	 *
 	 * @param int  $maskPattern
 	 * @param int  $maskPattern
 	 * @param bool $test
 	 * @param bool $test
 	 *
 	 *
@@ -132,25 +150,25 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
-	 * @param int $version
+	 * returns the length bits for the version breakpoints 1-9, 10-26 and 27-40
 	 *
 	 *
 	 * @return int
 	 * @return int
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 * @codeCoverageIgnore
 	 * @codeCoverageIgnore
 	 */
 	 */
-	protected function getLengthBits(int $version):int {
+	protected function getLengthBits():int {
 
 
 		 foreach([9, 26, 40] as $key => $breakpoint){
 		 foreach([9, 26, 40] as $key => $breakpoint){
-			 if($version <= $breakpoint){
+			 if($this->version <= $breakpoint){
 				 return $this->lengthBits[$key];
 				 return $this->lengthBits[$key];
 			 }
 			 }
 		 }
 		 }
 
 
-		throw new QRCodeDataException('invalid version number: '.$version);
+		throw new QRCodeDataException('invalid version number: '.$this->version);
 	}
 	}
 
 
 	/**
 	/**
-	 * returns the byte count of the string
+	 * returns the byte count of the $data string
 	 *
 	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
@@ -161,6 +179,8 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
+	 * returns the minimum version number for the given string
+	 *
 	 * @return int
 	 * @return int
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 */
 	 */
@@ -179,7 +199,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
-	 * writes the $data bits to $this->bitBuffer
+	 * @see \chillerlan\QRCode\Data\QRDataAbstract::writeBitBuffer()
 	 *
 	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
@@ -188,6 +208,8 @@ abstract class QRDataAbstract implements QRDataInterface{
 	abstract protected function write(string $data);
 	abstract protected function write(string $data);
 
 
 	/**
 	/**
+	 * writes the string data to the BitBuffer
+	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Data\QRDataAbstract
 	 * @return \chillerlan\QRCode\Data\QRDataAbstract
@@ -202,7 +224,7 @@ abstract class QRDataAbstract implements QRDataInterface{
 		$this->bitBuffer
 		$this->bitBuffer
 			->clear()
 			->clear()
 			->put($this->datamode, 4)
 			->put($this->datamode, 4)
-			->put($this->strlen, $this->getLengthBits($this->version))
+			->put($this->strlen, $this->getLengthBits())
 		;
 		;
 
 
 		$this->write($data);
 		$this->write($data);
@@ -241,6 +263,10 @@ abstract class QRDataAbstract implements QRDataInterface{
 	}
 	}
 
 
 	/**
 	/**
+	 * ECC masking
+	 *
+	 * @see \chillerlan\QRCode\Data\QRDataAbstract::writeBitBuffer()
+	 *
 	 * @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
 	 * @link http://www.thonky.com/qr-code-tutorial/error-correction-coding
 	 *
 	 *
 	 * @return array
 	 * @return array

+ 0 - 2
src/Data/QRMatrix.php

@@ -146,8 +146,6 @@ class QRMatrix{
 	}
 	}
 
 
 	/**
 	/**
-	 * Returns the data array
-	 *
 	 * @return array
 	 * @return array
 	 */
 	 */
 	public function matrix():array {
 	public function matrix():array {

+ 20 - 19
src/Output/QRImage.php

@@ -15,44 +15,37 @@ namespace chillerlan\QRCode\Output;
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\QRCode;
 
 
 /**
 /**
- *
+ * Converts the matrix into images, raw or base64 output
  */
  */
 class QRImage extends QROutputAbstract{
 class QRImage extends QROutputAbstract{
 
 
 	/**
 	/**
-	 * @todo
 	 * @return string
 	 * @return string
 	 */
 	 */
-	public function dump():string {
-		$length     = ($this->moduleCount + ($this->options->addQuietzone ? 8 : 0)) * $this->options->scale;
+	public function dump():string{
+		$scale      = $this->options->scale;
+		$length     = $this->moduleCount * $scale;
 		$image      = imagecreatetruecolor($length, $length);
 		$image      = imagecreatetruecolor($length, $length);
-		$background = imagecolorallocate($image, 255, 255, 255);
+		$background = imagecolorallocate($image, ...$this->options->imageTransparencyBG);
 
 
-		if((bool)$this->options->imageTransparent && $this->options->outputType !== QRCode::OUTPUT_IMAGE_JPG){
+		if((bool)$this->options->imageTransparent && in_array($this->options->outputType, [QRCode::OUTPUT_IMAGE_PNG, QRCode::OUTPUT_IMAGE_GIF,], true)){
 			imagecolortransparent($image, $background);
 			imagecolortransparent($image, $background);
 		}
 		}
 
 
 		imagefilledrectangle($image, 0, 0, $length, $length, $background);
 		imagefilledrectangle($image, 0, 0, $length, $length, $background);
 
 
-		foreach($this->matrix->matrix() as $r => $row){
-			foreach($row as $c => $pixel){
-				list($red, $green, $blue) = $this->options->moduleValues[$pixel];
-
-				imagefilledrectangle(
-					$image,
-					 $c      * $this->options->scale,
-					 $r      * $this->options->scale,
-					($c + 1) * $this->options->scale - 1,
-					($r + 1) * $this->options->scale - 1,
-					imagecolorallocate($image, $red, $green, $blue)
-				);
+		foreach($this->matrix->matrix() as $y => $row){
+			foreach($row as $x => $pixel){
+				$color = imagecolorallocate($image, ...$this->options->moduleValues[$pixel]);
 
 
+				imagefilledrectangle($image, $x * $scale, $y * $scale, ($x + 1) * $scale - 1, ($y + 1) * $scale - 1, $color);
 			}
 			}
 		}
 		}
 
 
 		ob_start();
 		ob_start();
 
 
-		$this->{$this->options->outputType ?? 'png'}($image);
+		call_user_func_array([$this, $this->options->outputType ?? QRCode::OUTPUT_IMAGE_PNG], [&$image]);
+
 		$imageData = ob_get_contents();
 		$imageData = ob_get_contents();
 		imagedestroy($image);
 		imagedestroy($image);
 
 
@@ -65,6 +58,9 @@ class QRImage extends QROutputAbstract{
 		return $imageData;
 		return $imageData;
 	}
 	}
 
 
+	/**
+	 * @param $image
+	 */
 	protected function png(&$image){
 	protected function png(&$image){
 		imagepng(
 		imagepng(
 			$image,
 			$image,
@@ -78,11 +74,16 @@ class QRImage extends QROutputAbstract{
 
 
 	/**
 	/**
 	 * Jiff - like... JitHub!
 	 * Jiff - like... JitHub!
+	 *
+	 * @param $image
 	 */
 	 */
 	protected function gif(&$image){
 	protected function gif(&$image){
 		imagegif($image, $this->options->cachefile);
 		imagegif($image, $this->options->cachefile);
 	}
 	}
 
 
+	/**
+	 * @param $image
+	 */
 	protected function jpg(&$image){
 	protected function jpg(&$image){
 		imagejpeg(
 		imagejpeg(
 			$image,
 			$image,

+ 8 - 7
src/Output/QRMarkup.php

@@ -15,19 +15,20 @@ namespace chillerlan\QRCode\Output;
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\QRCode;
 
 
 /**
 /**
- *
+ * Converts the matrix into markup types: HTML, SVG, ...
  */
  */
 class QRMarkup extends QROutputAbstract{
 class QRMarkup extends QROutputAbstract{
 
 
 	/**
 	/**
 	 * @return string
 	 * @return string
 	 */
 	 */
-	public function dump() {
+	public function dump(){
 		switch($this->options->outputType){
 		switch($this->options->outputType){
-			case QRCode::OUTPUT_MARKUP_SVG : return $this->toSVG();
 			case QRCode::OUTPUT_MARKUP_HTML:
 			case QRCode::OUTPUT_MARKUP_HTML:
-			default:
 				return $this->toHTML();
 				return $this->toHTML();
+			case QRCode::OUTPUT_MARKUP_SVG :
+			default:
+				return $this->toSVG();
 		}
 		}
 	}
 	}
 
 
@@ -38,13 +39,13 @@ class QRMarkup extends QROutputAbstract{
 		$html = '';
 		$html = '';
 
 
 		foreach($this->matrix->matrix() as $row){
 		foreach($this->matrix->matrix() as $row){
-			$html .= '<'.$this->options->htmlRowTag.'>';
+			$html .= '<div>';
 
 
 			foreach($row as $pixel){
 			foreach($row as $pixel){
-				$html .= '<b style="background: '.($this->options->moduleValues[$pixel] ?? 'lightgrey').';"></b>';
+				$html .= '<span style="background: '.($this->options->moduleValues[$pixel] ?? 'lightgrey').';"></span>';
 			}
 			}
 
 
-			$html .= (bool)$this->options->htmlOmitEndTag ? '</'.$this->options->htmlRowTag.'>' : '';
+			$html .= '</div>';
 			$html .= $this->options->eol;
 			$html .= $this->options->eol;
 		}
 		}
 
 

+ 9 - 7
src/Output/QROutputAbstract.php

@@ -22,23 +22,25 @@ use chillerlan\QRCode\{
 abstract class QROutputAbstract implements QROutputInterface{
 abstract class QROutputAbstract implements QROutputInterface{
 
 
 	/**
 	/**
-	 * @param \chillerlan\QRCode\Data\QRMatrix $matrix
+	 * @var int
 	 */
 	 */
-	protected $matrix;
+	protected $moduleCount;
 
 
 	/**
 	/**
-	 * @var int
+	 * @param \chillerlan\QRCode\Data\QRMatrix $matrix
 	 */
 	 */
-	protected $moduleCount;
+	protected $matrix;
 
 
 	/**
 	/**
-	 * @var object
+	 * @var \chillerlan\QRCode\QROptions
 	 */
 	 */
 	protected $options;
 	protected $options;
 
 
 	/**
 	/**
-	 * @param \chillerlan\QRCode\QROptions      $options
-	 * @param \chillerlan\QRCode\Data\QRMatrix  $matrix
+	 * QROutputAbstract constructor.
+	 *
+	 * @param \chillerlan\QRCode\QROptions     $options
+	 * @param \chillerlan\QRCode\Data\QRMatrix $matrix
 	 *
 	 *
 	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
 	 * @throws \chillerlan\QRCode\Output\QRCodeOutputException
 	 */
 	 */

+ 1 - 1
src/Output/QROutputInterface.php

@@ -13,7 +13,7 @@
 namespace chillerlan\QRCode\Output;
 namespace chillerlan\QRCode\Output;
 
 
 /**
 /**
- *
+ * Converts the data matrix into readable output
  */
  */
 interface QROutputInterface{
 interface QROutputInterface{
 
 

+ 7 - 6
src/Output/QRString.php

@@ -15,20 +15,21 @@ namespace chillerlan\QRCode\Output;
 use chillerlan\QRCode\QRCode;
 use chillerlan\QRCode\QRCode;
 
 
 /**
 /**
- *
+ * Converts the matrix data into string types
  */
  */
 class QRString extends QROutputAbstract{
 class QRString extends QROutputAbstract{
 
 
 	/**
 	/**
 	 * @return string
 	 * @return string
 	 */
 	 */
-	public function dump():string {
+	public function dump():string{
 
 
 		switch($this->options->outputType){
 		switch($this->options->outputType){
-			case QRCode::OUTPUT_STRING_TEXT: return $this->toString();
+			case QRCode::OUTPUT_STRING_TEXT:
+				return $this->toString();
 			case QRCode::OUTPUT_STRING_JSON:
 			case QRCode::OUTPUT_STRING_JSON:
 			default:
 			default:
-				return json_encode($this->matrix);
+				return json_encode($this->matrix->matrix());
 		}
 		}
 
 
 	}
 	}
@@ -36,12 +37,12 @@ class QRString extends QROutputAbstract{
 	/**
 	/**
 	 * @return string
 	 * @return string
 	 */
 	 */
-	protected function toString():string {
+	protected function toString():string{
 		$str = '';
 		$str = '';
 
 
 		foreach($this->matrix->matrix() as $row){
 		foreach($this->matrix->matrix() as $row){
 			foreach($row as $col){
 			foreach($row as $col){
-				$str .= $col
+				$str .= $col >> 8 > 0
 					? $this->options->textDark
 					? $this->options->textDark
 					: $this->options->textLight;
 					: $this->options->textLight;
 			}
 			}

+ 31 - 12
src/QRCode.php

@@ -21,6 +21,8 @@ use chillerlan\QRCode\Output\{
 use chillerlan\Traits\ClassLoader;
 use chillerlan\Traits\ClassLoader;
 
 
 /**
 /**
+ * Turns a text string into a Model 2 QR Code
+ *
  * @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
  * @link https://github.com/kazuhikoarase/qrcode-generator/tree/master/php
  * @link http://www.qrcode.com/en/codes/model12.html
  * @link http://www.qrcode.com/en/codes/model12.html
  * @link http://www.thonky.com/qr-code-tutorial/
  * @link http://www.thonky.com/qr-code-tutorial/
@@ -40,7 +42,7 @@ class QRCode{
 	const OUTPUT_IMAGE_GIF    = 'gif';
 	const OUTPUT_IMAGE_GIF    = 'gif';
 
 
 	const OUTPUT_STRING_JSON  = 'json';
 	const OUTPUT_STRING_JSON  = 'json';
-	const OUTPUT_STRING_TEXT  = 'txt';
+	const OUTPUT_STRING_TEXT  = 'text';
 
 
 	const VERSION_AUTO        = -1;
 	const VERSION_AUTO        = -1;
 	const MASK_PATTERN_AUTO   = -1;
 	const MASK_PATTERN_AUTO   = -1;
@@ -107,6 +109,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * Sets the options, called internally by the constructor
+	 *
 	 * @param \chillerlan\QRCode\QROptions $options
 	 * @param \chillerlan\QRCode\QROptions $options
 	 *
 	 *
 	 * @return \chillerlan\QRCode\QRCode
 	 * @return \chillerlan\QRCode\QRCode
@@ -118,6 +122,10 @@ class QRCode{
 			throw new QRCodeException('Invalid error correct level: '.$options->eccLevel);
 			throw new QRCodeException('Invalid error correct level: '.$options->eccLevel);
 		}
 		}
 
 
+		if(!is_array($options->imageTransparencyBG || count($options->imageTransparencyBG) < 3)){
+			$options->imageTransparencyBG = [255, 255, 255];
+		}
+
 		$options->version = (int)$options->version;
 		$options->version = (int)$options->version;
 
 
 		// clamp min/max version number
 		// clamp min/max version number
@@ -130,6 +138,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * Renders a QR Code for the given $data and QROptions
+	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
 	 * @return mixed
 	 * @return mixed
@@ -139,6 +149,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * Returns a QRMatrix object for the given $data and current QROptions
+	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Data\QRMatrix
 	 * @return \chillerlan\QRCode\Data\QRMatrix
@@ -170,6 +182,10 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * shoves a QRMatrix through the MaskPatternTester to find the lowest penalty mask pattern
+	 *
+	 * @see \chillerlan\QRCode\Data\MaskPatternTester
+	 *
 	 * @return int
 	 * @return int
 	 */
 	 */
 	protected function getBestMaskPattern():int{
 	protected function getBestMaskPattern():int{
@@ -191,12 +207,14 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * returns a fresh QRDataInterface for the given $data
+	 *
 	 * @param string                       $data
 	 * @param string                       $data
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Data\QRDataInterface
 	 * @return \chillerlan\QRCode\Data\QRDataInterface
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 * @throws \chillerlan\QRCode\Data\QRCodeDataException
 	 */
 	 */
-	protected function initDataInterface(string $data):QRDataInterface{
+	public function initDataInterface(string $data):QRDataInterface{
 
 
 		$DATA_MODES = [
 		$DATA_MODES = [
 			Number::class   => 'Number',
 			Number::class   => 'Number',
@@ -217,6 +235,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * returns a fresh (built-in) QROutputInterface
+	 *
 	 * @param string $data
 	 * @param string $data
 	 *
 	 *
 	 * @return \chillerlan\QRCode\Output\QROutputInterface
 	 * @return \chillerlan\QRCode\Output\QROutputInterface
@@ -236,17 +256,18 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * checks of a string qualifies as numeric
+	 *
 	 * @param string $string
 	 * @param string $string
 	 *
 	 *
 	 * @return bool
 	 * @return bool
 	 */
 	 */
 	public function isNumber(string $string):bool {
 	public function isNumber(string $string):bool {
 		$len = strlen($string);
 		$len = strlen($string);
+		$map = str_split('0123456789');
 
 
 		for($i = 0; $i < $len; $i++){
 		for($i = 0; $i < $len; $i++){
-			$c = ord($string[$i]);
-
-			if(!(ord('0') <= $c && $c <= ord('9'))){
+			if(!in_array($string[$i], $map, true)){
 				return false;
 				return false;
 			}
 			}
 		}
 		}
@@ -255,6 +276,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * checks of a string qualifies as alphanumeric
+	 *
 	 * @param string $string
 	 * @param string $string
 	 *
 	 *
 	 * @return bool
 	 * @return bool
@@ -263,13 +286,7 @@ class QRCode{
 		$len = strlen($string);
 		$len = strlen($string);
 
 
 		for($i = 0; $i < $len; $i++){
 		for($i = 0; $i < $len; $i++){
-			$c = ord($string[$i]);
-
-			if(
-				   !(ord('0') <= $c && $c <= ord('9'))
-				&& !(ord('A') <= $c && $c <= ord('Z'))
-				&& strpos(' $%*+-./:', $string[$i]) === false
-			){
+			if(!in_array($string[$i], AlphaNum::CHAR_MAP, true)){
 				return false;
 				return false;
 			}
 			}
 		}
 		}
@@ -278,6 +295,8 @@ class QRCode{
 	}
 	}
 
 
 	/**
 	/**
+	 * checks of a string qualifies as Kanji
+	 *
 	 * @param string $string
 	 * @param string $string
 	 *
 	 *
 	 * @return bool
 	 * @return bool

+ 15 - 42
src/QROptions.php

@@ -31,16 +31,13 @@ use chillerlan\Traits\Container;
  * @property int    $scale
  * @property int    $scale
  *
  *
  * @property string $cssClass
  * @property string $cssClass
- * @property string $htmlRowTag
- * @property bool   $htmlOmitEndTag
- * @property string $svgFgColor
- * @property string $svgBgColor
  *
  *
  * @property string $textDark
  * @property string $textDark
  * @property string $textLight
  * @property string $textLight
  *
  *
  * @property bool   $imageBase64
  * @property bool   $imageBase64
  * @property bool   $imageTransparent
  * @property bool   $imageTransparent
+ * @property array  $imageTransparencyBG
  * @property int    $pngCompression
  * @property int    $pngCompression
  * @property int    $jpegQuality
  * @property int    $jpegQuality
  *
  *
@@ -126,8 +123,6 @@ class QROptions{
 	 */
 	 */
 	protected $cachefile;
 	protected $cachefile;
 
 
-
-
 	/**
 	/**
 	 * newline string [HTML, SVG, TEXT]
 	 * newline string [HTML, SVG, TEXT]
 	 *
 	 *
@@ -143,9 +138,6 @@ class QROptions{
 	 */
 	 */
 	protected $scale = 5;
 	protected $scale = 5;
 
 
-
-
-
 	/**
 	/**
 	 * a common css class
 	 * a common css class
 	 *
 	 *
@@ -153,36 +145,6 @@ class QROptions{
 	 */
 	 */
 	protected $cssClass;
 	protected $cssClass;
 
 
-	/**
-	 * the shortest available semanically correct row (block) tag to not bloat the output
-	 *
-	 * @var string
-	 */
-	protected $htmlRowTag = 'p';
-
-	/**
-	 * the closing tag may be omitted (moar bloat!)
-	 *
-	 * @var bool
-	 */
-	protected $htmlOmitEndTag = true;
-
-	/**
-	 * SVG foreground color
-	 *
-	 * @var string
-	 */
-	protected $svgFgColor = '#000';
-
-	/**
-	 * SVG background color
-	 *
-	 * @var string
-	 */
-	protected $svgBgColor = '#fff';
-
-
-
 	/**
 	/**
 	 * string substitute for dark
 	 * string substitute for dark
 	 *
 	 *
@@ -197,26 +159,37 @@ class QROptions{
 	 */
 	 */
 	protected $textLight = '⭕';
 	protected $textLight = '⭕';
 
 
-
-
 	/**
 	/**
+	 * toggle base64 or raw image data
+	 *
 	 * @var bool
 	 * @var bool
 	 */
 	 */
 	protected $imageBase64 = true;
 	protected $imageBase64 = true;
 
 
 	/**
 	/**
-	 * not supported by jpg
+	 * toggle transparency, not supported by jpg
 	 *
 	 *
 	 * @var bool
 	 * @var bool
 	 */
 	 */
 	protected $imageTransparent = true;
 	protected $imageTransparent = true;
 
 
 	/**
 	/**
+	 * @see imagecolortransparent()
+	 *
+	 * @var array [R, G, B]
+	 */
+	protected $imageTransparencyBG = [255, 255, 255];
+
+	/**
+	 * @see imagepng()
+	 *
 	 * @var int
 	 * @var int
 	 */
 	 */
 	protected $pngCompression = -1;
 	protected $pngCompression = -1;
 
 
 	/**
 	/**
+	 * @see imagejpeg()
+	 *
 	 * @var int
 	 * @var int
 	 */
 	 */
 	protected $jpegQuality = 85;
 	protected $jpegQuality = 85;