Usually images are watermarked using a predefined color (let’s say for example “white”). How well does this actually work when you’re doing the watermark on a light or even a white image? The answer is simple: not very well.

This example illustrates how to use ImagickPixelIterator to get the average luminosity of the background and chosing text color according to it. I tested this algorithm very briefly and the results seemed positive. There’s four example images posted at the end of this post to show why background matters when doing a watermark.

Here is the code:

  1. <?php
  2.  
  3. /* Allowed images */
  4. $allowed = array( "strawberry.png", "Image32.png" );
  5. $img = ( isset( $_GET['img'] ) && in_array( $_GET['img'], $allowed ) )
  6.           ? $_GET['img'] : 'strawberry.png';
  7.  
  8. /* Read the image in. This image will be watermarked. */
  9. $image = new Imagick( $img  );
  10. $image->setImageFormat( "png" );
  11.  
  12. /* The text to write on the mark */
  13. $text = "www.valokuva.org";
  14.  
  15. /* This object will hold the font properties */
  16. $draw = new ImagickDraw();
  17.  
  18. /* Setting gravity to the center changes the origo
  19.         where annotation coordinates are relative to */
  20. $draw->setGravity( Imagick::GRAVITY_CENTER );
  21.  
  22. /* Use a custom truetype font */
  23. $draw->setFont( "./WCManoNegraBta.ttf" );
  24.  
  25. /* Set the font size */
  26. $draw->setFontSize( 26 );
  27.  
  28. /* Create a new imagick object */
  29. $im = new imagick();
  30.  
  31. /* Get the text properties */
  32. $properties = $im->queryFontMetrics( $draw, $text );
  33.  
  34. /* Region size for the watermark.
  35.         Add some extra space on the sides  */
  36. $watermark['w'] = intval( $properties["textWidth"] + 5 );
  37. $watermark['h'] = intval( $properties["textHeight"] + 5 );
  38.  
  39. /* Create a canvas using the font properties.
  40.         Add some extra space on width and height */
  41. $im->newImage( $watermark['w'], $watermark['h'],
  42.                     new ImagickPixel( "transparent" ) );
  43.  
  44. /* Get a region pixel iterator to get the pixels in the watermark area */
  45. $it = $image->getPixelRegionIterator( 0, 0, $watermark['w'], $watermark['h'] );
  46.  
  47. $luminosity = 0;
  48. $i = 0;
  49.  
  50. /* Loop trough rows */
  51. while( $row = $it->getNextIteratorRow() )
  52. {
  53.         /* Loop trough each column on the row */
  54.         foreach ( $row as $pixel )
  55.         {
  56.                 /* Get HSL values */
  57.                 $hsl = $pixel->getHSL();
  58.                 $luminosity += $hsl['luminosity'];
  59.                 $i++;
  60.         }
  61. }
  62.  
  63. /* If we are closer to white, then use black font and
  64.         the other way around */
  65. $textColor = ( ( $luminosity / $i ) > 0.5 ) ?
  66.                         new ImagickPixel( "black" ) :
  67.                         new ImagickPixel( "white" );
  68.  
  69. /* Use the same color for the shadow */
  70. $draw->setFillColor( $textColor );
  71.  
  72. /* Use png format */
  73. $im->setImageFormat( "png" );
  74.  
  75. /* Annotate some text on the image */
  76. $im->annotateImage( $draw, 0, 0, 0, $text );
  77.  
  78. /* Clone the canvas to create the shadow */
  79. $watermark = $im->clone();
  80.  
  81. /* Set the image bg color to black. (The color of the shadow) */
  82. $watermark->setImageBackgroundColor( $textColor );
  83.  
  84. /* Create the shadow (You can tweak the parameters
  85.         to produce "different" kind of shadows */
  86. $watermark->shadowImage( 80, 2, 2, 2 );
  87.  
  88. /* Composite the text on the background */
  89. $watermark->compositeImage( $im, Imagick::COMPOSITE_OVER, 0, 0 );
  90.  
  91. /* Composite the watermark on the image to the top left corner */
  92. $image->compositeImage( $watermark, Imagick::COMPOSITE_OVER, 0, 0 );
  93.  
  94. /* Display the results */
  95. header( "Content-Type: image/png" );
  96. echo $image;
  97.  
  98. ?>

Here is strawberry.png with black watermark (this was chosen by the script):
black

And here is strawberry.png with white watermark:
white

Image32.png with white watermark (this was chosen by the script):
white

Image32.png with black watermark:
black

P.S. I opened a new page for the Windows Imagick builds. Seems like my dynamic builds work pretty well, so I will keep providing them thru this site.