mirror of
https://github.com/chillerlan/php-qrcode.git
synced 2026-09-01 04:58:26 +00:00
:octocat: circular modules in GD output
This commit is contained in:
+30
-18
@@ -11,51 +11,63 @@ namespace chillerlan\QRCodeExamples;
|
||||
use chillerlan\QRCode\{QRCode, QROptions};
|
||||
use chillerlan\QRCode\Data\QRMatrix;
|
||||
use chillerlan\QRCode\Common\EccLevel;
|
||||
use Throwable;
|
||||
|
||||
require_once __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
$data = 'https://www.youtube.com/watch?v=DLzxrzFCyOs&t=43s';
|
||||
|
||||
$options = new QROptions([
|
||||
'version' => 5,
|
||||
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
|
||||
'eccLevel' => EccLevel::L,
|
||||
'scale' => 5,
|
||||
'imageBase64' => false,
|
||||
'moduleValues' => [
|
||||
'version' => 7,
|
||||
'outputType' => QRCode::OUTPUT_IMAGE_PNG,
|
||||
'eccLevel' => EccLevel::L,
|
||||
'scale' => 10,
|
||||
'imageBase64' => false,
|
||||
'imageTransparent' => false,
|
||||
'drawCircularModules' => true,
|
||||
'circleRadius' => 0.4,
|
||||
'keepAsSquare' => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
|
||||
'moduleValues' => [
|
||||
// finder
|
||||
QRMatrix::M_FINDER | QRMatrix::IS_DARK => [0, 63, 255], // dark (true)
|
||||
QRMatrix::M_FINDER => [255, 255, 255], // light (false), white is the transparency color and is enabled by default
|
||||
QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => [241, 28, 163], // finder dot, dark (true)
|
||||
QRMatrix::M_FINDER => [233, 233, 233], // light (false), white is the transparency color and is enabled by default
|
||||
QRMatrix::M_FINDER_DOT | QRMatrix::IS_DARK => [0, 63, 255], // finder dot, dark (true)
|
||||
// alignment
|
||||
QRMatrix::M_ALIGNMENT | QRMatrix::IS_DARK => [255, 0, 255],
|
||||
QRMatrix::M_ALIGNMENT => [255, 255, 255],
|
||||
QRMatrix::M_ALIGNMENT => [233, 233, 233],
|
||||
// timing
|
||||
QRMatrix::M_TIMING | QRMatrix::IS_DARK => [255, 0, 0],
|
||||
QRMatrix::M_TIMING => [255, 255, 255],
|
||||
QRMatrix::M_TIMING => [233, 233, 233],
|
||||
// format
|
||||
QRMatrix::M_FORMAT | QRMatrix::IS_DARK => [67, 99, 84],
|
||||
QRMatrix::M_FORMAT => [255, 255, 255],
|
||||
QRMatrix::M_FORMAT | QRMatrix::IS_DARK => [67, 159, 84],
|
||||
QRMatrix::M_FORMAT => [233, 233, 233],
|
||||
// version
|
||||
QRMatrix::M_VERSION | QRMatrix::IS_DARK => [62, 174, 190],
|
||||
QRMatrix::M_VERSION => [255, 255, 255],
|
||||
QRMatrix::M_VERSION => [233, 233, 233],
|
||||
// data
|
||||
QRMatrix::M_DATA | QRMatrix::IS_DARK => [0, 0, 0],
|
||||
QRMatrix::M_DATA => [255, 255, 255],
|
||||
QRMatrix::M_DATA => [233, 233, 233],
|
||||
// darkmodule
|
||||
QRMatrix::M_DARKMODULE | QRMatrix::IS_DARK => [0, 0, 0],
|
||||
// separator
|
||||
QRMatrix::M_SEPARATOR => [255, 255, 255],
|
||||
QRMatrix::M_SEPARATOR => [233, 233, 233],
|
||||
// quietzone
|
||||
QRMatrix::M_QUIETZONE => [255, 255, 255],
|
||||
QRMatrix::M_QUIETZONE => [233, 233, 233],
|
||||
// logo (requires a call to QRMatrix::setLogoSpace()), see QRImageWithLogo
|
||||
QRMatrix::M_LOGO => [255, 255, 255],
|
||||
QRMatrix::M_LOGO => [233, 233, 233],
|
||||
],
|
||||
]);
|
||||
|
||||
try{
|
||||
$im = (new QRCode($options))->render($data);
|
||||
}
|
||||
catch(Throwable $e){
|
||||
exit($e->getMessage());
|
||||
}
|
||||
|
||||
header('Content-type: image/png');
|
||||
|
||||
echo (new QRCode($options))->render($data);
|
||||
echo $im;
|
||||
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -29,10 +29,10 @@ $options = new QROptions([
|
||||
'markupDark' => '',
|
||||
'markupLight' => '',
|
||||
// draw the modules as circles isntead of squares
|
||||
'svgDrawCircularModules' => true,
|
||||
'svgCircleRadius' => 0.3,
|
||||
'drawCircularModules' => true,
|
||||
'circleRadius' => 0.4,
|
||||
// keep modules of thhese types as square
|
||||
'svgKeepAsSquare' => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
|
||||
'keepAsSquare' => [QRMatrix::M_FINDER|QRMatrix::IS_DARK, QRMatrix::M_FINDER_DOT, QRMatrix::M_ALIGNMENT|QRMatrix::IS_DARK],
|
||||
// connect
|
||||
'svgConnectPaths' => true,
|
||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element/linearGradient
|
||||
|
||||
+35
-12
@@ -17,9 +17,10 @@ use chillerlan\QRCode\QRCode;
|
||||
use chillerlan\Settings\SettingsContainerInterface;
|
||||
use Exception;
|
||||
|
||||
use function array_values, call_user_func, count, extension_loaded, imagecolorallocate, imagecolortransparent,
|
||||
imagecreatetruecolor, imagedestroy, imagefilledrectangle, imagegif, imagejpeg, imagepng, in_array,
|
||||
use function array_values, count, extension_loaded, imagecolorallocate, imagecolortransparent, imagecreatetruecolor,
|
||||
imagedestroy, imagefilledellipse, imagefilledrectangle, imagegif, imagejpeg, imagepng, imagescale, in_array,
|
||||
is_array, ob_end_clean, ob_get_contents, ob_start, range;
|
||||
use const IMG_BICUBIC;
|
||||
|
||||
/**
|
||||
* Converts the matrix into GD images, raw or base64 output (requires ext-gd)
|
||||
@@ -93,6 +94,12 @@ class QRImage extends QROutputAbstract{
|
||||
public function dump(string $file = null){
|
||||
$file ??= $this->options->cachefile;
|
||||
|
||||
// we're scaling the image up in order to draw crisp round circles, otherwise they appear square-y on small scales
|
||||
if($this->options->drawCircularModules && $this->options->scale <= 20){
|
||||
$this->length = ($this->length + 2) * 10;
|
||||
$this->scale *= 10;
|
||||
}
|
||||
|
||||
$this->image = imagecreatetruecolor($this->length, $this->length);
|
||||
|
||||
// avoid: "Indirect modification of overloaded property $imageTransparencyBG has no effect"
|
||||
@@ -113,6 +120,11 @@ class QRImage extends QROutputAbstract{
|
||||
}
|
||||
}
|
||||
|
||||
// scale down to the expected size
|
||||
if($this->options->drawCircularModules && $this->options->scale <= 20){
|
||||
$this->image = imagescale($this->image, $this->length/10, $this->length/10, IMG_BICUBIC);
|
||||
}
|
||||
|
||||
if($this->options->returnResource){
|
||||
return $this->image;
|
||||
}
|
||||
@@ -134,15 +146,26 @@ class QRImage extends QROutputAbstract{
|
||||
* Creates a single QR pixel with the given settings
|
||||
*/
|
||||
protected function setPixel(int $x, int $y, int $M_TYPE):void{
|
||||
imagefilledrectangle(
|
||||
$this->image,
|
||||
$x * $this->scale,
|
||||
$y * $this->scale,
|
||||
($x + 1) * $this->scale,
|
||||
($y + 1) * $this->scale,
|
||||
/** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
|
||||
imagecolorallocate($this->image, ...$this->moduleValues[$M_TYPE])
|
||||
);
|
||||
/** @phan-suppress-next-line PhanParamTooFewInternalUnpack */
|
||||
$color = imagecolorallocate($this->image, ...$this->moduleValues[$M_TYPE]);
|
||||
|
||||
$this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->keepAsSquare)
|
||||
? imagefilledellipse(
|
||||
$this->image,
|
||||
($x * $this->scale) + ($this->scale / 2),
|
||||
($y * $this->scale) + ($this->scale / 2),
|
||||
2 * $this->options->circleRadius * $this->scale,
|
||||
2 * $this->options->circleRadius * $this->scale,
|
||||
$color
|
||||
)
|
||||
: imagefilledrectangle(
|
||||
$this->image,
|
||||
$x * $this->scale,
|
||||
$y * $this->scale,
|
||||
($x + 1) * $this->scale,
|
||||
($y + 1) * $this->scale,
|
||||
$color
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,7 +177,7 @@ class QRImage extends QROutputAbstract{
|
||||
ob_start();
|
||||
|
||||
try{
|
||||
call_user_func([$this, $this->outputMode ?? $this->defaultMode]);
|
||||
$this->{$this->outputMode ?? $this->defaultMode}();
|
||||
}
|
||||
// not going to cover edge cases
|
||||
// @codeCoverageIgnoreStart
|
||||
|
||||
@@ -189,8 +189,8 @@ class QRMarkup extends QROutputAbstract{
|
||||
return '';
|
||||
}
|
||||
|
||||
if($this->options->svgDrawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->svgKeepAsSquare)){
|
||||
$r = $this->options->svgCircleRadius;
|
||||
if($this->options->drawCircularModules && !$this->matrix->checkTypes($x, $y, $this->options->keepAsSquare)){
|
||||
$r = $this->options->circleRadius;
|
||||
|
||||
return sprintf(
|
||||
'M%1$s %2$s a%3$s %3$s 0 1 0 %4$s 0 a%3$s,%3$s 0 1 0 -%4$s 0Z',
|
||||
|
||||
@@ -162,18 +162,20 @@ trait QROptionsTrait{
|
||||
|
||||
/**
|
||||
* specify whether to draw the modules as filled circles
|
||||
*
|
||||
* @see https://github.com/chillerlan/php-qrcode/issues/23
|
||||
*/
|
||||
protected bool $svgDrawCircularModules = false;
|
||||
protected bool $drawCircularModules = false;
|
||||
|
||||
/**
|
||||
* specifies the radius of the modules when $svgDrawCircularModules is set to true
|
||||
*/
|
||||
protected float $svgCircleRadius = 0.45;
|
||||
protected float $circleRadius = 0.45;
|
||||
|
||||
/**
|
||||
* specifies which module types to exclude when $svgDrawCircularModules is set to true
|
||||
*/
|
||||
protected array $svgKeepAsSquare = [];
|
||||
protected array $keepAsSquare = [];
|
||||
|
||||
/**
|
||||
* string substitute for dark
|
||||
|
||||
Reference in New Issue
Block a user