3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Barcode\Renderer
;
12 use Zend\Barcode\Exception\RendererCreationException
;
13 use Zend\Stdlib\ErrorHandler
;
16 * Class for rendering the barcode as image
18 class Image
extends AbstractRenderer
21 * List of authorized output format
24 protected $allowedImageType = [
34 protected $imageType = 'png';
37 * Resource for the image
40 protected $resource = null;
43 * Resource for the font and bars color of the image
46 protected $imageForeColor = null;
49 * Resource for the background color of the image
52 protected $imageBackgroundColor = null;
55 * Height of the rendered image wanted by user
58 protected $userHeight = 0;
61 * Width of the rendered image wanted by user
64 protected $userWidth = 0;
69 * @param array|\Traversable $options
70 * @throws RendererCreationException
72 public function __construct($options = null)
74 if (! function_exists('gd_info')) {
75 throw new RendererCreationException(__CLASS__
. ' requires the GD extension');
78 parent
::__construct($options);
82 * Set height of the result image
84 * @param null|int $value
85 * @throws Exception\OutOfRangeException
86 * @return self Provides a fluent interface
88 public function setHeight($value)
90 if (! is_numeric($value) ||
intval($value) < 0) {
91 throw new Exception\
OutOfRangeException(
92 'Image height must be greater than or equals 0'
95 $this->userHeight
= intval($value);
104 public function getHeight()
106 return $this->userHeight
;
112 * @param mixed $value
113 * @throws Exception\OutOfRangeException
114 * @return self Provides a fluent interface
116 public function setWidth($value)
118 if (! is_numeric($value) ||
intval($value) < 0) {
119 throw new Exception\
OutOfRangeException(
120 'Image width must be greater than or equals 0'
123 $this->userWidth
= intval($value);
132 public function getWidth()
134 return $this->userWidth
;
138 * Set an image resource to draw the barcode inside
140 * @param resource $image
141 * @return self Provides a fluent interface
142 * @throws Exception\InvalidArgumentException
144 public function setResource($image)
146 if (gettype($image) != 'resource' ||
get_resource_type($image) != 'gd') {
147 throw new Exception\
InvalidArgumentException(
148 'Invalid image resource provided to setResource()'
151 $this->resource = $image;
156 * Set the image type to produce (png, jpeg, gif)
158 * @param string $value
159 * @throws Exception\InvalidArgumentException
160 * @return self Provides a fluent interface
162 public function setImageType($value)
164 if ($value == 'jpg') {
168 if (! in_array($value, $this->allowedImageType
)) {
169 throw new Exception\
InvalidArgumentException(sprintf(
170 'Invalid type "%s" provided to setImageType()',
175 $this->imageType
= $value;
180 * Retrieve the image type to produce
184 public function getImageType()
186 return $this->imageType
;
190 * Initialize the image resource
194 protected function initRenderer()
196 $barcodeWidth = $this->barcode
->getWidth(true);
197 $barcodeHeight = $this->barcode
->getHeight(true);
199 if (null === $this->resource) {
200 $width = $barcodeWidth;
201 $height = $barcodeHeight;
202 if ($this->userWidth
&& $this->barcode
->getType() != 'error') {
203 $width = $this->userWidth
;
205 if ($this->userHeight
&& $this->barcode
->getType() != 'error') {
206 $height = $this->userHeight
;
209 // Cast width and height to ensure they are correct type for image
211 $width = (int) $width;
212 $height = (int) $height;
214 $this->resource = imagecreatetruecolor($width, $height);
216 $white = imagecolorallocate($this->resource, 255, 255, 255);
217 imagefilledrectangle($this->resource, 0, 0, $width - 1, $height - 1, $white);
220 $foreColor = $this->barcode
->getForeColor();
221 $this->imageForeColor
= imagecolorallocate(
223 ($foreColor & 0xFF0000) >> 16,
224 ($foreColor & 0x00FF00) >> 8,
225 $foreColor & 0x0000FF
228 $backgroundColor = $this->barcode
->getBackgroundColor();
229 $this->imageBackgroundColor
= imagecolorallocate(
231 ($backgroundColor & 0xFF0000) >> 16,
232 ($backgroundColor & 0x00FF00) >> 8,
233 $backgroundColor & 0x0000FF
236 // JPEG does not support transparency, if transparentBackground is true and
237 // image type is JPEG, ignore transparency
238 if ($this->getImageType() != "jpeg" && $this->transparentBackground
) {
239 imagecolortransparent($this->resource, $this->imageBackgroundColor
);
242 $this->adjustPosition(imagesy($this->resource), imagesx($this->resource));
244 imagefilledrectangle(
248 (int) ($this->leftOffset +
$barcodeWidth - 1),
249 (int) ($this->topOffset +
$barcodeHeight - 1),
250 $this->imageBackgroundColor
255 * Check barcode parameters
259 protected function checkSpecificParams()
261 $this->checkDimensions();
265 * Check barcode dimensions
267 * @throws Exception\RuntimeException
270 protected function checkDimensions()
272 if ($this->resource !== null) {
273 if (imagesy($this->resource) < $this->barcode
->getHeight(true)) {
274 throw new Exception\
RuntimeException(
275 'Barcode is define outside the image (height)'
279 if ($this->userHeight
) {
280 $height = $this->barcode
->getHeight(true);
281 if ($this->userHeight
< $height) {
282 throw new Exception\
RuntimeException(sprintf(
283 "Barcode is define outside the image (calculated: '%d', provided: '%d')",
290 if ($this->resource !== null) {
291 if (imagesx($this->resource) < $this->barcode
->getWidth(true)) {
292 throw new Exception\
RuntimeException(
293 'Barcode is define outside the image (width)'
297 if ($this->userWidth
) {
298 $width = $this->barcode
->getWidth(true);
299 if ($this->userWidth
< $width) {
300 throw new Exception\
RuntimeException(sprintf(
301 "Barcode is define outside the image (calculated: '%d', provided: '%d')",
311 * Draw and render the barcode with correct headers
315 public function render()
318 header("Content-Type: image/" . $this->imageType
);
319 $functionName = 'image' . $this->imageType
;
320 $functionName($this->resource);
322 ErrorHandler
::start(E_WARNING
);
323 imagedestroy($this->resource);
324 ErrorHandler
::stop();
328 * Draw a polygon in the image resource
330 * @param array $points
332 * @param bool $filled
334 protected function drawPolygon($points, $color, $filled = true)
336 $newPoints = [$points[0][0] +
$this->leftOffset
,
337 $points[0][1] +
$this->topOffset
,
338 $points[1][0] +
$this->leftOffset
,
339 $points[1][1] +
$this->topOffset
,
340 $points[2][0] +
$this->leftOffset
,
341 $points[2][1] +
$this->topOffset
,
342 $points[3][0] +
$this->leftOffset
,
343 $points[3][1] +
$this->topOffset
, ];
345 $allocatedColor = imagecolorallocate(
347 ($color & 0xFF0000) >> 16,
348 ($color & 0x00FF00) >> 8,
353 imagefilledpolygon($this->resource, $newPoints, 4, $allocatedColor);
355 imagepolygon($this->resource, $newPoints, 4, $allocatedColor);
360 * Draw a polygon in the image resource
362 * @param string $text
364 * @param array $position
365 * @param string $font
367 * @param string $alignment
368 * @param float|int $orientation
369 * @throws Exception\RuntimeException
371 protected function drawText($text, $size, $position, $font, $color, $alignment = 'center', $orientation = 0)
373 $allocatedColor = imagecolorallocate(
375 ($color & 0xFF0000) >> 16,
376 ($color & 0x00FF00) >> 8,
380 if ($font === null) {
383 $position[0] +
= $this->leftOffset
;
384 $position[1] +
= $this->topOffset
;
386 if (is_numeric($font)) {
389 * imagestring() doesn't allow orientation, if orientation
390 * needed: a TTF font is required.
391 * Throwing an exception here, allow to use automaticRenderError
392 * to inform user of the problem instead of simply not drawing
395 throw new Exception\
RuntimeException(
396 'No orientation possible with GD internal font'
399 $fontWidth = imagefontwidth($font);
400 $positionY = $position[1] - imagefontheight($font) +
1;
401 switch ($alignment) {
403 $positionX = $position[0];
406 $positionX = $position[0] - ceil(($fontWidth * strlen($text)) / 2);
409 $positionX = $position[0] - ($fontWidth * strlen($text));
412 imagestring($this->resource, $font, $positionX, $positionY, $text, $color);
414 if (! function_exists('imagettfbbox')) {
415 throw new Exception\
RuntimeException(
416 'A font was provided, but this instance of PHP does not have TTF (FreeType) support'
420 $box = imagettfbbox($size, 0, $font, $text);
421 switch ($alignment) {
426 $width = ($box[2] - $box[0]) / 2;
429 $width = ($box[2] - $box[0]);
436 $position[0] - ($width * cos(pi() * $orientation / 180)),
437 $position[1] +
($width * sin(pi() * $orientation / 180)),