To call it as “photo tagging” is outright wrong, to be precise it should be called as image annotation or even sticky notes, which is the process of super-imposing a piece of information or data( called as tags) to a specific part of an image without changing the underlying image. You can have one or more tags for a single image. Most of us are already familiar with tags marked over group photos on social media sites, but this type of tagging information onto an image serves wider purpose. Annotation or Image tagging ( to sound familiar ) can be used in the following scenarios.

Demo

  • To highlight errors or provide some corrections, write comments or suggestions on any kind of design.
  • Can be helpful as a presentational markup.
  • Annotation on plans and designs will be helpful in remembering the concept and idea and discussing it further.
  • Markup on graphs and scientific images.
  • Name of people or person on photos. ( I bet you already know this he..he.. )

image-taggingAll right, my intent was to write a piece of software code with PHP and jQuery to annotate images, store them in database and retrieve them when a particular image is loaded. Then I came across various photo tagging scripts and plugins, some are too complex, some are simple but doesn’t have the expected feature. Here is what I came up with, a simple code without any plugin or complexity. But before getting into the code I would like to present a basic workflow on how image annotation works.

annotation-workflow

Now lets take a look into the code.  Here is the break-up of what is to be done.

  1. Present an image( it can be one within a gallery, or an image embedded in an article ).
  2. When the image has been loaded, we send an ajax request to retrieve the annotations for the particular image and load them if available.
  3. Setup interactivity for all the annotations with jQuery. So that each annotation appears only when mouse pointer moves over annotated or tagged area.
  4. Setup event handlers to create and remove annotations.

The PHP that presents the image to the user.

  <div id="container">
  <div id="imgtag"> 
    <?php 
    $sql = "SELECT * FROM picture WHERE id=1";
    $qry = mysql_query( $sql );
    $rs = mysql_fetch_array( $qry );
    ?>
    <img id="<?php echo $rs['id']; ?>" src="<?php echo $rs['name']; ?>" /> 
    <div id="tagbox">
    </div>
  </div> 
  <div id="taglist"> 
    <ol> 
    </ol> 
  </div> 
  </div>

Every image we insert into gallery or article will be given unique id, which will be used to retrieve the image. So you can see in the above code we construct a query with id=1, which is image id. You can make this dynamic by replacing the number with a variable or value from query string. We have also placed the image within a div name imgtag, along with 2 more div elements which will be used to place the annotation data. Now after presenting the image, the rest is taken care by jQuery.

jQuery Code for capturing the Click event on the image.

    $("#imgtag img").click(function(e) { // make sure the image is clicked
      var imgtag = $(this).parent(); // get the div to append the tagging list
      mouseX = ( e.pageX - $(imgtag).offset().left ) - 50; // x and y axis
      mouseY = ( e.pageY - $(imgtag).offset().top ) - 50;
      $( '#tagit' ).remove( ); // remove any tagit div first
      //insert an input box with save and cancel operations.
      $( imgtag ).append( '<div id="tagit"><div class="box"></div><div class="name"><div class="text">Type any name or tag</div><input type="text" name="txtname" id="tagname" /><input type="button" name="btnsave" value="Save" id="btnsave" /><input type="button" name="btncancel" value="Cancel" id="btncancel" /></div></div>' );
      $( '#tagit' ).css({ top:mouseY, left:mouseX });
      
      $('#tagname').focus();
    });

Now when the user clicks on the image, the above code will place an input box with save and cancel buttons, so user can enter the required tag or info to be saved. Clicking save after entering the tag will send an ajax request to save the tag. The following jQuery code will send the x and y position and the tag to the server.

    $( document ).on( 'click',  '#tagit #btnsave', function(){
        name = $('#tagname').val();
	var img = $('#imgtag').find( 'img' );
	var id = $( img ).attr( 'id' );
      $.ajax({
        type: "POST", 
        url: "savetag.php", 
        data: "pic_id=" + id + "&name=" + name + "&pic_x=" + mouseX + "&pic_y=" + mouseY + "&type=insert",
        cache: true, 
        success: function(data){
          viewtag( id );
          $('#tagit').fadeOut();
        }
      });
      
    });

The following PHP code will store the annotated area, that is x and y position and the user entered tag into database.

if( !empty( $_POST['type'] ) && $_POST['type'] == "insert" )
{
  $id = $_POST['pic_id'];  
  $name = $_POST['name'];
  $pic_x = $_POST['pic_x'];
  $pic_y = $_POST['pic_y'];
  $sql = "INSERT INTO image_tag (pic_id,name,pic_x,pic_y) VALUES ( $id, '$name', $pic_x, $pic_y )";
  $qry = mysql_query($sql);
}

Now we have successfully stored the tag in to the database. All we have to do is retrieve the X and Y position of the annotated area and the tags  associated with the image. You may have multiple annotations per image( e.g  a group photo or a natural scenery ), we must load them all. We will load two kinds of data here.

  1. Tag boxes with data to be placed over the image.
  2. The list of tags with an option to remove the tag.

jQuery code to retrieve the tags.

$.post( "taglist.php" ,  "pic_id=" + pic_id, function( data ) {
  	$('#taglist ol').html(data.lists);
	$('#tagbox').html(data.boxes);
}, "json");

You can see in the above code snippet, we are expecting a json object which contains two different data

  • boxes – those are the tag boxes to be place on the image.
  • lists – those are list with optional tag removing feature.

Now you take a look into the PHP code that sends json object.

$sql = "SELECT * FROM image_tag WHERE pic_id=" . $_POST[ 'pic_id' ] ;
$qry = mysql_query($sql);
$rs = mysql_fetch_array($qry);

$data['boxes'] = '';
$data['lists'] = '';

if ($rs){
  do{
	
    $data['boxes'] .= '<div class="tagview" style="left:' . $rs['pic_x'] . 'px;top:' . $rs['pic_y'] . 'px;" id="view_'.$rs['id'].'">';
	$data['boxes'] .= '<div class="square"></div>';
	$data['boxes'] .= '<div class="person" style="left:' . $rs['pic_x'] . 'px;top:' . $rs['pic_y']  . 'px;">' . $rs[ 'name' ] . '</div>';
	$data['boxes'] .= '</div>';
	
	$data['lists'] .= '<li id="'.$rs['id'].'"><a>' . $rs['name'] . '</a> (<a class="remove">Remove</a>)</li>';
	
  }while($rs = mysql_fetch_array($qry));
}

echo json_encode( $data );

In the above code we place the div in $data[‘boxes’] and lists in $data[‘lists’] and send it as a json object, we did this way so that we can eliminate two separate ajax requests for tag boxes and lists.

Now we have placed the tag boxes over the image, but it should not appear unless the user hovers the mouse over the image. the trick lies in the CSS code, we just set the opacity of the div to 0(zero), so that the div disappears completely. So when the user hover the mouse over the annotated/tagged area we set the opacity of the div to 1, so it appears. Here is the jQuery code that does the trick.

	// mouseover the tagboxes that is already there but opacity is 0.
	$( '#tagbox' ).on( 'mouseover', '.tagview', function( ) {
		var pos = $( this ).position();
		$(this).css({ opacity: 1.0 }); // div appears when opacity is set to 1.
	}).on( 'mouseout', '.tagview', function( ) {
		$(this).css({ opacity: 0.0 }); // hide the div by setting opacity to 0.
	});


So we have chained the mouseover and mouseout events which sets the opacity to 1 and 0 respectively for the tag boxes which has the class name “tagview“. we have done the same to capture the mouse hover on the lists, and display the tags accordingly. We also have implemented remove tag feature which basically sends an ajax request and removes the tag. You can download the full working code here. Hope you like it.

Demo

Updated code for current PHP versions: Download Image Tagging (706 downloads)

I was told that I wrote a horrible piece of code, though I have come a long way in my career after 10+ years, The code I provided was supposed to serve as a basic structure and not as a completed app or project, though I re wrote the code. Hope this code served that purpose. Pls leave your feedback in the comments.

Simple photo tagging with PHP and jQuery

12 thoughts on “Simple photo tagging with PHP and jQuery

  • at
    Permalink

    Hello friend,

    Well done , it is very beautiful example, i have already use it and i am very happy with it.

    I only have a question, when i add the tags i use full screen 100% view but if i change anything from that i loose the correct point from tag, do you have any suggestion how to fix this ?

    Thank you in advance.

    Best Regards,
    Tasos

    Reply
    • at
      Permalink

      Hi Tasos,

      I am glad that you liked it and thanks for the appreciation.
      Tags are placed based on the original image size, to retain the tag position when we resize the image (responsive pages), we need to recalculate the image tag positions based on the image size after it has been resized.
      I have done this already, I didn’t update though, kind of lost interest after the site didn’t receive much attention.

      Regards
      Pelister

      Reply
  • at
    Permalink

    Hello Dear Pelister,

    Thank you very much for you’re time for replace to me.

    I am so sorry for you’re lost interest. 🙁

    Could you please give an idea how to do it because i have no experience, try some info found for resize the image but no one working correct.

    Thank you in advance.

    Best Regards,
    Tasos

    Reply
    • at
      Permalink

      Hi Tasos,

      To adjust the tag positions on a resized image we need to calculate the new x,y position of the tags based on how much the image has been resized.

      say for example we have 1000 pixel image and you have set the marker on the original (100%) size , when the image is loaded on a resized window,
      say for example the image has been resized to 600px.

      then you can do as follows

      currW = $( img ).width( );
      currH = $( img ).height( );
      imgW = $( img )[0].naturalWidth; /* original Width of the image */
      imgH = $( img )[0].naturalHeight; /* original Height of the image */

      now you can calculate the marker position as follows

      picx = Math.round( (( currW / imgW ) * picx ));
      picy = Math.round( (( currH / imgW ) * picy ));

      ( currW / imgW ) will give you how much percent the image has been resized, and you can calculate the marker position based on it.

      you can calculate the tag positions in window resize event to adjust the tag position automatically whenever the window was resized.
      you will have to keep the original x,y position of the marker to calculate the new position every time. you can store the original x,y position in a json object for the purpose.

      Reply
      • at
        Permalink

        Dear Pelister,

        You are amazing and fantastic person ! ! !

        Thank you very very much for your time and your valuable help ! ! !

        God bless you ! ! !

        Have a nice day ! ! !

        Best Regards,
        Tasos

        Reply
          • at
            Permalink

            Dear Pelister,

            Yes my good friend and now works Perfect 🙂

            I try to add what i did it but the site blocks me .

            Because of you ! ! !

            Thank you very very much, my good friend ! ! !

            God bless you ! ! !

            Best Regards,
            Tasos

          • at
            Permalink

            Glad, you got it working, comment system blocks the scripts in the comments usually.

            Thank You and have a great time

          • at
            Permalink

            Hi Tasos, I have updated the code and interface for responsive images. Download and have fun.

  • at
    Permalink

    Dear Pelister,

    I use you’re code and now works Perfect 🙂

    Because of you ! ! !

    Thank you very very much, my good friend ! ! !

    God bless you ! ! !

    Best Regards,
    Tasos

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *