Click here to Skip to main content
Click here to Skip to main content

Facebook Style Photo Tag

By , 20 Jun 2011
 

Introduction

You know how in Facebook, you can Tag images like this:

fbTag.jpg

How can this be done in .NET ?

BreakDown

We'll have to divide this feature into a number of components:

  1. Select an area
  2. A list of friends is shown
  3. After selecting a friend, a label with friends name is added
  4. Friend name is removed from list (step 2)
  5. Image is now marked with the friends name where you selected
  6. On hovering the label with friend name, area from step(1) is selected

For steps (1) and (6), we will use Michal Wojciechowski's imgAreaSelect.

We'll get into that shortly, first let's examine the database.

ERD

ERD.jpg

vTags.jpg

tPhoto 

Nothing special here, holds the photo name, id and path.

tFriend

we need a boolean to tell us whether the friend has been tagged already or not, so he won't be shown again in the list (step number 2).

tTag

Holds the data about areas position in the photo, and Id of tagged person.

In real life the tables are more complex, where a friend can be tagged in more than one photo and a photo can have more than one friend tagged, this is simplified for the sake of demonstration.

vTag
The view displaying the tagged friends, the special field here is Coords, which is areas' positions(from tTag,x1,y1,x2,y2) concatenated together ,we'll need that later 

How to Use the Code

This is the JavaScript function imgAreaSelect(), notice it's bound to our asp:Image control, Image1, it magically frames the area we selected based on image name.

our image control name in run-time is MainContent_Image1 , that's the one we'll use. 

$(function () {
            $('#MainContent_Image1').imgAreaSelect({ aspectRatio: '1:1', handles: true,
                fadeSpeed: 200, onSelectChange: Select, onSelectEnd: DisplayFriends
            });
        });        

We have 4 hidden fields in the page, we need those to store the positions of area selected.

Now, this function fires the onSelectEnd event, which calls the function Select(), it simply populates the hidden fields.

function Select(img, selection) {
if (!selection.width || !selection.height)
return;
document.getElementById('<%=x1.ClientID %>').value = selection.x1;
document.getElementById('<%=y1.ClientID %>').value = selection.y1;
document.getElementById('<%=x2.ClientID %>').value = selection.x2;
document.getElementById('<%=y2.ClientID %>').value = selection.y2;
}  

... and on the onSelectEnd event, we'll call our DisplayFriends() method.

dvFriends is a div containing a datalist populated with our untagged friends (initially hidden of course).

function DisplayFriends(img, selection) {
if (!selection.width || !selection.height || 
	document.getElementById('<%=HFShowFriends.ClientID %>').value == "0")
return;
document.getElementById('<%=dvFriends.ClientID %>').style.display = "block";
}    

When user selects a friend, it will fire the function SelectEnd() which ends the selection process.

function SelectEnd() {
$('#MainContent_Image1').imgAreaSelect({ hide: true });
}  

Nice, now we need to actually tag the image (where you hover on photo and see a tool tip displaying the friend's name).

To do this, we'll use an HTML map.

AddNewArea() function takes the newly created tTag object and adds a new area to the map.

private void AddNewArea(tTag t)
{
    HtmlGenericControl gcArea = new HtmlGenericControl("area");
    gcArea.Attributes.Add("shape", "rect");
    gcArea.Attributes.Add("href", "#");
    string strFriendName = Friends.GetFriendName(t.nFriendId);
    gcArea.Attributes.Add("id", "a" + t.nFriendId.ToString());
    gcArea.Attributes.Add("title", strFriendName);
    gcArea.Attributes.Add("alt", strFriendName);
    gcArea.Attributes.Add("coords", GenerateCoordiantes(t));
    mapPhoto.Controls.Add(gcArea);
}

(Note: In case of using Mozilla Firefox 5.0 or Safari 5.0.3, the tagging effect does not work until after refreshing the whole page.)

Very good, now we need the area to be selected again on hovering the links, which are actually ItemTemplates inside a datalist. 

<asp:DataList ID="dlTaggedFriends" runat="server" RepeatDirection="Horizontal" 
DataSourceID="sdsTags"
ViewStateMode="Disabled">
<ItemTemplate>
<asp:LinkButton ID="lbName" runat="server" onmouseout="SelectEnd()" 
onmouseover='<%#Eval("Coords","preview(\"{0}\");")%>'
Text='<%# Eval("sName") %>'></asp:LinkButton>
(<asp:LinkButton ID="lbRemoveTag" runat="server" 
CommandArgument='<%# Eval("nFriendId") %>'
OnCommand="lbRemoveTag_Command1">remove</asp:LinkButton>)
<asp:Literal ID="Literal1" runat="server"></asp:Literal>
</ItemTemplate>
</asp:DataList>

The DatasourceId of datalist dlTaggedFriends , is SqlDataSource sdsTags , which is bound to the view vTag  

vTagsData.jpg 

That's why we concatenated the positions, to pass them as one parameter to the javascript function  preview() on  onmouseover event, where they'll be spitted again . 

function preview(Coords) {
            var arrResult = Coords.split(",");
            var nx1 = arrResult[0];
            var ny1 = arrResult[1];
            var nx2 = arrResult[2];
            var ny2 = arrResult[3];
            var ias = $('#MainContent_Image1').imgAreaSelect({ instance: true });
            ias.setSelection(nx1, ny1, nx2, ny2, true);
            ias.setOptions({ show: true });
            ias.update();
} 

Output

Example.jpg

Drawbacks

  • The tagging effect does not work until after refreshing the whole page when using Mozilla Firefox 5.0 or Safari 5.0.3.

Future Work

  • Free hand selection (instead of rectangle)

Conclusion

  • Tested on Internet Explorer 8, Google Chrome 10.0.6, Mozilla Firefox 5.0 and Safari 5.0.3
  • Feel free to post any questions, modifications, comments

History

  • 20th March, 2011: Initial post 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Omar Gameel Salem
Software Developer
Egypt Egypt
Member
Enthusiastic programmer/researcher, passionate to learn new technologies, interested in problem solving,data structures, algorithms and automation.
 
If you have a question\suggestion about one of my articles, or you want an algorithm implemented in C#, feel free to contact me.
 
Résumé
 
vWorker Account

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionGood!!memberPrimillo21 Feb '13 - 20:51 
Very helpfull
Questionshowing error [modified]membernephy k7 Sep '12 - 6:16 
tTag is showing error...reference cannot be found...please help me..its urgent

modified 10 Sep '12 - 2:07.

QuestionHow to do Friends.TagFriend(nFriendId, true); method?membersudhakar mr23 Apr '12 - 22:14 
Hi ,
I downloaded the tag project . Here i am working on images , not names . I finished till the addnewtag() . I am storing related values of x1,y1,x2,y2. Please explain how to do this method Friends.TagFriend(nFriendId, true); . what have you done in the Con.SubmitChanges(); method. please explain this . thank you in advance
GeneralMy vote of 3memberNileshKRathod5 Mar '12 - 18:27 
It is very helpful for me as first time worked on image tagging.
GeneralRe: My vote of 3memberOmar Gamil9 Mar '12 - 1:46 
why did you rate it so low then?
GeneralRe: My vote of 3membernephy k7 Sep '12 - 6:09 
can u send me the code...please.....
QuestionNice onememberAhmed_Said23 Sep '11 - 12:32 
Good job man, keep it up Wink | ;)
GeneralMy vote of 4memberSChristmas8 Jul '11 - 7:06 
Please mention which version of .Net framework you are using. My bad that i donwnloaded your application and i dont have 4.0 framework :(
GeneralMy vote of 4memberkoolprasad200321 Jun '11 - 3:37 
Good Article
GeneralNot working with Chrome andmemberbayonian16 May '11 - 4:37 
On local machine, after selecting the images the friend list doesn't show up in Chrome 11.0.696.68. But it works when hosted in IIS 7.5
 
- Doesn't work with IE9 and Opera 11.10
 
Please write mark-up and JavaScript and most browsers recognize
GeneralRe: Not working with Chrome andmembereasyese26 May '12 - 15:36 
To fix the issues download the latest library of the imgAreaSelect here.
 
http://odyniec.net/projects/imgareaselect/[^]
 
I had the same IE 9 issue but downloading the newest files and updating the .js files it seemed to fix the issue. Also I changed it from function() to document.ready see below of the example I followed from imgAreaSelect Documentation
 
<script type="text/javascript">
$(document).ready(function () {
    $('img#photo').imgAreaSelect({
        handles: true,
        onSelectEnd: someFunction
    });
});
</script>

QuestionOld database notation?memberBerggreenDK20 Mar '11 - 7:41 
Hi I'm an old "ASP classic" developer myself, gone on to C# etc.
 
I was looking at your DB design and was curious as to why you keep the "tFriend" notation, when .NET more or less states that the tablename itself is saying enough?
 
I know its an old habbit for many, and I also have old databases with sName, nValue etc. But I also converting more and more of these to the more modern standards used in JAVA and .NET
 
Eg. a field/record in database called: "Name" is clearly a string/text, what else could it be?
 
I usually design tables today with: "ID", "Name" as default fields in most tables. For views/lists I just name them in plain english, like "GetFriendList" or "GetFriendView". You could also move Friend in the end of the name or first, depending on how you like your tables sorted in the list.
 
Also if you start using LINQ it makes much more sense when the names are more readable, like when you pull data from Friends instead of tFriends.
 
Just my two cents. Hope you can use them.
 
Thanks for article, I did a similar project a year ago, so I was curious to see your implementation.
AnswerRe: Old database notation?memberOmar Gamil20 Mar '11 - 8:15 
you are right, its an old habit back when i was developing C++
Thanks for your feedback Smile | :)
GeneralRe: Old database notation?memberBerggreenDK21 Mar '11 - 2:28 
hehe, I am also way back from C/C++, then VBscript (ASP Classic) where I had to make the shortest way to keep a little tidyness in the code. But after switching to ASP.NET and C#, AS 3.0 and Javascript it seems more and more unpleasant to read those old notations as the API's/LIBS all use normal readable table and variable names.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 21 Jun 2011
Article Copyright 2011 by Omar Gameel Salem
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid