【问题标题】:How can I generate two colour product images dynamically?如何动态生成两个彩色产品图像?
【发布时间】:2013-08-17 03:21:15
【问题描述】:

我目前正在构建一个电子商务网站(使用 Drupal Commerce)。我们销售定制的运动服装。客户可以选择一种款式、两种颜色和一种尺寸。每种款式都有三百多种颜色可供选择。

我正在为 Illustrator 中的产品创建图稿。它们是相当简单的向量,仅使用两种平面颜色,顶部有黑色轮廓。

我正在尝试找到一种方法来为每种样式生成所有颜色组合,最好是动态生成。我看过GD,但我不确定这会在这里奏效。我想知道是否有一种方法可以使用 SVG(因为我已经有了矢量)或堆叠 3 个可以应用颜色叠加并保留其透明度的透明 PNG? 完成。

为了动态创建图像,我创建了一个包含白色背景和纯红色和纯蓝色区域的 GIF,以定义主要和次要区域。这是通过 GD 运行的,它将红色和蓝色更改为用户选择的颜色。然后在顶部合并一个透明的 PNG,其中包含黑色轮廓和公司徽标。

在 index.php 上,我有一个表单,允许用户选择一种样式和两种颜色:

    <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>

提交表单后,有一些 PHP 会创建一个 URL,将选项传递给 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; ?>">

那么大部分工作都是由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);

我对结果很满意,因为我还在学习 PHP,以前从未研究过 GD。我已经发布了rough demo here(还有一个链接可以下载该页面上使用的所有文件)。

有什么改进建议吗?最终,我希望用户在下拉菜单中选择两种颜色,然后脚本将查看是否存在具有这些选项的图像,如果不存在,则通过设置两个区域的颜色动态创建它,然后存储新创建的图像对于未来的用户。

如何在不需要提交按钮的情况下使其自动更新?

【问题讨论】:

  • 您可以使用哪些语言?
  • 如果可能的话,我想坚持使用 php 和 javascript。
  • 我已经用一些示例代码更新了帖子。我已经使用 GIF 进行颜色更改,但如果我尝试使用 PNG,它似乎会失败。我想我会使用两张图片获得更清晰的结果。两个平面颜色区域之一,然后在应用颜色后向下合并透明轮廓。
  • 更新了帖子,其中包含一些几乎完成的代码以及指向工作示例 here 的链接。现在我只是想弄清楚如何在填充字段时使其自动更新。

标签: image dynamic colors product variations


【解决方案1】:

以上所有方法都有效,现在我已经用它来存储它创建的图像,并添加了一个检查,以在它尝试创建图像之前查看图像是否存在。链接的示例已经更新了所有代码,但这里有新的 product-image.php 文件供感兴趣的人使用。

$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;
}

【讨论】:

    【解决方案2】:

    使用上面的代码并添加几行jQuery,我终于达到了我最初的目标。

    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);
        });
    

    一旦选择框被修改,jQuery 通过附加值从 product-image.php 请求不同的图像。交互很流畅,完全符合我的要求。

    现在我只需要弄清楚如何存储生成的图像并添加一个检查以查看它们是否已经生成。然后我必须通过 Drupal Commerce 使所有这些都变得更好。

    我已经更新了my example page,所有代码都可以在那里下载。

    虽然这个问题没有收到任何回复,但如果不浏览本网站上的许多其他问题,我就无法弄清楚这一点,因此感谢所有在这里发帖的人!

    【讨论】: