1 <?php
2 /**
3 * @package Joomla.Platform
4 * @subpackage Image
5 *
6 * @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 */
9
10 defined('JPATH_PLATFORM') or die;
11
12 /**
13 * Image Filter class fill background with color;
14 *
15 * @package Joomla.Platform
16 * @subpackage Image
17 * @since 3.4
18 */
19 class JImageFilterBackgroundfill extends JImageFilter
20 {
21 /**
22 * Method to apply a background color to an image resource.
23 *
24 * @param array $options An array of options for the filter.
25 * color Background matte color
26 *
27 * @return void
28 *
29 * @since 3.4
30 * @throws InvalidArgumentException
31 */
32 public function execute(array $options = array())
33 {
34 // Validate that the color value exists and is an integer.
35 if (!isset($options['color']))
36 {
37 throw new InvalidArgumentException('No color value was given. Expected string or array.');
38 }
39
40 $colorCode = (!empty($options['color'])) ? $options['color'] : null;
41
42 // Get resource dimensions
43 $width = imagesX($this->handle);
44 $height = imagesY($this->handle);
45
46 // Sanitize color
47 $rgba = $this->sanitizeColor($colorCode);
48
49 // Enforce alpha on source image
50 if (imageIsTrueColor($this->handle))
51 {
52 imageAlphaBlending($this->handle, false);
53 imageSaveAlpha($this->handle, true);
54 }
55
56 // Create background
57 $bg = imageCreateTruecolor($width, $height);
58 imageSaveAlpha($bg, empty($rgba['alpha']));
59
60 // Allocate background color.
61 $color = imageColorAllocateAlpha($bg, $rgba['red'], $rgba['green'], $rgba['blue'], $rgba['alpha']);
62
63 // Fill background
64 imageFill($bg, 0, 0, $color);
65
66 // Apply image over background
67 imageCopy($bg, $this->handle, 0, 0, 0, 0, $width, $height);
68
69 // Move flattened result onto curent handle.
70 // If handle was palette-based, it'll stay like that.
71 imageCopy($this->handle, $bg, 0, 0, 0, 0, $width, $height);
72
73 // Free up memory
74 imageDestroy($bg);
75
76 return;
77 }
78
79 /**
80 * Method to sanitize color values
81 * and/or convert to an array
82 *
83 * @param mixed $input Associative array of colors and alpha,
84 * or hex RGBA string when alpha FF is opaque.
85 * Defaults to black and opaque alpha
86 *
87 * @return array Associative array of red, green, blue and alpha
88 *
89 * @since 3.4
90 *
91 * @note '#FF0000FF' returns an array with alpha of 0 (opaque)
92 */
93 protected function sanitizeColor($input)
94 {
95 // Construct default values
96 $colors = array('red' => 0, 'green' => 0, 'blue' => 0, 'alpha' => 0);
97
98 // Make sure all values are in
99 if (is_array($input))
100 {
101 $colors = array_merge($colors, $input);
102 }
103 // Convert RGBA 6-9 char string
104 elseif (is_string($input))
105 {
106 $hex = ltrim($input, '#');
107
108 $hexValues = array(
109 'red' => substr($hex, 0, 2),
110 'green' => substr($hex, 2, 2),
111 'blue' => substr($hex, 4, 2),
112 'alpha' => substr($hex, 6, 2),
113 );
114
115 $colors = array_map('hexdec', $hexValues);
116
117 // Convert Alpha to 0..127 when provided
118 if (strlen($hex) > 6)
119 {
120 $colors['alpha'] = floor((255 - $colors['alpha']) / 2);
121 }
122 }
123 // Cannot sanitize such type
124 else
125 {
126 return $colors;
127 }
128
129 // Make sure each value is within the allowed range
130 foreach ($colors as &$value)
131 {
132 $value = max(0, min(255, (float) $value));
133 }
134
135 $colors['alpha'] = min(127, $colors['alpha']);
136
137 return $colors;
138 }
139 }
140