Monthly Archives: February 2009

Color replacement in PHP, pixel by pixel

If you’re crazy enough to process an image pixel by pixel in PHP, then you can replace a color with another.

You can get decent results for vector graphics, but it’s slow.

On this one, I won’t explain the code, I’ll just post it and let you figure it out, it has some comments.

The code could be better, but I don’t really have the time or the will to  improve it.

A quick example

Let’s say you have this image (the Ubuntu wallpaper):


Original image

And for some reason, you want to replace the oranges with some sort of violet. You can use Photoshop, or Gimp, or a PHP script to get this:


Image with colors replaced by the PHP script

Above is the result of the script, after 3 seconds of processing.

Download the PHP code

Here is the script: color.tar.bz2. If you can find a use for it, by all means use it.

I have to give credit to Paul Bourke for the HSVToRGB and RGBToHSV functions that I ported to PHP.

Race conditions in PHP and how to guard against them

What do you think? Does PHP need inter-process synchronization?

Although PHP doesn’t support running multiple threads, it runs in a multi-threaded or multi-process environment.

PHP needs some form of mutex

PHP needs mutexes. Sometimes, we need to create critical sections.

You can’t create threads from your PHP scripts, but that’s not a problem; if you need threads to generate some HTML, then something is very wrong.

If you look at the bigger picture, things start to get a little messy – your scripts could run at the same time.

Scripts are started by the web server in response to different, concurrent, HTTP requests. Because of this we need to think about shared resources and some form of locking.

In a normal PHP script, the shared resources are usually files, but they could be anything that’s global and shared by all your scripts.

If you find yourself using shared resources, you’d better start thinking about locking start analyzing your code as if you were writing it in a multithreaded environment.

Don’t believe me? well… take a look in the PHP source at the session handling code; why are they locking the session files?

A quick example

Let’s assume that we run this thing on a server with 2 physical processors.

It just happens that Apache gets 2 requests for our script at the exact same moment. The kernel just happens to schedule Apache’s processes to run on the 2 processors at the exact same time.

Here’s what will happen:

  1. Instance 1 starts and reads the value from the file (assume it’s 0).
  2. Instance 2 starts and reads the value from the file (it’s still 0).
  3. Instance 1 increments the value to 1 and saves it back.
  4. Instance 2 increments the value to 1 and saves it back.
  5. The file contains the 1, not 2.

What you can do about it

If you understood my crummy example above, you’ll notice that there is one function in PHP which can ensure that we don’t use the file from multiple scripts at the same time. I’m talking about flock().

So, we can use flock() to create a critical section and everything will be OK? Well, actually, yes! We can and we should.

Let’s fix the previous example:

  1. Instance 1 starts and locks the file.
  2. Instance 1 reads the value from the file (assume it’s 0).
  3. Instance 2 starts and blocks while locking the file.
  4. Instance 1 increments the value to 1 and saves it back.
  5. Instance 1 unlocks the file and exits.
  6. Instance 2 is resumed and locks the file.
  7. Instance 2 reads the value from the file. The value is 1.
  8. Instance 2 increments the value to 2 and saves it back.
  9. Instance 2 unlocks the file and exits.
  10. The file contains the 2.

That wasn’t so hard! was it?

Just keep in mind that flock() has its limitations. Check out its manual page for more details.

Another thing: keep your critical sections small, or you’ll get a bottleneck where requests are waiting for the same lock.

Use this mutex class

I’ve written a mutex class that you can use: mutex.zip.