Permalink
Browse files

handle transparency

  • Loading branch information...
1 parent a88d3b9 commit af2041b9553d3332a45d5dff373982108e374807 @MatTheCat MatTheCat committed Mar 24, 2016
View
@@ -48,6 +48,21 @@ $colors = $extractor->extract(5);
```
+## Handling transparency
+
+By default **any pixel with alpha value greater than zero will be discarded**. This is because transparent colors are not perceived
+as is. For exemple fully transparent black would be seen white on a white background. So if you want to take transparency into account
+when building a palette you have to specify this background color. You can do this with the second argument of `Palette` constructors.
+Its default value is `null`, meaning a color won't be added to the palette if its alpha component exists and is greater than zero.
+
+You can set it as an integer representing the color, then transparent colors will be blended before addition to the palette.
+
+```php
+// we set a white background so fully transparent colors will be added as white in the palette
+// pure red #FF0000 at 50% opacity will be stored as #FF8080 as it would be perceived
+$palette = Palette::fromFilename('./some/image.png', Color::fromHexToInt('#FFFFFF'));
+```
+
## Contributing
Please see [CONTRIBUTING](https://github.com/thephpleague/color-extractor/blob/master/CONTRIBUTING.md) for details.
@@ -44,27 +44,35 @@ public function getMostUsedColors($limit = null)
}
/**
- * @param string $filename
+ * @param string $filename
+ * @param int|null $backgroundColor
*
* @return Palette
*/
- public static function fromFilename($filename)
+ public static function fromFilename($filename, $backgroundColor = null)
{
- return self::fromGD(imagecreatefromstring(file_get_contents($filename)));
+ return self::fromGD(
+ imagecreatefromstring(file_get_contents($filename)),
+ $backgroundColor
+ );
}
/**
* @param resource $image
+ * @param int|null $backgroundColor
*
* @return Palette
*
* @throws \InvalidArgumentException
*/
- public static function fromGD($image)
+ public static function fromGD($image, $backgroundColor = null)
{
if (!is_resource($image) || get_resource_type($image) != 'gd') {
throw new \InvalidArgumentException('Image must be a gd resource');
}
+ if ($backgroundColor !== null && (!is_numeric($backgroundColor) || $backgroundColor < 0 || $backgroundColor > 16777215)) {
+ throw new \InvalidArgumentException(sprintf('"%s" does not represent a valid color', $backgroundColor));
+ }
$palette = new self();
@@ -73,12 +81,30 @@ public static function fromGD($image)
$imageHeight = imagesy($image);
$palette->colors = [];
+ $backgroundColorRed = ($backgroundColor >> 16) & 0xFF;
+ $backgroundColorGreen = ($backgroundColor >> 8) & 0xFF;
+ $backgroundColorBlue = $backgroundColor & 0xFF;
+
for ($x = 0; $x < $imageWidth; ++$x) {
for ($y = 0; $y < $imageHeight; ++$y) {
$color = imagecolorat($image, $x, $y);
if ($areColorsIndexed) {
$colorComponents = imagecolorsforindex($image, $color);
- $color = ($colorComponents['red'] * 65536) + ($colorComponents['green'] * 256) + ($colorComponents['blue']);
+ $color = ($colorComponents['alpha'] * 16777216) +
+ ($colorComponents['red'] * 65536) +
+ ($colorComponents['green'] * 256) +
+ ($colorComponents['blue']);
+ }
+
+ if ($alpha = $color >> 24) {
+ if ($backgroundColor === null) {
+ continue;
+ }
+
+ $alpha /= 127;
+ $color = (int) (($color >> 16 & 0xFF) * (1 - $alpha) + $backgroundColorRed * $alpha) * 65536 +
+ (int) (($color >> 8 & 0xFF) * (1 - $alpha) + $backgroundColorGreen * $alpha) * 256 +
+ (int) (($color & 0xFF) * (1 - $alpha) + $backgroundColorBlue * $alpha);
}
isset($palette->colors[$color]) ?
@@ -2,6 +2,7 @@
namespace League\ColorExtractor\Test;
+use League\ColorExtractor\Color;
use League\ColorExtractor\ColorExtractor;
use League\ColorExtractor\Palette;
@@ -10,6 +11,7 @@ class PaletteTest extends \PHPUnit_Framework_TestCase
protected $jpegPath = './tests/assets/test.jpeg';
protected $gifPath = './tests/assets/test.gif';
protected $pngPath = './tests/assets/test.png';
+ protected $transparentPngPath = './tests/assets/red-transparent-50.png';
public function testJpegExtractSingleColor()
{
@@ -51,4 +53,15 @@ public function testJpegExtractMultipleColors()
$this->assertCount($numColors, $colors);
$this->assertEquals($colors, [14024704, 3407872, 7111569]);
}
+
+ public function testTransparencyHandling()
+ {
+ $this->assertCount(0, Palette::fromFilename($this->transparentPngPath));
+
+ $whiteBackgroundPalette = Palette::fromFilename($this->transparentPngPath, Color::fromHexToInt('#FFFFFF'));
+ $this->assertEquals(iterator_to_array($whiteBackgroundPalette), [Color::fromHexToInt('#FF8080') => 1]);
+
+ $blackBackgroundPalette = Palette::fromFilename($this->transparentPngPath, Color::fromHexToInt('#000000'));
+ $this->assertEquals(iterator_to_array($blackBackgroundPalette), [Color::fromHexToInt('#7E0000') => 1]);
+ }
}
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 af2041b

Please sign in to comment.