I'm creating a little web app where people can choose colors for different parts of a race car. I'm using ImageMagick to take separate images of each part of the car, recolor them (with the clutImage function), and layer them on top of each other to create the final image.
Each image is PNG-24 with alpha transparency. Each image is exactly the same size to make it easier to combine them.
There are about ten layers, six of which are being recolored. The problem is that performance is a bit poor; it takes about ten seconds to render the image after each color change. Here's my code:
Sample code:
<?php
if(isSet($piece['color'])) {
//make a 开发者_JAVA百科1pixel image to replace color with
$clut = new Imagick();
$clut->newImage(1, 1, new ImagickPixel("#".$piece["color"]));
//change the color of the part
$car_part->clutImage($clut);
}
//now we need to add the part onto the car
$car->compositeImage($car_part, Imagick::COMPOSITE_DEFAULT, 0, 0);
clutImage seems like it might be overkill for this task; I'm not doing a gradient map, I'm simply replacing all colored pixels with a solid color. Yet no matter what function I use, it will probably still have to iterate over several million pixels total.
Is there a more efficient way to accomplish this, or is this just the nature of what I'm trying to do?
AFAIK, that is the nature of what you are doing. When it really comes down to it, you are just changing the values of a bunch of indices of a multidimensional array. At some point or another, there will be a loop.
There is also colorFloodfillImage, but I have never actually used that method. It may be worth a shot though.
I would guess clutImage is better than iterating through the pixels, because it is running at c speeds, where as iterating through the pixels using a php construct (for/while/foreach) would likely be slower.
One way that you may be able to really increase performance would be to cache parts, so that a given part x with a given color y is only generated once. The next time someone wants to paint part x with the color y, all you have to do is pull the rendered image from the cache. You could either store the image as a file, or store the imagick object in a memory object cache (apc/memcached/etc.) right after the clutImage call, so you can composite it with other objects.
hth.
精彩评论