22.07.2014

Context sensitive watermarks


Just recently I published at stackoverflow a method for context sensitive watermarks – eg white on black and black on white background.
First, I started with blurring the picture before measuring image color at the target area. But blurring is not necessary, as we can average pixel brightness at a later stage. It was much better to convert RGB values directly into perceived brightness where the cutpoint between white and black text will be set around 122 which is halfway down between 0 and 255.
The brightness formula came from nbdtech and the final code used at this site is being

$bright = array();
/* sampling brightness along a line running from $x1,$y to $x2,$y */
for ($i = $x1; $i < $x2; $i += 5) {
  $rgb = imagecolorat($img, $i, $y);
  $r = ($rgb >> 16) & 0xFF; $g = ($rgb >> 8) & 0xFF; $b = $rgb & 0xFF;
  $bright[] = intval( sqrt(  0.241*$r*$r + 0.691*$g*$g + 0.068*$b*$b ) );
}
/* calculcate median brightness */
rsort($bright);
$middle = round(count($bright) / 2);
$m = $bright[$middle-1];
/* $cw then contains the watermark color */
$m<122 ? $cw= imagecolorallocatealpha($img, 255, 255, 255, 80) : $cw = imagecolorallocatealpha($img,0, 0, 0, 80);

Can be put into a function and be called before any text is written to the picture with imagettftext.

Imagemagick is a bit more powerful than GD. A much longer script fromĀ www.navioo.com does it pixelwise and is a bit more advanced than my solution

$image = new Imagick( $img  ); 
$image->setImageFormat( "png" ); 
$text = "wjst.de"; 
$draw = new ImagickDraw(); 
$draw->setGravity( Imagick::GRAVITY_CENTER ); 
$draw->setFont( "./WCManoNegraBta.ttf" ); 
$draw->setFontSize( 26 ); 
$im = new imagick(); 
$properties = $im->queryFontMetrics( $draw, $text ); 
$watermark['w'] = intval( $properties["textWidth"] + 5 ); 
$watermark['h'] = intval( $properties["textHeight"] + 5 ); 
$im->newImage( $watermark['w'], $watermark['h'], new ImagickPixel( "transparent" ) ); 
$it = $image->getPixelRegionIterator( 0, 0, $watermark['w'], $watermark['h'] ); 
$luminosity = 0; 
$i = 0; 
while( $row = $it->getNextIteratorRow() ) { 
  foreach ( $row as $pixel ) { 
    $hsl = $pixel->getHSL(); 
    $luminosity += $hsl['luminosity']; 
    $i++; 
  } 
} 
$textColor = ( ( $luminosity / $i )> 0.5 ) ? new ImagickPixel( "black" ) : new ImagickPixel( "white" );
$draw->setFillColor( $textColor );
$im->setImageFormat( "png" );
$im->annotateImage( $draw, 0, 0, 0, $text ); 
$watermark = $im->clone();
$watermark->setImageBackgroundColor( $textColor );
$watermark->shadowImage( 80, 2, 2, 2 );
$watermark->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 );
$image->compositeImage( $watermark, Imagick::COMPOSITE_OVER, 0, 0 );