Question

I am looking to have multiple users edit the same image using the gd library's imagecopymerge function.

I am worried that two users might select to edit the image at the same time. The application then merge's the two users images seperately and finally saves them but one overwrites the other and thus one of the users images is missing.

I am not sure of how to test the above... is it a possibility and if so how can I combat it?

Was it helpful?

Solution

Store the last-modified timestamp when the user begins editing an image. when they submit their changes, check against the last-modified timestamp again. If it's different, inform the user than another user has already modified the image.

You might want to let the user see the new version of the image before choosing to overwrite. Also, you may want to provide a version control system (a la wikipedia) to let people roll back changes.

EDIT (In response to comments below)

  1. As opposed to storing the last modified time stamp (or perhaps in addition to), store a hash of the original image. and compare those immediately before overwriting. Otherwise same as above.

  2. The other option, as you suggested would also work well. at step 3 in your workflow create an [imagefilename].lock file (or modify a field in the DB if they are stored there) at the beginning of the process if one doesn't already exist, of course if one does exist, then same as above.

  3. To expand on the DB option in point 2 above, it would be much simpler to have a table like: image_id | image_data

    query including the md5 when you begin (optionally compute the md5 in php instead to reduce load on your db)

    select image_data, md5(image_data) from image_table where image_id=1
    

    Then when you want to write back, do

    update image_table set image_data=? where image_id=? and md5(image_data)=?
    

    This makes the update conditional on the md5 being identical before being overwritten, and it remains in a single, simple query.

    Then check the affected_rows. If no rows were affected, then check the hash. If the hash is different then presumably the query failed to update due to the md5 check. (Note: you will probably also want to check for any mysql errors)

OTHER TIPS

Ah, what you basically want is saving the delta with respect to the original images.

One way:

  1. A user Fred fetches the original source image I1 and edits it. Fred posts back the whole new image N1
  2. You compute the delta of the image D1, that is {N1 - O}. Instead of saving just overwriting N1, you retrieve the current image I2 from disk which might have been changed in the meantime (I1 doesn't need to equal I2) . You apply D1 to I1 and overwrite the image with the resulting image, which we call I3.
    Beware, you need to remember I1 for this to work in $_SESSION for example.
  3. Now an other Ria could edit the same image during the previous steps. For instance, shortly after Fred got I1, Ria got it too. Just before Ria has finished her work, Fred has had his delta saved on disk resulting in I3, like we saw. So what now? You blindly apply step 2. I will show what happens: User2 submits his work N2, the delta D2 is computed by comparing I1 with N2 (The session for Ria contains I1). The current image is retrieved from disk, which is I3 as you might correctly remember. This delta D2 is applied to I3 resulting in I4, which is saved to disk. Result is that Ria has overwrited I3, but only those parts she has actually edited.

This recipe will work, because file saving is an atomic operation in php.

To get this working:

  1. you need to ensure when a user A retrieves an image I to edit, I needs to be stored in A's session. Easy.
  2. You need to be able to compute a diff of the image, and apply this diff to an image. This should be possible with imagemagick's compare function for instance. Looking at the example of that url you'll see that in the diff white pixels are those that untouched.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top