Enhance GD::greyscale to allow darker or lighter results, and change color weights for greyscale (#5332)

Tweaking the first three parameters (R, G, B) allows you to get a different mix of colors into grey, but it does not allow you to make the result lighter or darker because their total is normalized. This is quite a common operation on greyscaled images though, so I added a fourth parameter: brightness. It defaults to 100% so that it does not have any effect when not used (making this backwards compatible). $brightness = 50 will make it darker, $brightness = 150 will overlight it.
This commit is contained in:
JorisDebonnet 2016-04-21 09:26:46 +02:00 committed by Sam Minnée
parent 4f14175022
commit 9eac541740
2 changed files with 18 additions and 13 deletions

View File

@ -486,14 +486,16 @@ class GDBackend extends Object implements Image_Backend {
}
/**
* Make the image greyscale
* $rv = red value, defaults to 38
* $gv = green value, defaults to 36
* $bv = blue value, defaults to 26
* Based (more or less entirely, with changes for readability) on code from
* http://www.teckis.com/scriptix/thumbnails/teck.html
* Make the image greyscale.
* Default color weights are based on standard BT.601 (those used in PAL, NTSC and many software packages, also see
* https://en.wikipedia.org/wiki/Grayscale#Luma_coding_in_video_systems )
*
* $R = red weight, defaults to 299
* $G = green weight, defaults to 587
* $B = blue weight, defaults to 114
* $brightness = brightness in percentage, defaults to 100
*/
public function greyscale($rv=38, $gv=36, $bv=26) {
public function greyscale($R=299, $G=587, $B=114, $brightness=100) {
$width = $this->width;
$height = $this->height;
$newGD = imagecreatetruecolor($this->width, $this->height);
@ -502,15 +504,18 @@ class GDBackend extends Object implements Image_Backend {
imagealphablending($newGD, false);
imagesavealpha($newGD, true);
$rt = $rv + $bv + $gv;
$rr = ($rv == 0) ? 0 : 1/($rt/$rv);
$br = ($bv == 0) ? 0 : 1/($rt/$bv);
$gr = ($gv == 0) ? 0 : 1/($rt/$gv);
$rt = $R + $G + $B;
// if $rt is 0, bad parameters are provided, so result will be a black image
$rr = $rt ? $R/$rt : 0;
$gr = $rt ? $G/$rt : 0;
$br = $rt ? $B/$rt : 0;
// iterate over all pixels and make them grey
for($dy = 0; $dy < $height; $dy++) {
for($dx = 0; $dx < $width; $dx++) {
$pxrgb = imagecolorat($this->gd, $dx, $dy);
$heightgb = ImageColorsforIndex($this->gd, $pxrgb);
$newcol = ($rr*$heightgb['red']) + ($br*$heightgb['blue']) + ($gr*$heightgb['green']);
$newcol = min(255, $newcol*$brightness/100);
$setcol = ImageColorAllocateAlpha($newGD, $newcol, $newcol, $newcol, $heightgb['alpha']);
imagesetpixel($newGD, $dx, $dy, $setcol);
}

View File

@ -91,8 +91,8 @@ class GDTest extends SapphireTest {
}
// check various sample points
$this->assertColourEquals(96, $samples[0]['red'], $tolerance);
$this->assertColourEquals(91, $samples[2]['red'], $tolerance);
$this->assertColourEquals(76, $samples[0]['red'], $tolerance);
$this->assertColourEquals(149, $samples[2]['red'], $tolerance);
$this->assertColourEquals(0, $samples[8]['red'], $tolerance);
$this->assertColourEquals(127, $samples[9]['red'], $tolerance);