/** * {@inheritdoc} */ protected function validateArguments(array $arguments) { // Assure color is a valid hex string. if (!Color::validateHex($arguments['RGB'])) { throw new \InvalidArgumentException("Invalid color ('{$arguments['RGB']}') specified for the image 'colorshift' operation"); } return $arguments; }
/** * Convert a RGBA hex to its RGBA integer GD components. * * GD expects a value between 0 and 127 for alpha, where 0 indicates * completely opaque while 127 indicates completely transparent. * RGBA hexadecimal notation has #00 for transparent and #FF for * fully opaque. * * @param string $rgba_hex * A string specifing an RGBA color in the format '#RRGGBBAA'. * * @return array * An array with four elements for red, green, blue, and alpha. */ protected function hexToRgba($rgba_hex) { $rgbHex = Unicode::substr($rgba_hex, 0, 7); try { $rgb = Color::hexToRgb($rgbHex); $opacity = ColorUtility::rgbaToOpacity($rgba_hex); $alpha = 127 - floor($opacity / 100 * 127); $rgb['alpha'] = $alpha; return $rgb; } catch (\InvalidArgumentException $e) { return FALSE; } }
/** * Determine best match to over/underlay a defined color. * * Calculates UCCIR 601 luma of the entered color and returns a black or * white color to ensure readibility. * * @see http://en.wikipedia.org/wiki/Luma_video */ public static function matchLuma($rgba, $soft = FALSE) { $rgb = Unicode::substr($rgba, 0, 7); list($r, $g, $b) = array_values(Color::hexToRgb($rgb)); $luma = 1 - (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255; if ($luma < 0.5) { // Bright colors - black. $d = 0; } else { // Dark colors - white. $d = 255; } return Color::rgbToHex(array($d, $d, $d)); }
/** * Form element validation handler for #type 'color'. */ public static function validateColor(&$element, FormStateInterface $form_state, &$complete_form) { $value = trim($element['#value']); // Default to black if no value is given. // @see http://www.w3.org/TR/html5/number-state.html#color-state if ($value === '') { $form_state->setValueForElement($element, '#000000'); } else { // Try to parse the value and normalize it. try { $form_state->setValueForElement($element, ColorUtility::rgbToHex(ColorUtility::hexToRgb($value))); } catch (\InvalidArgumentException $e) { $form_state->setError($element, t('%name must be a valid color.', array('%name' => empty($element['#title']) ? $element['#parents'][0] : $element['#title']))); } } }
/** * {@inheritdoc} */ protected function execute(array $arguments) { // Get the image type. $type = $this->getToolkit()->extensionToImageType($arguments['extension']); // Store the original GD resource. $original_res = $this->getToolkit()->getResource(); // Create the resource. if (!($res = imagecreatetruecolor($arguments['width'], $arguments['height']))) { return FALSE; } // Fill the resource with transparency as possible. switch ($type) { case IMAGETYPE_PNG: imagealphablending($res, FALSE); $transparency = imagecolorallocatealpha($res, 0, 0, 0, 127); imagefill($res, 0, 0, $transparency); imagealphablending($res, TRUE); imagesavealpha($res, TRUE); break; case IMAGETYPE_GIF: if (empty($arguments['transparent_color'])) { // No transparency color specified, fill white. $fill_color = imagecolorallocate($res, 255, 255, 255); } else { $fill_rgb = Color::hexToRgb($arguments['transparent_color']); $fill_color = imagecolorallocate($res, $fill_rgb['red'], $fill_rgb['green'], $fill_rgb['blue']); imagecolortransparent($res, $fill_color); } imagefill($res, 0, 0, $fill_color); break; case IMAGETYPE_JPEG: imagefill($res, 0, 0, imagecolorallocate($res, 255, 255, 255)); break; } // Update the toolkit properties. $this->getToolkit()->setType($type); $this->getToolkit()->setResource($res); // Destroy the original resource if it is not needed by other operations. if (!$arguments['is_temp'] && is_resource($original_res)) { imagedestroy($original_res); } return TRUE; }
/** * {@inheritdoc} */ protected function validateArguments(array $arguments) { // PHP 5.5 GD bug: https://bugs.php.net/bug.php?id=65148: To prevent buggy // behavior on negative multiples of 90 degrees we convert any negative // angle to a positive one between 0 and 360 degrees. $arguments['degrees'] -= floor($arguments['degrees'] / 360) * 360; // Validate or set background color argument. if (!empty($arguments['background'])) { // Validate the background color: Color::hexToRgb does so for us. $background = Color::hexToRgb($arguments['background']) + array('alpha' => 0); } else { // Background color is not specified: use transparent white as background. $background = array('red' => 255, 'green' => 255, 'blue' => 255, 'alpha' => 127); } // Store the color index for the background as that is what GD uses. $arguments['background_idx'] = imagecolorallocatealpha($this->getToolkit()->getResource(), $background['red'], $background['green'], $background['blue'], $background['alpha']); if ($this->getToolkit()->getType() === IMAGETYPE_GIF) { // GIF does not work with a transparency channel, but can define 1 color // in its palette to act as transparent. // Get the current transparent color, if any. $gif_transparent_id = imagecolortransparent($this->getToolkit()->getResource()); if ($gif_transparent_id !== -1) { // The gif already has a transparent color set: remember it to set it on // the rotated image as well. $arguments['gif_transparent_color'] = imagecolorsforindex($this->getToolkit()->getResource(), $gif_transparent_id); if ($background['alpha'] >= 127) { // We want a transparent background: use the color already set to act // as transparent, as background. $arguments['background_idx'] = $gif_transparent_id; } } else { // The gif does not currently have a transparent color set. if ($background['alpha'] >= 127) { // But as the background is transparent, it should get one. $arguments['gif_transparent_color'] = $background; } } } return $arguments; }
/** * Gets the color set for transparency in GIF images. * * @return string|null * A color string like '#rrggbb', or NULL if not set or not relevant. */ public function getTransparentColor() { if (!$this->getResource() || $this->getType() != IMAGETYPE_GIF) { return NULL; } // Find out if a transparent color is set, will return -1 if no // transparent color has been defined in the image. $transparent = imagecolortransparent($this->getResource()); if ($transparent >= 0) { // Find out the number of colors in the image palette. It will be 0 for // truecolor images. $palette_size = imagecolorstotal($this->getResource()); if ($palette_size == 0 || $transparent < $palette_size) { // Return the transparent color, either if it is a truecolor image // or if the transparent color is part of the palette. // Since the index of the transparent color is a property of the // image rather than of the palette, it is possible that an image // could be created with this index set outside the palette size. // (see http://stackoverflow.com/a/3898007). $rgb = imagecolorsforindex($this->getResource(), $transparent); unset($rgb['alpha']); return Color::rgbToHex($rgb); } } return NULL; }
/** * {@inheritdoc} */ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { if (!$form_state->isValueEmpty('bgcolor') && !Color::validateHex($form_state->getValue('bgcolor'))) { $form_state->setErrorByName('bgcolor', $this->t('Background color must be a hexadecimal color value.')); } }
/** * {@inheritdoc} */ protected function execute(array $arguments) { $rgb = Color::hexToRgb($arguments['RGB']); return imagefilter($this->getToolkit()->getResource(), IMG_FILTER_COLORIZE, $rgb['red'], $rgb['green'], $rgb['blue']); }
/** * Tests Color::rgbToHex(). * * @param string $value * The rgb color value. * @param string $expected * The expected hex color value. * * @dataProvider providerTestRbgToHex */ public function testRgbToHex($value, $expected) { $this->assertSame($expected, Color::rgbToHex($value)); }