문제

I'm currently building an ecommerce site (with Drupal Commerce). We sell sports clothing that is made to order. The customer is able to pick a style, two colours and a size. For each style there are over three hundred combinations of colours that could be chosen.

I am creating artwork for the products in Illustrator. They are fairly simple vectors that use only two flat colours with a black outline on top.

I'm trying to find a way to generate all of the colour combinations for each style, preferably dynamically. I've looked at GD but I'm not sure that will work here. I wondered if there was a way of either using SVG (as I already have vectors) or stacking 3 transparent PNGs that could have a colour overlay applied and preserve their transparency? Done.

To create the images dynamically I have created one GIF that contains the white background and a pure red and pure blue region to define the primary and secondary areas. This is run through GD which changes the red and blue to the user selected colours. Then a transparent PNG is merged on top which contains the black outline and the company logo.

On index.php I have a form that allows users to choose a style and two colours:

    <form method="post" action="index.php">
    <label for="style">Style:</label>
    <select id="style" name="style" required>
        <option value="0001">Vertical Stripe</option>
        <option value="0002">V Neck</option>
        <option value="0003">Contrast Side</option>
        ...
    </select>
    <br><br>
    <label for="color1">Color 1:</label>
    <select id="color1" name="color1" required>
        <option></option>
        <option value="134,84,66">Retro Brown</option>
        <option value="115,51,68">Claret</option>
        <option value="167,57,52">Deep Red</option>
        <option value="213,69,54">Bright Red</option>
        ...
    </select>
    ...
</form>

After the form has been submitted there's some PHP to create a URL that passes the options over to product-image.php:

<?php
    $url = "product-image.php";

    if (isset($_POST["style"])) {
        $url = $url . "?style=" . $_POST["style"]; 
    }
    if (isset($_POST["color1"])) {
        $url = $url . "&color1=" . $_POST["color1"];
    }
    if (isset($_POST["color2"])) {
        $url = $url . "&color2=" . $_POST["color2"];
    }

?>

<img class="product" src="<?php echo $url; ?>">

Then the bulk of the work is done by product-image.php:

// Set some dummy values to avoid errors
$style = "0001";
$color1 = array(255,255,0);
$color2 = array(0,0,200);

if (isset($_GET["style"])) {
    $style = $_GET["style"];
}

$colorFile = $style . "colors.gif";
$outlineFile = $style . "outline.png";

// Load image with coloured sections
$image_1 = imagecreatefromgif($colorFile);
// Load image with outlines 
$image_2 = imagecreatefrompng($outlineFile);            

imagealphablending($image_1, true);
imagesavealpha($image_1, true);

imagetruecolortopalette($image_1, false, 255);

// Import $color1 values to create an RGB array
if (isset($_GET["color1"])) {
    $color1 = explode(',', $_GET["color1"]);                
}
// Import $color2 values to create an RGB array
if (isset($_GET["color2"])) {               
    $color2 = explode(',', $_GET["color2"]);
}

// Define Primary (red) region
$region1 = imagecolorclosest ( $image_1, 255,0,0);

// Set new colour for $region1 using the values passed into $color1
imagecolorset($image_1, $region1, $color1[0], $color1[1], $color1[2]); 

// Get Secondary (blue) region
$region2 = imagecolorclosest ( $image_1, 0,0,255);

// Set new colour for $region2 using the values passed into $color2
imagecolorset($image_1, $region2, $color2[0], $color2[1], $color2[2]);

// Create a true color canvas, this seems to retain transparency when merging PNG & GIF
$merged_image = imagecreatetruecolor(339, 390);

// Merge the newly coloured sections
imagecopy($merged_image, $image_1, 0, 0, 0, 0, 339, 390);

// Merge the outlines on top    
imagecopy($merged_image, $image_2, 0, 0, 0, 0, 339, 390);   

// Tell browser to expect PNG
header("Content-type: image/png");

// Output new PNG                       
imagepng($merged_image);        

// Tidy up
imagedestroy($image_1);                                     
imagedestroy($image_2);
imagedestroy($merged_image);

I am pretty chuffed with the results as I am still learning PHP and had never looked into GD before. I have posted a rough demo here (there is also a link to download all the files used on that page).

Any suggestions for improvements? Ultimately I want the user to select two colours in the drop downs and then a script will look to see if an image with those options exists and if not it dynamically creates it by setting the colour of the two regions and then stores the newly created image for future users.

How can I make it auto update without the need for a submit button?

도움이 되었습니까?

해결책

All of the above works and now I've got it to store the images it creates and added a check to see if the image is there before it tries to create it too. The linked example has been updated with all the code but here's the new product-image.php file for anyone that's interested.

$style = "0001";                    // Dummy values to avoid errors
$color1 = array(247,228,064);
$color2 = array(031,076,146);

$templatePath = "../templates/";        // Relative path from this file to your templates

if (isset($_GET["style"])) {
    $style = $_GET["style"];                    // Replace $style with real value if recieved
}

if (isset($_GET["color1"])) {
    $color1 = explode(',', $_GET["color1"]);    // Replace $color1 with real RGB array if recieved
}

if (isset($_GET["color2"])) {               
    $color2 = explode(',', $_GET["color2"]);    // Replace $color2 with real RGB array if recieved
}

// Create unique output file name by concatenating all numerical values eg:0001247228522562146.png
$outputFileName = $style . implode("", $color1) . implode("", $color2) . ".png";

// Check if the image we want already exists
if (file_exists($outputFileName)) {

    // If it does then open the file in a binary mode
    $fp = fopen($outputFileName, 'rb');

    // send the right headers
    header("Content-Type: image/png");
    header("Content-Length: " . filesize($outputFileName));

    // dump the picture and stop the script
    fpassthru($fp);
    exit;

} else {        // If it doesn't already exist then lets create the image...

    $colorFile = $templatePath . $style . "colors.gif";
    $outlineFile = $templatePath . $style . "outline.png";

    $image_1 = imagecreatefromgif($colorFile);              // Load image with coloured sections
    $image_2 = imagecreatefrompng($outlineFile);            // Load image with outlines

    imagealphablending($image_1, true);
    imagesavealpha($image_1, true);

    imagetruecolortopalette($image_1, false, 255);

    $region1 = imagecolorclosest ( $image_1, 255,0,0);                          // Get Primary (red) region
    imagecolorset($image_1, $region1, $color1[0], $color1[1], $color1[2]);      // Set new colour for $region1

    $region2 = imagecolorclosest ( $image_1, 0,0,255);                          // Get Secondary (blue) region
    imagecolorset($image_1, $region2, $color2[0], $color2[1], $color2[2]);      // Set new colour for $region2

    $merged_image = imagecreatetruecolor(339, 390);             // Create a true color canvas

    imagecopy($merged_image, $image_1, 0, 0, 0, 0, 339, 390);   // Merge the newly coloured sections
    imagecopy($merged_image, $image_2, 0, 0, 0, 0, 339, 390);   // Merge the outlines on top

    header("Content-type: image/png");                          // Tell browser to expect PNG
    imagepng($merged_image, $outputFileName);                   // Save new PNG to server

    imagedestroy($image_1);                                     // Tidy up
    imagedestroy($image_2);
    imagedestroy($merged_image);

    // open the image we just created in a binary mode
    $fp = fopen($outputFileName, 'rb');

    // send the right headers
    header("Content-Type: image/png");
    header("Content-Length: " . filesize($outputFileName));

    // dump the picture and stop the script
    fpassthru($fp);
    exit;
}

다른 팁

Using the code above and adding a few lines of jQuery I have finally achieved my original goal.

The jQuery:

    $('select').click(function() {
        var style = $("select#style").val();
        var color1 = $("select#color1").val();
        var color2 = $("select#color2").val();
        var productImgURL = 'product-image.php?style='+ style + '&color1=' + color1 + '&color2=' + color2;
        $('.product').attr('src',productImgURL);
    });

As soon as the select box is modified the jQuery requests a different image from product-image.php by appending the values. The interaction is smooth and works exactly how I wanted.

Now I just have to figure out how to store the generated images and add a check to see if they have already been generated. Then I have to make all of this play nice with Drupal Commerce.

I have updated my example page and the all of the code is available for download there.

Although this question received no responses I wouldn't have figured this out without trawling through many other questions on this site so thanks to everyone who posts here!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top