Skip to content

Commit

Permalink
Merge pull request #205 from picqer/background-colors
Browse files Browse the repository at this point in the history
Add support for background colors
  • Loading branch information
casperbakker authored Sep 21, 2024
2 parents fb4480b + 110b2ce commit 5fd1162
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 13 deletions.
12 changes: 8 additions & 4 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ Each renderer has their own options. Only the barcode is required, the rest is o
A vector based SVG image. Gives the best quality to print.
```php
$renderer = new Picqer\Barcode\Renderers\SvgRenderer();
$renderer->setForegroundColor('red'); // Give a color for the bars, the background is always white
$renderer->setForegroundColor('red'); // Give a color for the bars, default is black
$renderer->setBackgroundColor('blue'); // Give a color for the background, default is transparent
$renderer->setSvgType($renderer::TYPE_SVG_INLINE); // Changes the output to be used inline inside HTML documents, instead of a standalone SVG image (default)
$renderer->setSvgType($renderer::TYPE_SVG_STANDALONE); // If you want to force the default, create a stand alone SVG image

Expand All @@ -78,7 +79,8 @@ $renderer->render($barcode, 450.20, 75); // Width and height support floats
All options for PNG and JPG are the same.
```php
$renderer = new Picqer\Barcode\Renderers\PngRenderer();
$renderer->setForegroundColor([255, 0, 0]); // Give a color for the bars, the background is always white. Give it as 3 times 0-255 values for red, green and blue.
$renderer->setForegroundColor([255, 0, 0]); // Give a color for the bars, default is black. Give it as 3 times 0-255 values for red, green and blue.
$renderer->setBackgroundColor([0, 255, 255]); // Give a color for the background, default is transparent (in PNG) or white (in JPG). Give it as 3 times 0-255 values for red, green and blue.
$renderer->useGd(); // If you have Imagick and GD installed, but want to use GD
$renderer->useImagick(); // If you have Imagick and GD installed, but want to use Imagick

Expand All @@ -89,7 +91,8 @@ $renderer->render($barcode, 5, 40); // Width factor (how many pixel wide every b
Gives HTML to use inline in a full HTML document.
```php
$renderer = new Picqer\Barcode\Renderers\HtmlRenderer();
$renderer->setForegroundColor('red'); // Give a color for the bars, the background is always white
$renderer->setForegroundColor('red'); // Give a color for the bars, default is black
$renderer->setBackgroundColor('blue'); // Give a color for the background, default is transparent

$renderer->render($barcode, 450.20, 75); // Width and height support floats
````
Expand All @@ -98,7 +101,8 @@ $renderer->render($barcode, 450.20, 75); // Width and height support floats
Give HTML here the barcode is using the full width and height, to put inside a container/div that has a fixed size.
```php
$renderer = new Picqer\Barcode\Renderers\DynamicHtmlRenderer();
$renderer->setForegroundColor('red'); // Give a color for the bars, the background is always white
$renderer->setForegroundColor('red'); // Give a color for the bars, default is black
$renderer->setBackgroundColor('blue'); // Give a color for the background, default is transparent

$renderer->render($barcode);
````
Expand Down
7 changes: 7 additions & 0 deletions generate-verified-files.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,15 @@
file_put_contents('tests/verified-files/081231723897-ean13.svg', $svgRenderer->render($barcode, $barcode->getWidth() * 2));
file_put_contents('tests/verified-files/081231723897-ean13-fractional-width.svg', $svgRenderer->render($barcode, $barcode->getWidth() * 0.25, 25.75));

$svgRendererRed = new Picqer\Barcode\Renderers\SvgRenderer();
$svgRendererRed->setBackgroundColor('red');
file_put_contents('tests/verified-files/081231723897-ean13-red-background.svg', $svgRendererRed->render($barcode, $barcode->getWidth() * 2));

$barcode = $typeEncoderCode128->getBarcode('081231723897');
file_put_contents('tests/verified-files/081231723897-code128.html', $htmlRenderer->render($barcode, $barcode->getWidth() * 2));
$htmlRendererRed = new Picqer\Barcode\Renderers\HtmlRenderer();
$htmlRendererRed->setBackgroundColor('red');
file_put_contents('tests/verified-files/081231723897-code128-red-background.html', $htmlRendererRed->render($barcode, $barcode->getWidth() * 2));

$barcode = $typeEncoderIMB->getBarcode('12345678903');
file_put_contents('tests/verified-files/12345678903-imb.html', $htmlRenderer->render($barcode, $barcode->getWidth() * 2));
Expand Down
10 changes: 9 additions & 1 deletion src/Renderers/DynamicHtmlRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ class DynamicHtmlRenderer
protected const WIDTH_PRECISION = 6;

protected string $foregroundColor = 'black';
protected ?string $backgroundColor = null;

public function render(Barcode $barcode): string
{
$html = '<div style="font-size:0;position:relative;width:100%;height:100%">' . PHP_EOL;
$html = '<div style="font-size:0;position:relative;width:100%;height:100%' . ($this->backgroundColor ? ';background-color:' . $this->backgroundColor : '') . '">' . PHP_EOL;

$positionHorizontal = 0;
/** @var BarcodeBar $bar */
Expand All @@ -36,10 +37,17 @@ public function render(Barcode $barcode): string
return $html;
}

// Use HTML color definitions, like 'red' or '#ff0000'
public function setForegroundColor(string $color): self
{
$this->foregroundColor = $color;
return $this;
}

// Use HTML color definitions, like 'red' or '#ff0000'
public function setBackgroundColor(?string $color): self
{
$this->backgroundColor = $color;
return $this;
}
}
12 changes: 10 additions & 2 deletions src/Renderers/HtmlRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
class HtmlRenderer
{
protected string $foregroundColor = 'black';
protected ?string $backgroundColor = null;

public function render(Barcode $barcode, float $width = 200, float $height = 30): string
{
$widthFactor = $width / $barcode->getWidth();

$html = '<div style="font-size:0;position:relative;width:' . $width . 'px;height:' . ($height) . 'px;">' . PHP_EOL;
$html = '<div style="font-size:0;position:relative;width:' . $width . 'px;height:' . ($height) . 'px;' . ($this->backgroundColor ? 'background-color:' . $this->backgroundColor . ';' : '') . '">' . PHP_EOL;

$positionHorizontal = 0;
/** @var BarcodeBar $bar */
Expand All @@ -36,10 +37,17 @@ public function render(Barcode $barcode, float $width = 200, float $height = 30)
return $html;
}

// Use HTML color definitions, like 'red' or '#ff0000'
public function setForegroundColor(string $color): self
{
$this->foregroundColor = $color;

return $this;
}

// Use HTML color definitions, like 'red' or '#ff0000'
public function setBackgroundColor(?string $color): self
{
$this->backgroundColor = $color;
return $this;
}
}
10 changes: 9 additions & 1 deletion src/Renderers/JpgRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@
namespace Picqer\Barcode\Renderers;

use Imagick;
use ImagickPixel;

class JpgRenderer extends PngRenderer
{
protected function createImagickImageObject(int $width, int $height): Imagick
{
$image = new Imagick();
$image->newImage($width, $height, 'none', 'JPG');
if ($this->backgroundColor !== null) {
// Colored background
$backgroundColor = new ImagickPixel('rgb(' . implode(',', $this->backgroundColor) . ')');
} else {
// Use transparent background
$backgroundColor = new ImagickPixel('none');
}
$image->newImage($width, $height, $backgroundColor, 'JPG');

return $image;
}
Expand Down
35 changes: 30 additions & 5 deletions src/Renderers/PngRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
class PngRenderer
{
protected array $foregroundColor = [0, 0, 0];
protected ?array $backgroundColor = null;

protected bool $useImagick;

/**
Expand Down Expand Up @@ -52,6 +54,7 @@ public function render(Barcode $barcode, int $widthFactor = 2, int $height = 30)
$width = (int)round($barcode->getWidth() * $widthFactor);

if ($this->useImagick) {
$image = $this->createImagickImageObject($width, $height);
$imagickBarsShape = new ImagickDraw();
$imagickBarsShape->setFillColor(new ImagickPixel('rgb(' . implode(',', $this->foregroundColor) .')'));
} else {
Expand Down Expand Up @@ -80,7 +83,6 @@ public function render(Barcode $barcode, int $widthFactor = 2, int $height = 30)
}

if ($this->useImagick) {
$image = $this->createImagickImageObject($width, $height);
$image->drawImage($imagickBarsShape);
return $image->getImageBlob();
} else {
Expand All @@ -90,26 +92,49 @@ public function render(Barcode $barcode, int $widthFactor = 2, int $height = 30)
}
}

// Use RGB color definitions, like [0, 0, 0] or [255, 255, 255]
public function setForegroundColor(array $color): self
{
$this->foregroundColor = $color;

return $this;
}

// Use RGB color definitions, like [0, 0, 0] or [255, 255, 255]
// If no color is set, the background will be transparent
public function setBackgroundColor(?array $color): self
{
$this->backgroundColor = $color;
return $this;
}

protected function createGdImageObject(int $width, int $height)
{
$image = \imagecreate($width, $height);
$colorBackground = \imagecolorallocate($image, 255, 255, 255);
\imagecolortransparent($image, $colorBackground);

if ($this->backgroundColor !== null) {
// Colored background
$backgroundColor = \imagecolorallocate($image, $this->backgroundColor[0], $this->backgroundColor[1], $this->backgroundColor[2]);
\imagefill($image, 0, 0, $backgroundColor);
} else {
// Use transparent background
$backgroundColor = \imagecolorallocate($image, 255, 255, 255);
\imagecolortransparent($image, $backgroundColor);
}

return $image;
}

protected function createImagickImageObject(int $width, int $height): Imagick
{
$image = new Imagick();
$image->newImage($width, $height, 'none', 'PNG');
if ($this->backgroundColor !== null) {
// Colored background
$backgroundColor = new ImagickPixel('rgb(' . implode(',', $this->backgroundColor) . ')');
} else {
// Use transparent background
$backgroundColor = new ImagickPixel('none');
}
$image->newImage($width, $height, $backgroundColor, 'PNG');

return $image;
}
Expand Down
13 changes: 13 additions & 0 deletions src/Renderers/SvgRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
class SvgRenderer
{
protected string $foregroundColor = 'black';
protected ?string $backgroundColor = null;
protected string $svgType = self::TYPE_SVG_STANDALONE;

public const TYPE_SVG_STANDALONE = 'standalone';
Expand All @@ -25,6 +26,12 @@ public function render(Barcode $barcode, float $width = 200, float $height = 30)
}
$svg .= '<svg width="' . $width . '" height="' . $height . '" viewBox="0 0 ' . $width . ' ' . $height . '" version="1.1" xmlns="http://www.w3.org/2000/svg">' . PHP_EOL;
$svg .= "\t" . '<desc>' . htmlspecialchars($barcode->getBarcode()) . '</desc>' . PHP_EOL;

// Add background rectangle if backgroundColor is set
if ($this->backgroundColor !== null) {
$svg .= "\t" . '<rect id="background" width="100%" height="100%" fill="' . $this->backgroundColor . '"/>' . PHP_EOL;
}

$svg .= "\t" . '<g id="bars" fill="' . $this->foregroundColor . '" stroke="none">' . PHP_EOL;

// print bars
Expand Down Expand Up @@ -55,6 +62,12 @@ public function setForegroundColor(string $color): self
return $this;
}

public function setBackgroundColor(?string $color): self
{
$this->backgroundColor = $color;
return $this;
}

public function setSvgType(string $svgType): self
{
if (! in_array($svgType, [self::TYPE_SVG_INLINE, self::TYPE_SVG_STANDALONE])) {
Expand Down
11 changes: 11 additions & 0 deletions tests/HtmlRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,15 @@ public function test_html_barcode_generator_can_generate_imb_barcode_to_test_hei

$this->assertStringEqualsFile('tests/verified-files/12345678903-imb.html', $generated);
}

public function test_html_barcode_generator_with_background()
{
$barcode = (new Picqer\Barcode\Types\TypeCode128())->getBarcode('081231723897');

$renderer = new Picqer\Barcode\Renderers\HtmlRenderer();
$renderer->setBackgroundColor('red');
$generated = $renderer->render($barcode, $barcode->getWidth() * 2);

$this->assertStringEqualsFile('tests/verified-files/081231723897-code128-red-background.html', $generated);
}
}
11 changes: 11 additions & 0 deletions tests/SvgRendererTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,15 @@ public function test_svg_renderer_throws_exception_wrong_type()
$renderer = new Picqer\Barcode\Renderers\SvgRenderer();
$renderer->setSvgType('other');
}

public function test_svg_barcode_generator_can_use_background_color()
{
$barcode = (new Picqer\Barcode\Types\TypeEan13())->getBarcode('081231723897');

$renderer = new Picqer\Barcode\Renderers\SvgRenderer();
$renderer->setBackgroundColor('red');
$generated = $renderer->render($barcode, 190);

$this->assertStringEqualsFile('tests/verified-files/081231723897-ean13-red-background.svg', $generated);
}
}
30 changes: 30 additions & 0 deletions tests/verified-files/081231723897-code128-red-background.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<div style="font-size:0;position:relative;width:202px;height:30px;background-color:red;">
<div style="background-color:black;width:4px;height:30px;position:absolute;left:0px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:6px;top:0">&nbsp;</div>
<div style="background-color:black;width:6px;height:30px;position:absolute;left:12px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:22px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:30px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:38px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:44px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:48px;top:0">&nbsp;</div>
<div style="background-color:black;width:6px;height:30px;position:absolute;left:56px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:66px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:72px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:82px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:88px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:94px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:106px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:110px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:118px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:128px;top:0">&nbsp;</div>
<div style="background-color:black;width:8px;height:30px;position:absolute;left:132px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:142px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:146px;top:0">&nbsp;</div>
<div style="background-color:black;width:6px;height:30px;position:absolute;left:154px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:162px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:166px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:176px;top:0">&nbsp;</div>
<div style="background-color:black;width:6px;height:30px;position:absolute;left:186px;top:0">&nbsp;</div>
<div style="background-color:black;width:2px;height:30px;position:absolute;left:194px;top:0">&nbsp;</div>
<div style="background-color:black;width:4px;height:30px;position:absolute;left:198px;top:0">&nbsp;</div>
</div>
38 changes: 38 additions & 0 deletions tests/verified-files/081231723897-ean13-red-background.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 5fd1162

Please sign in to comment.