Ok..here's a challenge (maybe not if you're really good I guess) for you PHP/MySQL gurus out there (may need javascript perhaps?)

If you can point me to a solution that exists for this, that would be good. If you can implement one, I'd love to learn from it, tweak it, integrate it...thanks!

SPEC. IN A NUTSHELL
A PHP page which lets a user overlay text labels on a picture. The picture's filename*, text and the X,Y coordinates for the position of the labels are then stored in MySQL.
This information can then be recalled from MySQL to regenerate the labeled picture. This is done by showing the picture file in the browser and overlying it with text at the X,Y coordinates stored.
Would prefer this to work in both IE7+ and FF2+
* please note: I don't want to store the picture file itself in MySQL, just the name for it for later reference for rendering the webpage.

SPEC. IN A STORY
1) User opens labeler.php in their browser.
2) labeler.php pulls up label_me.jpg and renders a "Submit" button underneath this.
3) Whenever user clicks on label_me.jpg, a cursor (or textbox) appears at that position to allow them to type text which overlays label_me.jpg - user can continue to do this until they get bored of putting text over the picture.
4) User clicks on "Submit" button. The page then saves each text entry as well as its X,Y coordinates to a MySQL database (this Database also stores other information aside from what's in this example).
5) User goes to a page which lists all the records in the said MySQL database as a table. Each row in the table also contains a link to each labeled picture associated with a record if that record has one.
6) Clicking on the link sends user to show_me.php which renders label_me.jpg with the overlying text(s) previously entered at their saved X,Y coordinates.

Thanks for reading this far. Looking forward to seeing what elegant solutions people come up with!

Cheers,
Kev

Recommended Answers

All 14 Replies

BzzBee: thanks for the thoughts.
As far as I can tell though..the aim of that page is to simply place a caption at the bottom of a picture.

What I'm trying to do is have a system which places text ON pictures. Not only that, but have a system where users can point-&-click then type in the text onto the picture. This labelled picture can then be stored & recalled later (regenerated by displaying the .jpg with the text at their inputted X,Y positions overlaid over the top).

Aware of anything like that I can learn from?

This can be done you just need to do alot of research into php regarding the related topics.
- File Uploading
- MySQL Database

If you get those two underyour belt, then it just leaves the customization of trial and error left.
Let me know how you go.

Thanks for the input..

This can be done you just need to do alot of research into php regarding the related topics.
- File Uploading
- MySQL Database

If you get those two underyour belt, then it just leaves the customization of trial and error left.
Let me know how you go.

It's like saying learn all of MySQL :)
Well..actually...the upload bit isn't too bad. I was thinking about referencing the file directly, no need to store it in the database like a BLOB. The bit I was finding a bit hard to get my head around is the text over picture input.
I've seen how you can locate where the user clicks on a picture to grab X,Y coordinates..but translating that into a response where a text box appears for them to type in text then grabbing that text info. along with the X,Y to park in the database - that's the tricky bit!

For any realtime functionality you will require javascript.
Something like a popup window, confirm button. Maybe something like:

<img onclick="javascript: confirm("Enter Text");" >

Something like that I would gather would work?

Thanks again..

<img onclick="javascript: confirm("Enter Text");" >

Something like that I would gather would work?

Yes, that would deliver a popup stating "Enter Text" upon click on the picture.
That would not however give the user the ability to type text directly over the picture itself. Not to mention, detecting the X,Y coordinates of where that text is supposed to be on that picture & the ability to save that...then later recalling it to put it all together as per 1st post's description.

It would seem there aren't really any examples around for me to learn from. Thanks for the the thoughts though!

There is alot of coding involved but this is the logic behind it.
- Javascript to obtain x/y value
- Javasript confirm button or whatever button to enter text
- PHP to store text and save into the mysqldatabase along with x/y position

Now there are various other things you can do from this point.
- Write the text to the file and resave the file
- Store Information and load image with text (not sure about this one)

Let me know with something you want and well try whip up some logic together.

PS: Why flag of previous post as a bad post, meant to be a good one?

Hey OmniX - thanks for reply..didn't think I'd get any more :)

There is alot of coding involved but this is the logic behind it.
- Javascript to obtain x/y value
- Javasript confirm button or whatever button to enter text
- PHP to store text and save into the mysqldatabase along with x/y position

There's of course more than one way to skin this problem but I was intrigued by what's implemented on this page - http://www.plus2net.com/php_tutorial/php_image_coordinates.php
..it doesn't seem to use Javascript? If course..it may well be more efficient to use Javascript..
Anyhow, I haven't fully comprehended the code behind that one yet (I'm working on it but not as fast as I would like since I'm also working on a few other problems at the moment) but it does demonstrate PHP picking up X,Y coordinates from mouse input?

Logic left to solve this:
1) Allow the user to type text into the X,Y position where the click was made.
2) Have a submission process where the X,Y position, VARCHAR string of the text in that X,Y position and the associated filename of the .jpg file under it all is saved.
3) A process whereby the associated .jpg is called up and overlaid with the saved VARCHAR string at the saved X,Y position.

Reason why I don't want to render a whole new .jpg file with the text saved into the image itself to recall later is that this strikes me as being rather wasteful from a disk storage point of view?
Also, that implementation doesn't allow for later edits.

PS: Why flag of previous post as a bad post, meant to be a good one?

I'm not sure what you mean by the above. Did I click some button flagging the your last post as a bad one? If so, I didn't mean to! Let me know how to fix it (if there's something to be fixed). No badness here..I've been grateful for your input into this thus far!
I believe solving this problem will be very useful for everyone as it is something that can be used for all sorts of situations eg: labelling maps/diagrams, general labelling of uploaded pictures people want to share etc...

Hey OmniX - thanks for reply..didn't think I'd get any more :)
http://www.plus2net.com/php_tutorial/php_image_coordinates.php

Logic left to solve this:
1) Allow the user to type text into the X,Y position where the click was made.
2) Have a submission process where the X,Y position, VARCHAR string of the text in that X,Y position and the associated filename of the .jpg file under it all is saved.
3) A process whereby the associated .jpg is called up and overlaid with the saved VARCHAR string at the saved X,Y position.

Reason why I don't want to render a whole new .jpg file with the text saved into the image itself to recall later is that this strikes me as being rather wasteful from a disk storage point of view?
Also, that implementation doesn't allow for later edits.

No problem KevT glad to help.
What they have done at the url is easy assuming my logic is correct and assuming so can easily do steps 1, 2 for you. 3 would require more research. I understand why you wouldnt render a new jpeg and personally if I did have to I wouldnt either I have done something similar rendering new jpegs but this idea of reconstructing one would be useful down the track so well try solve it and yes also to save disk space :P

Ok what I gather they have done is :
- Created an input with type image so when the user clicks on the image the page reloads it self and using the previous $_POST variables to gather the x/y attributes (I guess this is a possibility of using input type image).
- Now you said you wanted to input your own x/y and text that is even easier. Just make three text boxes x, y, and text and use $_POST to gather those 3 variables and store them in a variable in a database or whatever.
- Now the last step I think you could accomplish with CSS and PHP as I have used something similar with using z coordinate so you can overlay the with CSS. YOu will have to do some research my hands are pretty tied at the moment but if I get a chance I will try to do some research.

I'm not sure what you mean by the above. Did I click some button flagging the your last post as a bad one? If so, I didn't mean to! Let me know how to fix it (if there's something to be fixed). No badness here..I've been grateful for your input into this thus far!
I believe solving this problem will be very useful for everyone as it is something that can be used for all sorts of situations eg: labelling maps/diagrams, general labelling of uploaded pictures people want to share etc...

Maybe because I didnt see you put a comment I thought it was a negative and that you dont have much rep but dosent matter as long as its all good :)

Hey OmniX...thanks again. I'll be chewing through what you said and trying to understand how you interpreted that URL's PHP. Good to see my ideas are heading along the right track though.

If you come up with more thoughts, I would love to hear it. Like I said, this would be a generically useful bit of code for everyone once worked out since PHP & MySQL is so commonly employed.

Oh..and I see what you mean about the rep. thing..well, I just clicked on your's. Thanks again, look forward to any other posts you may have. Meanwhile..we'll all keep learning :)

towards part 3
code not confirmed for this use, but the source of the data can be from the dbase instead of input

<?php
/* configurable script 
All options can be input from the command line in the form 
<img src='make.jpg.php?h=l1=v1=l2=v2=l3=v3=l4=v4=l5=v5=size=max=r=imagename=color='>
order is not important to create multiple signs from a single script unused lines 
can be ignored will default to blank 

imagename
max, max1-5 maximum characters per line
trucase makes case sensitive signs, otherwise uppercase
h, h1-5 horizontal offset
v, v1-5 vertical offset
r, r1-5 rotation
s, s1-5 text size in points
c, c1-5 text color
f, f1-5 font face:: server installed fonts only
/* CONFIGURATION */
if(!$imagename)
{
$im = imagecreate(400, 200);
/* white background and blue text */
$bg = imagecolorallocate($im, 225, 255, 255);
$textcolor = imagecolorallocate($im, 0, 0, 255);
imagestring($im, 5, 10, 10, "No Image name!", $textcolor);
imagestring($im, 5, 10, 40, "This script requires parameters!", $textcolor);
imagestring($im, 5, 10, 70, "Check the format of 'billboard.php'!", $textcolor);
imagestring($im, 5, 10, 100, "for the necessary strings!", $textcolor);
imagestring($im, 5, 10, 130, "Read the comments in this file", $textcolor);
// output the image
header('Content-type : image/jpeg');
header('Content-Disposition: inline; filename="made.jpg"');
imagejpeg($im);
imagedestroy($im);
}
else 
{
$im = @imagecreatefromjpeg($imagename); /* Do NOT alter */
/* autoconfigure if not stated set default */

if(!$h or $h=='') {$h = 0;}
if(!$h1 or $h1=='') {$h1 = $h;}
if(!$h2 or $h2=='') {$h2 = $h;}
if(!$h3 or $h3=='') {$h3 = $h;}
if(!$h4 or $h4=='') {$h4 = $h;}
if(!$h5 or $h5=='') {$h5 = $h;}

if(!$v1 or $v1=='') {$v1 = 240; /* default Vertical offset from bottom of image */}
if(!$v2 or $v2=='') {$v2 = 200;}
if(!$v3 or $v3=='') {$v3 = 160;}
if(!$v4 or $v4=='') {$v4 = 120;}
if(!$v5 or $v5=='') {$v5 = 80;}

if(!$s or $s=='') {$s = 20; /* default text point size */}
if(!$s1 or $s1=='') {$s1 = $s;}
if(!$s2 or $s2=='') {$s2 = $s;}
if(!$s3 or $s3=='') {$s3 = $s;}
if(!$s4 or $s4=='') {$s4 = $s;}
if(!$s5 or $s5=='') {$s5 = $s;}

if(!$max or $max=='') {$max = 20; /* default max chars per line */}
if(!$max1 or $max1=='') {$max1 = $max;}
if(!$max2 or $max2=='') {$max2 = $max;}
if(!$max3 or $max3=='') {$max3 = $max;}
if(!$max4 or $max4=='') {$max4 = $max;}
if(!$max5 or $max5=='') {$max5 = $max;}

if(!$r or $r=='') {$r = 0; /* default text angle */}
if(!$r1 or $r1=='') {$r1 = $r;}
if(!$r2 or $r2=='') {$r2 = $r;}
if(!$r3 or $r1=='') {$r3 = $r;}
if(!$r4 or $r4=='') {$r4 = $r;}
if(!$r5 or $r5=='') {$r5 = $r;}
/* defined colors (add as many as required)
 colors are defined $cNAME in case the color NAME is a reserved word see here for color charts
 http://www.pitt.edu/~nisg/cis/web/cgi/rgb.html */
$cwhite = imagecolorallocate($im, 255, 255, 255); 
$cblack = imagecolorallocate($im, 0, 0, 0); 
$cred =  imagecolorallocate($im, 255, 0, 0);
$cdkred = imagecolorallocate($im, 150, 25, 25);
$cyellow = imagecolorallocate($im, 255, 255, 0); 
$cblue = imagecolorallocate($im, 0, 0, 255); 
$cgreen = imagecolorallocate($im, 0, 255, 0);
$cmagenta = imagecolorallocate($im, 255, 0, 255);

if($c) 
{
if(strtoupper($c) == 'WHITE') $cc = $cwhite;
if(strtoupper($c) == 'BLACK') $cc = $cblack;
if(strtoupper($c) == 'RED') $cc = $cred;
if(strtoupper($c) == 'DKRED') $cc = $cdkred;
if(strtoupper($c) == 'YELLOW') $cc = $cyellow;
if(strtoupper($c) == 'BLUE') $cc = $cblue;
if(strtoupper($c) == 'GREEN') $cc = $cgreen;
if(strtoupper($c) == 'MAGENTA') $cc = $cmagenta;
}
else {$cc = $cblack;}

if ($c1)
{
if(strtoupper($c1) == 'WHITE') $cc1 = $cwhite;
if(strtoupper($c1) == 'BLACK') $cc1 = $cblack;
if(strtoupper($c1) == 'RED') $cc1 = $cred;
if(strtoupper($c1) == 'DKRED') $cc1 = $cdkred;
if(strtoupper($c1) == 'YELLOW') $cc1 = $cyellow;
if(strtoupper($c1) == 'BLUE') $cc1 = $cblue;
if(strtoupper($c1) == 'GREEN') $cc1 = $cgreen;
if(strtoupper($c1) == 'MAGENTA') $cc1 = $cmagenta;
}
else $cc1 = $cc;

if ($c2)
{
if(strtoupper($c2) == 'WHITE') $cc2 = $cwhite;
if(strtoupper($c2) == 'BLACK') $cc2 = $cblack;
if(strtoupper($c2) == 'RED') $cc2 = $cred;
if(strtoupper($c2) == 'DKRED') $cc2 = $cdkred;
if(strtoupper($c2) == 'YELLOW') $cc2 = $cyellow;
if(strtoupper($c2) == 'BLUE') $cc2 = $cblue;
if(strtoupper($c2) == 'GREEN') $cc2 = $cgreen;
if(strtoupper($c2) == 'MAGENTA') $cc2 = $cmagenta;
}
else {$cc2 = $cc;}

if ($c3)
{
if(strtoupper($c3) == 'WHITE') $cc3 = $cwhite;
if(strtoupper($c3) == 'BLACK') $cc3 = $cblack;
if(strtoupper($c3) == 'RED') $cc3 = $cred;
if(strtoupper($c3) == 'DKRED') $cc3 = $cdkred;
if(strtoupper($c3) == 'YELLOW') $cc3 = $cyellow;
if(strtoupper($c3) == 'BLUE') $cc3 = $cblue;
if(strtoupper($c3) == 'GREEN') $cc3 = $cgreen;
if(strtoupper($c3) == 'MAGENTA') $cc3 = $cmagenta;
}
else $cc3 = $cc;

if ($c4)
{
if(strtoupper($c4) == 'WHITE') $cc4 = $cwhite;
if(strtoupper($c4) == 'BLACK') $cc4 = $cblack;
if(strtoupper($c4) == 'RED') $cc4 = $cred;
if(strtoupper($c4) == 'DKRED') $cc4 = $cdkred;
if(strtoupper($c4) == 'YELLOW') $cc4 = $cyellow;
if(strtoupper($c4) == 'BLUE') $cc4 = $cblue;
if(strtoupper($c4) == 'GREEN') $cc4 = $cgreen;
if(strtoupper($c4) == 'MAGENTA') $cc4 = $cmagenta;
}
else {$cc4 = $cc;}

if ($c5)
{
if(strtoupper($c5) == 'WHITE') $cc5 = $cwhite;
if(strtoupper($c5) == 'BLACK') $cc5 = $cblack;
if(strtoupper($c5) == 'RED') $cc5 = $cred;
if(strtoupper($c5) == 'DKRED') $cc5 = $cdkred;
if(strtoupper($c5) == 'YELLOW') $cc5 = $cyellow;
if(strtoupper($c5) == 'BLUE') $cc5 = $cblue;
if(strtoupper($c5) == 'GREEN') $cc5 = $cgreen;
if(strtoupper($c5) == 'MAGENTA') $cc5 = $cmagenta;
}
else {$cc5 = $cc;}

/* end c defintions */

if(!$l1 and !$l2 and !$l3 and !$l4 and !$l5)
{
$l1 = 'input'; /* configurable */
$l2 = 'some';
$l3 = 'value';
$l4 = 'in the';
$l5 = 'text fields';
}
else
{
if(!$l2) {$l2 = " ";}
if(!$l3) {$l3 = " ";}
if(!$l4) {$l4 = " ";}
if(!$l5) {$l5 = " ";}
}

if(!$f) {$f = 'arial.ttf';}
if(!$f1) {$f1 = $f;}
if(!$f2) {$f2 = $f;}
if(!$f3) {$f3 = $f;}
if(!$f4) {$f4 = $f;}
if(!$f5) {$f5 = $f;}

if($trucase)
{
$l1 = substr(trim($l1), 0, $max);
$l2 = substr(trim($l2), 0, $max);
$l3 = substr(trim($l3), 0, $max);
$l4 = substr(trim($l4), 0, $max);
$l5 = substr(trim($l5), 0, $max);
}
else
{
$l1 = strtoupper(substr(trim($l1), 0, $max));
$l2 = strtoupper(substr(trim($l2), 0, $max));
$l3 = strtoupper(substr(trim($l3), 0, $max));
$l4 = strtoupper(substr(trim($l4), 0, $max));
$l5 = strtoupper(substr(trim($l5), 0, $max));
}
header("Cache-Control: no-cache, must-revalidate");
header('Content-type : image/jpeg');
header('Content-Disposition: inline; filename="made.jpg"');
$width = imagesx($im);
$height = imagesy($im);
$w1 = imagettfbbox($s1, $r1, $f1, $l1);
$w2 = imagettfbbox($s2, $r2, $f2, $l2);
$w3 = imagettfbbox($s3, $r3, $f3, $l3);
$w4 = imagettfbbox($s4, $r4, $f4, $l4);
$w5 = imagettfbbox($s5, $r5, $f5, $l5);
imagettftext($im, $s1, $r1, ($width - ($w1[2] - $w1[0])) / 2 + $h1, $height - $v1, $cc1, $f1, $l1); 
imagettftext($im, $s2, $r2, ($width - ($w2[2] - $w2[0])) / 2 + $h2, $height - $v2, $cc2, $f2, $l2); 
imagettftext($im, $s3, $r3, ($width - ($w3[2] - $w3[0])) / 2 + $h3, $height - $v3, $cc3, $f3, $l3); 
imagettftext($im, $s4, $r4, ($width - ($w4[2] - $w4[0])) / 2 + $h4, $height - $v4, $cc4, $f4, $l4); 
imagettftext($im, $s5, $r5, ($width - ($w5[2] - $w5[0])) / 2 + $h5, $height - $v5, $cc5, $f5, $l5); 
imagejpeg($im);
imagedestroy($im);
}
<?php 
define('_BBCLONE_DIR', '../bbclone/');
define('COUNTER', _BBCLONE_DIR.'mark_page.php');
if (is_readable(COUNTER)) include_once(COUNTER);
echo "<html><head>
<LINK rel='StyleSheet' HREF='/style.css' TYPE='text/css' MEDIA=screen>
<script language='javascript' type='text/javascript' src='/scriptrc.js'></script>
<title>video - Entertainment - Dockrey Apartments</title>
</HEAD>
<body class='text' bgcolor='#eeeeee' onload='framekeeper('$_SERVER['PHP_SELF'];');self.focus();' leftmargin='0' topmargin='0'>
<center>";

if (!$l1 and !$l2 and !$l3) 
{
echo "<img border=1 src='make.jpg.php?f=&max=30&s=20&imagename=billboard.jpg&r=0&c=white&h=-10&v1=340&v2=300&v3=260&v4=&v5=&l1=world ends at ten tonite&l2=see full report&l3=on global news at eleven&l4=&l5='>";
}
else 
{
echo "<img border=1 src='make.jpg.php?f=&max=30&s=20&imagename=billboard.jpg&r=0&c=white&h=-10&v1=340&v2=300&v3=260&v4=&v5=&l1=$l1&l2=$l2&l3=$l3&l4=&l5='>";
}
echo "<br><form align='center' action='$PHP_SELF' METHOD='post'>
Type your sign here<br>
<Input name='l1' type='text' size=38 ><br>
<Input name='l2' type='text' size=38 ><br>
<Input name='l3' type='text' size=38 ><br>
<input type='submit' value='Get Sign'><br>
</body>
"; ?>

Hi almostbob (who's Practically a Master Poster) - thanks for your input with getting us almost there :)
In the interest of timely replies, I'm posting this to thank you for your help. I'll be on working understanding what you've posted and seeing if I can merge it together with other solutions pointed to in this thread. Let's see what happens :)

Almostbob, in short that code creates a white board which then you insert the image and then checks for text parameters and writes the text over it correct?

header("Cache-Control: no-cache, must-revalidate");
header('Content-type : image/jpeg');
header('Content-Disposition: inline; filename="made.jpg"');
$width = imagesx($im);
$height = imagesy($im);
$w1 = imagettfbbox($s1, $r1, $f1, $l1);
$w2 = imagettfbbox($s2, $r2, $f2, $l2);
$w3 = imagettfbbox($s3, $r3, $f3, $l3);
$w4 = imagettfbbox($s4, $r4, $f4, $l4);
$w5 = imagettfbbox($s5, $r5, $f5, $l5);
imagettftext($im, $s1, $r1, ($width - ($w1[2] - $w1[0])) / 2 + $h1, $height - $v1, $cc1, $f1, $l1); 
imagettftext($im, $s2, $r2, ($width - ($w2[2] - $w2[0])) / 2 + $h2, $height - $v2, $cc2, $f2, $l2); 
imagettftext($im, $s3, $r3, ($width - ($w3[2] - $w3[0])) / 2 + $h3, $height - $v3, $cc3, $f3, $l3); 
imagettftext($im, $s4, $r4, ($width - ($w4[2] - $w4[0])) / 2 + $h4, $height - $v4, $cc4, $f4, $l4); 
imagettftext($im, $s5, $r5, ($width - ($w5[2] - $w5[0])) / 2 + $h5, $height - $v5, $cc5, $f5, $l5); 
imagejpeg($im);
imagedestroy($im);

Now my question is, does this code override "made.jpeg"?

yes that code creates a white board and inserts an image, in my case, every image on the site is postcardable, and writes text over it as defined by the form inputs
it would't be much different to locate the start points for the text lines, colors fonts etc from the clicked position
I apologise for not producing code with inline comments, when it was built, it was a personal thing that was never to see the light of day,
now everyone has seen the "some a'hole on a cell phone got creamed" highway advisory sign, and there are dozens of versions of sign writing script to play with

may want to look up one of the tutorials on image watermarking, essentially the same as what both of us want/did/trying to do
could then pulll the text watermark and location from the database

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.