mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-08-30 03:58:28 +00:00
:octocat: better(?) module value handling
This commit is contained in:
@@ -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
@@ -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
@@ -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){
|
||||
|
||||
@@ -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()
|
||||
*
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user