How to read Lightroom keywords from image file using PHP? - php

I have a photo community (www.jungledragon.com) that allows users to upload photos. My platform is PHP/CodeIgniter.
As part of the upload process I'm already reading EXIF info using PHP's exif_read_data function, which works fine. I read camera details and show these on an info tab.
On top of that, user's are expected to manually set the photo title, description and tags on the website after uploading the photo. However, some users manage these fields in their image management program, for example Lightroom. It would be great if I could read those as well, uploading would become a total joy.
I already improved my EXIF reading to read the "caption", this way users don't have to set the image title after uploading anymore. Now I'm looking to read keywords, which is where I am stuck. Here's a partial screenshot of an image in Lightroom:
I can read the Metadata, but how do I read the keywords? The fact that it is not inside metadata makes me wonder if it's at all possible? I've tried reading every value I can get (ANY_TAG, IFD0, EXIF, APP12) using exif_read_data, but the keywords are not to be found.
Any thoughts?

As suggested you may have to use another method of reading metadata.
http://www.foto-biz.com/Lightroom/Exif-vs-iptc-vs-xmp
Image keywords may be stored in IPTC and not in EXIF. I don't know if there is a standard platform method for reading iptc but a quick google shows this
http://php.net/manual/en/function.iptcparse.php

Try using PEL, a much more comprehensive library than exif_read_data() for exif data.

After a long research, i found the solution to get keywords exported by lightroom in a jpg file :
$image = getimagesize($imagepath, $info);
if(isset($info['APP13']))
{
$iptc = iptcparse($info['APP13']);
$keywordcount = count($iptc["2#025"]);
for ($i=0; $i<$keywordcount; $i++)
{
echo "keyword : " . $iptc["2#025"][$i] . "<br/>";
}
}

Related

Saving images from sources without a specific mime type

As an example, say I'm trying to download App Icons from the Google Play store for a service. Here is an example URL:
https://lh6.ggpht.com/1eVPA6Iukw-F4i5xq1ZWicaKBzmprLGw98YhdG20E-wlsHHg3PcKJqbY_fWLdJeGRw=w512-rw
There is no mime type associated with the data provided, and when the file is saved any image viewers (or at least the ones I've tried) will say the file is corrupt. They will show up in Chrome and a couple of other things, but when inspecting the data, it's clear there's simply no mime type. This is an issue, because I am further using these data streams in other scripts which require that they be recognized as a specific type. (namely PNG)
I've tried things such as:
imagepng(imagecreatefromstring($icondata), $finaldir.'/icon.png');
Where $icondata is simply a curl response for the image. This will return an error saying that the data is of an unknown format for the imagecreatefromstring function. Of course, I've also tried:
file_put_contents($finaldir.'/icon.png', $icondata);
To no avail. It creates the file, but as I said, the image is not recognized as an image in most applications and in various analyzing functions. Is there a way to specifically set the mime type of a given string of data? Or some other workaround I'm not quite seeing?
Edit: Also, to note, there is nothing wrong with the $icondata variable. I have tried manually saving the image to a file through my web browser, and the same problem arises.
I have developed a small CMS for myself and was facing the same issue. After trying a lot, I have found a solution. It is working for me and I hope you will find it useful for your project too.
Regarding the corruption of file, for Chrome user-agent, Google servers send icons as .webp format and you need a PHP library for handling images of this type. And for other user-agents (like Firefox), images are sent as PNG.
Now comparing the two URLs for a same icon in Firefox or Chrome, you will notice that image paths generated for Chrome contain -rw at the end while the same URL in Firefox doesn't contain that -rw.
Not digging very deeper, simply remove the -rw from the end of the URL and copy the image. You will get a PNG image. A hint is here for you:
<?php
$image_path = "https://lh5.ggpht.com/8PODwBXKk4L201m4IO1wifRDfbn4Q1JxNxOzj-5TXPJ85_S-vOqntLi7TsVyeFQM0w4=w300-rw"; // Firefox app on Google Play
$png_path = substr($image_path, 0, -3);
copy($png_path, 'file.png');
?>
This will save the image as PNG. Please note that I have used substr() function to remove -rw from the end. To make it precise, you may use any other way to fix that part of the path.
P.S. You may also try sending a custom user-agent (i.e. Firefox) with your CURL request to receive the PNG path so you will not need to fix it by yourself :)
You can use HttpResponse::getContentType to determine type of content you're getting from URL
This not a png, but WebP
You can use it in PHP with
imagecreatefromwebp( string $filename );
More information:
- https://developers.google.com/speed/webp/
- http://php.net/manual/function.imagecreatefromwebp.php

build an API for streaming audio/video from GridFS mongodb

I have tried the solution given in the link stream audio/video files from gridFS on the browser
Still when I use my code the file gets downloaded or it plays with the default browser player.
My code is as:
header('Content-type: audio/mpeg;');
$stream = $file->getResource();
while (!feof($stream)) {
echo fread($stream, 8192);
}
I actually want a solution to build an API so that I can retrieve the audio/video from mongodb GridFS and play it streaming from a phone application.
Help is urgently needed. Any help on the topic would be welcome.
I found a way to make an API for playing the file straight from the mongoDB GridFS in a HTML audio video image widget. The only problem with it is that it uses the data retrieved from mongoDB as a base64 data. Now the problem that i am talking about is discussed in this link:
http://davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to.
I hope you find that useful before deciding to use the solution I am using. My solution is as follows:
$stream = $file->getResource();
$stringcoded = stream_get_contents($stream); //converts the stream to string data
$encoded = base64_encode($stringcoded); //encodes string data to base64
Now that you have the audio, video or image data encoded in base64, you just have to echo the data in the 'src' portion of the html5 widget.
I got this solution from a very useful blog. If you need more help on it please go through it:
http://www.iandevlin.com/blog/2012/09/html5/html5-media-and-data-uri
Any enhanced solution to this problem is more than welcome.

Edit exif data of an image [duplicate]

On our site, we get a large amount of photos uploaded from various sources.
In order to keep the file sizes down, we strip all exif data from the source using mogrify:
mogrify -strip image.jpg
What we'd like to be able to do is to insert some basic exif data (Copyright Initrode, etc) back onto this new "clean" image, but I can't seem to find anything in the docs that would achieve this.
Has anybody any experience of doing this?
If it can't be done through imagemagick, a PHP-based solution would be the next best thing!
Thanks.
You can save a large amount of space, especially if you have a large number of images..
Add the following to text.txt (format of the IPTC tags taken from here):
2#110#Credit="My Company"
2#05#Object Name="THE_OBJECT_NAME"
2#55#Date Created="2011-02-03 12:45"
2#80#By-line="BY-LINE?"
2#110#Credit="The CREDIT"
2#115#Source="SOURCE"
2#116#Copyright Notice="THE COPYRIGHT"
2#118#Contact="THE CONTACT"
2#120#Caption="AKA Title"
Strip all existing exif data from the image
mogrify -strip image.jpg
Add the credit to your image
mogrify -profile 8BIMTEXT:text.txt image.jpg
Exiftool looks like it would be an exact match for you.
I haven't tried it but I'm now tempted to go and fix all my honeymoon photos which are marked 01/01/2074 because I forgot to reset the date after the batteries died.
Here's a PHP Exif Library that should do what you need.
The PHP Exif Library (PEL) lets you
fully manipulate Exif (Exchangeable
Image File Format) data. This is the
data that digital cameras place in
their images, such as the date and
time, shutter speed, ISO value and so
on.
Using PEL, one can fully modify the
Exif data, meaning that it can be both
read and written. Completely new Exif
data can also be added to images. PEL
is written completely in PHP and
depends on nothing except a standard
installation of PHP, version 5. PEL is
hosted on SourceForge.
on linux there is a program called jhead. It can add a minimal exif header with the command:
jhead -mkexif img.jpg
I doubt you will gain lot of space by removing Exif information...
Anyway, I can be wrong, but Exif metadata belongs more to store technical (and contextual) information. For stuff like copyright, you should use IPTC instead.
That's something you can do, apparently, with ImageMagick: Write IPTC Data to Jpeg with ImageMagick.
You can do this directly in PHP using the PEL library. You would do this by simply overwriting the existing EXIF-headers,
// Load image data
$data = new PelDataWindow(file_get_contents('IMAGE PATH'));
// Prepare image data
$jpeg = $file = new PelJpeg();
$jpeg->load($data);
// Create new EXIF-headers, overwriting any existing ones (when writing to disk)
$exif = new PelExif();
$jpeg->setExif($exif);
$tiff = new PelTiff();
$exif->setTiff($tiff);
// Create Ifd-data that will hold EXIF-tags
$ifd0 = new PelIfd(PelIfd::IFD0);
$tiff->setIfd($ifd0);
// Create EXIF-data for copyright
$make = new PelEntryAscii(PelTag::COPYRIGHT, '2008-2017 Conroy');
$ifd0->addEntry($make);
// Add more EXIF-data...
// Save to disk
$file->saveFile('IMAGE.jpg');
You can find a complete list of all supported EXIF-data (PelTag) in the PEL docs.

Write EXIF into JPG with PHP

For a couple of days I'm trying to write (or update) EXIF information (geotag, latitude and longitude) in a JPG image using PHP.
After consulting many sites without success I think the best option is to use Imagick but although it seems I can set the latitude and longitude with setImageProperty(), but when I write the picture the EXIF is not saved.
Here I give a code fragment:
//Loading existing image
$edited = new Imagick(dirname(__FILE__)."/mini.jpg");
//Stripping the curren EXIF info. I think is not mandatory and I try to comment but nothing...
$edited->stripImage();
//Setting the new properties
$edited->setImageProperty('exif:GPSLatitude', '30/1, 46/1, 58605/1000');
$edited->setImageProperty('exif:GPSLongitude', '63/1, 57/1, 35550/1000');
$propiedades = $edited->getImageProperties();
var_dump($propiedades);
var_dump($edited->writeImage('mini_edited.jpg'));
//reading the new image EXIF Info
$readedited = new Imagick(dirname(__FILE__)."/mini_edited.jpg");
$propiedades_edited = $readedited->getImageProperties();
The image is saved successfully but no the exif information updates.
Anyone have an idea how I can solve this problem with this or any other tool?
The only requirement is to use PHP
Thank you very much in advance!
The only way I've found is to install PEL - the PHP Exif Library
The gd or ImageMagick libraries will help you do this sort of thing.
If you are using shared hosting one (or both of them) may have been installed for you.

Image creation using php

Am trying to create a video clip using .jpg images and ffmpeg, am creating .jpg images as below:
$str=$_REQUEST['data_array'];//gets the base64 encoded image data;
$count =$_REQUEST['count'];//gets number of images i've to create;
$edited_str=substr($str,23,strlen($str)-1);//
$edited_str=base64_decode($edited_str);
$f=fopen("Images/temp".$count.".jpg","w");//am creating temp.jpg file
fwrite($f,$edited_str);//placing my decoded data into file
fclose($f);
are the images am creating above different from normal .jpg images?
This line:
$edited_str=substr($str,23,strlen($str)-1);
makes it different. If this is the full base64 sting of the file, then this cuts it up and corrupts it. Maybe you are adding some stuff on the front.
If you are just removing stuff from the front that was added, then it should be the same as the original file that was encoded with base64.
If you want to get the information this way from another page, I suggest using $_POST as opposed to $_REQUEST for a number of reasons.
EDIT: I wouldn't say video manipulation in php is impossible. I think there is even a toolkit... here's one:
http://phpvideotoolkit.sourceforge.net/
which states:
It can perform video format conversion, extract video frames into separate image files, and assemble a video stream from a set of separate video images.
Haven't tested it, but plan to try it out one day.
EDIT2: On the php site, there were some issues that you could try, but to help more, there needs to be more information. Check with a file directly to make sure it's being sent and decrypted properly.
I haven't got to test any of these yet.
One piece of advice was for large files use:
$decodedstring=base64_decode(chunk_split($encodedstring));
Another was if you use javascript canvas.toDataURL() then you need to convert spaces back to pluses:
$encodedData = str_replace(' ','+',$encodedData);
$decocedData = base64_decode($encodedData);
http://php.net/manual/en/function.base64-decode.php

Categories