Watermark Images with Other Images and Text on the Fly

Discussion in 'PHP' started by shabbir, May 15, 2010.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Let us say you have some images and want to watermark those images with some other gif, jpeg, png images or with some plain text on the fly in PHP.

    It actually looks tough but it is very simple. Let us take a real time example of profile picture option we have here at Go4Expert.com where if you visit the contact info tab of your profile you will see a code as follow.

    HTML:
    <A rel="nofollow" HREF="http://www.go4expert.com/member.php?u=1"><IMG SRC="http://www.go4expert.com/share/member1.jpg" WIDTH="120" HEIGHT="90" BORDER="0" ALT="shabbir's Profile at Go4Expert.com"></A>
    And the output will be something like

    [​IMG]

    But actually it is this image

    [​IMG]

    Which converts into

    [​IMG]

    Now let us see how.

    Requirements



    PHP 4+ and GD 2.0+.

    Code



    PHP:
    $im imagecreatefromjpeg($baseimg); 
    It loads the file into the PHP script using the GD library and gives us the opportunity to manipulate and/or output the image using our script.

    We define variables for color and fonts which we will use to output the final text on the base image.
    PHP:
    $text_color[0] = imagecolorallocate($im2552550);
    $text_color[1] = imagecolorallocate($im192192192);
    $text_color[2] = imagecolorallocate($im255255255);
    $text_color[3] = imagecolorallocate($im255255255);

    $font[0] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[1] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[2] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[3] = DIR .'/images/user/fonts/arialbd.ttf';
    If we already have an image for the user we should check for last updated time and if it is less than a day we just use the existing image and do not update the image with latest information. This is done to cache the image for a day and is updated every 24 hours.
    PHP:
        $finalimg './advprofilepic/member'.$userid.'.jpg';

        if(
    file_exists($finalimg))
        {
            
    $cachetime TIMENOW 86400;
            if(
    $cachetime filemtime($finalimg))
            {
                
    header('Content-type: image/jpg');
                
    readfile($finalimg);
                exit;
            }
        }
    Next we test for a user uploaded profile picture. If user has uploaded a profile picture we need to use the profile picture in our final image and depending on the uploaded image format we create the profile image from the file and then using imagecopyresampled we merge the two images at the desired locations.
    PHP:
        // We have access to the linked image file
        
    if (file_exists($profilepicurl))
        {
            list(
    $width$height$image_type$attr) = getimagesize($profilepicurl);
            
    $max_width 32;
            
    $max_height 32;
            if(
    $width $height)
            {
                
    $width $height;
            }
            elseif(
    $width $height)
            {
                
    $height $width;
            }
            
    $profileim imagecreatetruecolor($max_width,$max_height);
            
    $bg_color imagecolorallocate ($profileim0,0,0); //background white
            
    imagefilledrectangle ($profileim00$max_width$max_height$bg_color);
            switch (
    $image_type)
            {
                case 
    1$profileim imagecreatefromgif($userinfo['profilepicurl']); break;
                case 
    2$profileim imagecreatefromjpeg($userinfo['profilepicurl']);  break;
                case 
    3$profileim imagecreatefrompng($userinfo['profilepicurl']); break;
                default:  
    trigger_error('Unsupported filetype!'E_USER_WARNING);  break;
            }
            
    imagecopyresampled($im$profileim53500$max_width$max_height$width$height); // copy empty banner
            
    imagedestroy($profileim);
        }
    Now we place few strings of user text at desired location.
    PHP:
        $text "Posts at";
        if(
    function_exists('imagettftext'))
        {
            
    imagettftext($im120$left$top$text_color[0], $font[0], $username);
            
    imagettftext($im80$left$top+$linespacing$text_color[1], $font[1], $usertitle);
            
    imagettftext($im100$leftcounter$topcounter$text_color[2], $font[2], number_format($posts));
            
    imagettftext($im100$leftcounter$topcounter $linespacing$text_color[3], $font[3], $text);
        }
    All done now out output the final image
    PHP:
    imagepng($im,$finalimg);
    header('Cache-control: max-age=86400');
    header('Expires: ' gmdate('D, d M Y H:i:s', (TIMENOW 86400)) . ' GMT');
    header('Content-disposition: inline; filename=' $username '.png');
    header('Content-transfer-encoding: binary');
    header("Content-type: image/png");
    imagepng($im);
    imagedestroy($im);

    Complete Code



    PHP:
    <?php
    $left 
    4//Left text-margin
    $top 15//text-margin from top
    $leftcounter 44;
    $topcounter 48;
    $linespacing 12;
    $baseimg './images/user/base.jpg';  //full path to empty input image
    $finalimg './advprofilepic/member0.jpg';

    $im imagecreatefromjpeg($baseimg); 

    $text_color[0] = imagecolorallocate($im2552550);
    $text_color[1] = imagecolorallocate($im192192192);
    $text_color[2] = imagecolorallocate($im255255255);
    $text_color[3] = imagecolorallocate($im255255255);

    $font[0] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[1] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[2] = DIR .'/images/user/fonts/arialbd.ttf';
    $font[3] = DIR .'/images/user/fonts/arialbd.ttf';

    if(
    $userid <> 0)
    {
        
    $finalimg './advprofilepic/member'.$userid.'.jpg';

        if(
    file_exists($finalimg))
        {
            
    $cachetime TIMENOW 86400;
            if(
    $cachetime filemtime($finalimg))
            {
                
    header('Content-type: image/jpg');
                
    readfile($finalimg);
                exit;
            }
        }

        
    // We have access to the linked image file
        
    if (file_exists($profilepicurl))
        {
            list(
    $width$height$image_type$attr) = getimagesize($profilepicurl);
            
    $max_width 32;
            
    $max_height 32;
            if(
    $width $height)
            {
                
    $width $height;
            }
            elseif(
    $width $height)
            {
                
    $height $width;
            }
            
    $profileim imagecreatetruecolor($max_width,$max_height);
            
    $bg_color imagecolorallocate ($profileim0,0,0); //background white
            
    imagefilledrectangle ($profileim00$max_width$max_height$bg_color);
            switch (
    $image_type)
            {
                case 
    1$profileim imagecreatefromgif($userinfo['profilepicurl']); break;
                case 
    2$profileim imagecreatefromjpeg($userinfo['profilepicurl']);  break;
                case 
    3$profileim imagecreatefrompng($userinfo['profilepicurl']); break;
                default:  
    trigger_error('Unsupported filetype!'E_USER_WARNING);  break;
            }
            
    imagecopyresampled($im$profileim53500$max_width$max_height$width$height); // copy empty banner
            
    imagedestroy($profileim);
        }

        
    $text "Posts at";
        if(
    function_exists('imagettftext'))
        {
            
    imagettftext($im120$left$top$text_color[0], $font[0], $username);
            
    imagettftext($im80$left$top+$linespacing$text_color[1], $font[1], $usertitle);
            
    imagettftext($im100$leftcounter$topcounter$text_color[2], $font[2], number_format($posts));
            
    imagettftext($im100$leftcounter$topcounter $linespacing$text_color[3], $font[3], $text);
        }
    }
    imagepng($im,$finalimg);
    header('Cache-control: max-age=86400');
    header('Expires: ' gmdate('D, d M Y H:i:s', (TIMENOW 86400)) . ' GMT');
    header('Content-disposition: inline; filename=' $username '.png');
    header('Content-transfer-encoding: binary');
    header("Content-type: image/png");
    imagepng($im);
    imagedestroy($im);
    ?>
    The above solution can also be used to watermark the images because standard watermarking procedure of editing the image in a photo-editing application is very time consuming and PHP offers better solution.

    You can use the above method to loop through an entire directory to watermark all images in one go.

    Possibilities are endless.
     
    Last edited: Jan 21, 2017
  2. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Darkness_inside likes this.
  3. pkphp

    pkphp New Member

    Joined:
    Sep 20, 2010
    Messages:
    7
    Likes Received:
    0
    Trophy Points:
    0
    Home Page:
    http://www.phpkode.com
    well. that's realllly what i need. thank you very much for your share.
     
  4. Darkness_inside

    Darkness_inside New Member

    Joined:
    Apr 20, 2011
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Mbbs
  5. learner guy

    learner guy New Member

    Joined:
    Aug 2, 2011
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    aoa sir,
    this script is for the profile pic of go4expert.com
    can i get a generalized code ....which i can use to create my water mark app.
    plz tell me what modifications i have to do
    waiting for reply ,
    regards,
    fasi khan
     
  6. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Fasi Khan, this is general script with example taken from is go4expert.com
     
  7. jhon786

    jhon786 New Member

    Joined:
    Oct 12, 2011
    Messages:
    46
    Likes Received:
    0
    Trophy Points:
    0
    Thanks for shearing this useful information.
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice