:octocat: better(?) module value handling

This commit is contained in:
codemasher
2018-09-19 18:11:56 +02:00
parent fb2c574b64
commit 3fd7e80148
9 changed files with 158 additions and 116 deletions
+4
View File
@@ -18,6 +18,10 @@ use chillerlan\QRCode\Output\QROutputAbstract;
*/
class MyCustomOutput extends QROutputAbstract{
protected function setModuleValues():void{
// TODO: Implement setModuleValues() method.
}
public function dump(string $file = null){
$output = '';
+38 -67
View File
@@ -12,85 +12,71 @@
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\{QRCode, Data\QRMatrix};
use chillerlan\QRCode\QRCode;
/**
* Converts the matrix into images, raw or base64 output
*/
class QRImage extends QROutputAbstract{
const transparencyTypes = [
const TRANSPARENCY_TYPES = [
QRCode::OUTPUT_IMAGE_PNG,
QRCode::OUTPUT_IMAGE_GIF,
];
protected $defaultMode = QRCode::OUTPUT_IMAGE_PNG;
protected $moduleValues = [
// light
QRMatrix::M_DATA => [255, 255, 255],
QRMatrix::M_FINDER => [255, 255, 255],
QRMatrix::M_SEPARATOR => [255, 255, 255],
QRMatrix::M_ALIGNMENT => [255, 255, 255],
QRMatrix::M_TIMING => [255, 255, 255],
QRMatrix::M_FORMAT => [255, 255, 255],
QRMatrix::M_VERSION => [255, 255, 255],
QRMatrix::M_QUIETZONE => [255, 255, 255],
QRMatrix::M_TEST => [255, 255, 255],
// dark
QRMatrix::M_DARKMODULE << 8 => [0, 0, 0],
QRMatrix::M_DATA << 8 => [0, 0, 0],
QRMatrix::M_FINDER << 8 => [0, 0, 0],
QRMatrix::M_ALIGNMENT << 8 => [0, 0, 0],
QRMatrix::M_TIMING << 8 => [0, 0, 0],
QRMatrix::M_FORMAT << 8 => [0, 0, 0],
QRMatrix::M_VERSION << 8 => [0, 0, 0],
QRMatrix::M_TEST << 8 => [0, 0, 0],
];
/**
* @see imagecreatetruecolor()
* @var resource
*/
protected $image;
/**
* @var int
*/
protected $scale;
/**
* @var int
*/
protected $length;
/**
* @see imagecolorallocate()
* @var int
*/
protected $background;
/**
* @return void
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_array($v) || count($v) < 3){
$this->moduleValues[$M_TYPE] = $defaultValue
? [0, 0, 0]
: [255, 255, 255];
}
else{
$this->moduleValues[$M_TYPE] = array_values($v);
}
}
}
/**
* @param string|null $file
*
* @return string
* @throws \chillerlan\QRCode\Output\QRCodeOutputException
*/
public function dump(string $file = null):string{
$this->image = imagecreatetruecolor($this->length, $this->length);
$this->background = imagecolorallocate($this->image, ...array_values($this->options->imageTransparencyBG));
if($this->options->cachefile !== null && !is_writable(dirname($this->options->cachefile))){
throw new QRCodeOutputException('Could not write data to cache file: '.$this->options->cachefile);
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::TRANSPARENCY_TYPES, true)){
imagecolortransparent($this->image, $this->background);
}
$this->setImage();
$moduleValues = is_array($this->options->moduleValues[$this->matrix::M_DATA])
? $this->options->moduleValues // @codeCoverageIgnore
: $this->moduleValues;
imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $this->background);
foreach($this->matrix->matrix() as $y => $row){
foreach($row as $x => $pixel){
$this->setPixel($x, $y, imagecolorallocate($this->image, ...$moduleValues[$pixel]));
foreach($row as $x => $M_TYPE){
$this->setPixel($x, $y, $this->moduleValues[$M_TYPE]);
}
}
@@ -104,35 +90,20 @@ class QRImage extends QROutputAbstract{
}
/**
* @param int $x
* @param int $y
* @param array $rgb
*
* @return void
*/
protected function setImage(){
$this->scale = $this->options->scale;
$this->length = $this->moduleCount * $this->scale;
$this->image = imagecreatetruecolor($this->length, $this->length);
$this->background = imagecolorallocate($this->image, ...$this->options->imageTransparencyBG);
if((bool)$this->options->imageTransparent && in_array($this->options->outputType, $this::transparencyTypes, true)){
imagecolortransparent($this->image, $this->background);
}
imagefilledrectangle($this->image, 0, 0, $this->length, $this->length, $this->background);
}
/**
* @param int $x
* @param int $y
* @param int $color
* @return void
*/
protected function setPixel(int $x, int $y, int $color){
protected function setPixel(int $x, int $y, array $rgb):void{
imagefilledrectangle(
$this->image,
$x * $this->scale,
$y * $this->scale,
($x + 1) * $this->scale - 1,
($y + 1) * $this->scale - 1,
$color
($x + 1) * $this->scale,
($y + 1) * $this->scale,
imagecolorallocate($this->image, ...$rgb)
);
}
+24 -9
View File
@@ -21,6 +21,27 @@ class QRMarkup extends QROutputAbstract{
protected $defaultMode = QRCode::OUTPUT_MARKUP_SVG;
/**
* @return void
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_string($v)){
$this->moduleValues[$M_TYPE] = $defaultValue
? $this->options->markupDark
: $this->options->markupLight;
}
else{
$this->moduleValues[$M_TYPE] = trim(strip_tags($v), '\'"');
}
}
}
/**
* @return string|bool
*/
@@ -30,8 +51,8 @@ class QRMarkup extends QROutputAbstract{
foreach($this->matrix->matrix() as $row){
$html .= '<div>';
foreach($row as $pixel){
$html .= '<span style="background: '.($this->options->moduleValues[$pixel] ?: 'lightgrey').';"></span>';
foreach($row as $M_TYPE){
$html .= '<span style="background: '.$this->moduleValues[$M_TYPE].';"></span>';
}
$html .= '</div>'.$this->options->eol;
@@ -59,13 +80,7 @@ class QRMarkup extends QROutputAbstract{
.'<defs>'.$this->options->svgDefs.'</defs>'
.$this->options->eol;
foreach($this->options->moduleValues as $M_TYPE => $value){
// fallback
if(is_bool($value)){
$value = $value ? '#000' : '#fff';
}
foreach($this->moduleValues as $M_TYPE => $value){
$path = '';
foreach($matrix as $y => $row){
+26 -1
View File
@@ -16,7 +16,7 @@ use chillerlan\QRCode\{Data\QRMatrix, QRCode};
use chillerlan\Settings\SettingsContainerInterface;
/**
*
* common output abstract
*/
abstract class QROutputAbstract implements QROutputInterface{
@@ -45,6 +45,21 @@ abstract class QROutputAbstract implements QROutputInterface{
*/
protected $defaultMode;
/**
* @var int
*/
protected $scale;
/**
* @var int
*/
protected $length;
/**
* @var array
*/
protected $moduleValues;
/**
* QROutputAbstract constructor.
*
@@ -55,6 +70,8 @@ abstract class QROutputAbstract implements QROutputInterface{
$this->options = $options;
$this->matrix = $matrix;
$this->moduleCount = $this->matrix->size();
$this->scale = $this->options->scale;
$this->length = $this->moduleCount * $this->scale;
$class = get_called_class();
@@ -62,8 +79,16 @@ abstract class QROutputAbstract implements QROutputInterface{
$this->outputMode = $this->options->outputType;
}
$this->setModuleValues();
}
/**
* Sets the initial module values (clean-up & defaults)
*
* @return void
*/
abstract protected function setModuleValues():void;
/**
* @see file_put_contents()
*
+24
View File
@@ -12,11 +12,35 @@
namespace chillerlan\QRCode\Output;
use chillerlan\QRCode\Data\QRMatrix;
/**
* Converts the data matrix into readable output
*/
interface QROutputInterface{
const DEFAULT_MODULE_VALUES = [
// light
QRMatrix::M_DATA => false, // 4
QRMatrix::M_FINDER => false, // 6
QRMatrix::M_SEPARATOR => false, // 8
QRMatrix::M_ALIGNMENT => false, // 10
QRMatrix::M_TIMING => false, // 12
QRMatrix::M_FORMAT => false, // 14
QRMatrix::M_VERSION => false, // 16
QRMatrix::M_QUIETZONE => false, // 18
QRMatrix::M_TEST => false, // 255
// dark
QRMatrix::M_DARKMODULE << 8 => true, // 512
QRMatrix::M_DATA << 8 => true, // 1024
QRMatrix::M_FINDER << 8 => true, // 1536
QRMatrix::M_ALIGNMENT << 8 => true, // 2560
QRMatrix::M_TIMING << 8 => true, // 3072
QRMatrix::M_FORMAT << 8 => true, // 3584
QRMatrix::M_VERSION << 8 => true, // 4096
QRMatrix::M_TEST << 8 => true, // 65280
];
/**
* @param string|null $file
*
+23 -11
View File
@@ -21,6 +21,27 @@ class QRString extends QROutputAbstract{
protected $defaultMode = QRCode::OUTPUT_STRING_TEXT;
/**
* @return void
*/
protected function setModuleValues():void{
foreach($this::DEFAULT_MODULE_VALUES as $M_TYPE => $defaultValue){
$v = $this->options->moduleValues[$M_TYPE] ?? null;
if(!is_string($v)){
$this->moduleValues[$M_TYPE] = $defaultValue
? $this->options->textDark
: $this->options->textLight;
}
else{
$this->moduleValues[$M_TYPE] = $v;
}
}
}
/**
* @return string
*/
@@ -30,17 +51,8 @@ class QRString extends QROutputAbstract{
foreach($this->matrix->matrix() as $row){
$r = [];
foreach($row as $col){
$col = $this->options->moduleValues[$col];
// fallback
if(is_bool($col) || !is_string($col)){
$col = $col
? $this->options->textDark
: $this->options->textLight;
}
$r[] = $col;
foreach($row as $M_TYPE){
$r[] = $this->moduleValues[$M_TYPE];
}
$str[] = implode('', $r);
+3
View File
@@ -37,6 +37,9 @@ use chillerlan\Settings\SettingsContainerAbstract;
* @property string $textDark
* @property string $textLight
*
* @property string $markupDark
* @property string $markupLight
*
* @property bool $imageBase64
* @property bool $imageTransparent
* @property array $imageTransparencyBG
+15 -23
View File
@@ -12,8 +12,6 @@
namespace chillerlan\QRCode;
use chillerlan\QRCode\Data\QRMatrix;
trait QROptionsTrait{
/**
@@ -153,6 +151,20 @@ trait QROptionsTrait{
*/
protected $textLight = '⭕';
/**
* markup substitute for dark (CSS value)
*
* @var string
*/
protected $markupDark = '#000';
/**
* markup substitute for light (CSS value)
*
* @var string
*/
protected $markupLight = '#fff';
/**
* toggle base64 or raw image data
*
@@ -196,27 +208,7 @@ trait QROptionsTrait{
*
* @var array
*/
protected $moduleValues = [
// light
QRMatrix::M_DATA => false, // 4
QRMatrix::M_FINDER => false, // 6
QRMatrix::M_SEPARATOR => false, // 8
QRMatrix::M_ALIGNMENT => false, // 10
QRMatrix::M_TIMING => false, // 12
QRMatrix::M_FORMAT => false, // 14
QRMatrix::M_VERSION => false, // 16
QRMatrix::M_QUIETZONE => false, // 18
QRMatrix::M_TEST => false, // 255
// dark
QRMatrix::M_DARKMODULE << 8 => true, // 512
QRMatrix::M_DATA << 8 => true, // 1024
QRMatrix::M_FINDER << 8 => true, // 1536
QRMatrix::M_ALIGNMENT << 8 => true, // 2560
QRMatrix::M_TIMING << 8 => true, // 3072
QRMatrix::M_FORMAT << 8 => true, // 3584
QRMatrix::M_VERSION << 8 => true, // 4096
QRMatrix::M_TEST << 8 => true, // 65280
];
protected $moduleValues;
/**
* Sets the options, called internally by the constructor
+1 -5
View File
@@ -35,11 +35,7 @@ class QRImageTest extends QROutputTestAbstract{
$this->options->outputType = $type;
$this->options->cachefile = $this::cachefile.$type;
$this->setOutputInterface();
$this->outputInterface->dump();
$this->options->cachefile = null;
$this->options->imageBase64 = false;
$this->setOutputInterface();
$this->outputInterface->dump($this::cachefile.$type);
$img = $this->outputInterface->dump();
if($type === QRCode::OUTPUT_IMAGE_JPG){ // jpeg encoding may cause different results