tags:

views:

58

answers:

3

I am looking to flock() an image.

Currently I am using the following

$img = ImageCreateFromPng($img_path);
flock($img,LOCK_EX);

It seems that the GD library's file handle is not valid with flock. How can I access the image and flock the file?

+1  A: 

The function flock only works on file handles (or stream wrappers if they support locking). So, if you want to lock an image when you read it, you'd need to open it twice:

$f = fopen($imgPath, 'r');
if (!$f) {
    //Handle error (file does not exist perhaps, or no permissions?)
}
if (flock($f, LOCK_EX)) {
    $img = imagecreatefrompng($imgPath);
    //...  Do your stuff here

    flock($f, LOCK_UN);
}
fclose($f);
ircmaxell
hmmm, IF the image is flock'd then I get an error from imagecreatefrompng - saying that it is not a valid png. To test it just before I called imagecreatefrompng I called flock($f, LOCK_UN) and the code worked again.
Pablo
What version of PHP and what OS? It works fine for me on 5.3.2 on Linux...
ircmaxell
I am using it on Windows at the moment. But this is only for testing.... it will be live on a linux server.
Pablo
That's probrably why. Windows has internal locking that prevents opening a file for write while another processes has it open. It should work fine on Linux, for what it's worth (And not have the memory overhead of reading the file in a string in PHP)...
ircmaxell
Thanks for all your help.
Pablo
A: 

flock only works with file pointers and ImageCreateFromPng only works with filenames. Try making two different calls:

$fp = fopen($img_path, 'r');
flock($fp, LOCK_EX);
$img = ImageCreateFromPng($img_path);

flock is cooperative, so it only works if everybody uses it. As long as ImageCreateFromPng doesn't use flock, the code above should work.

scompt.com
hmmm, If the image is flock'd then I get an error from imagecreatefrompng - saying that it is not a valid png. To test it just before I called imagecreatefrompng I called flock($fp, LOCK_UN) and the code worked again.
Pablo
That's too bad. Maybe try locking the file and copying it to a temporary file. Then, operate on the temporary file while the main file is locked.
scompt.com
Thanks, ircmaxell assures me that it will work on linux... so i'll be using this method after all.
Pablo
+1  A: 

$img in your example is not a file handle, it is a handle to a GD image resource in memory.

You can use imagecreatefromstring to load an image like this:

$file=fopen($fileName,"r+b");
flock($file,LOCK_EX);
$imageBinary=stream_get_contents($file);
$img=imagecreatefromstring($imageBinary);
unset($imageBinary); // we don't need this anymore - it saves a lot of memory

If you want to save a modified version of the image to the open stream you have to use output buffering:

ob_start();
imagepng($img);
$imageBinary=ob_get_clean();

ftruncate($file,0);
fseek($file,0);
fwrite($file,$imageBinary);
unset($imageBinary);
flock($file,LOCK_UN);
fclose($file);
Wikeno
This looks like a good workaround to the problem of imagecreatefrompng not working on flocked files.
scompt.com
I get an error for a parameter missing for ftruncate... I looked it up seems to be the size that you wish to truncate the file by
Pablo
sorry, ftruncate fixed
Wikeno
I haven't tested it so you may also have to fseek($file,0) after the trucating.
Wikeno
I tried truncating it to 0... it generated a file twice the size of the original... I'll try fseek
Pablo
Yes the fseek did the trick.. thanks
Pablo
Hmmm.. I just benchmarked it. This takes 600ms... imagecreatefrompng,imagepng ... takes 0.12ms. I am not sure its a viable option :S Thanks anyway
Pablo