【问题标题】:Applying a logo to a tshirt using PHP Imagick使用 PHP Imagick 将徽标应用于 T 恤
【发布时间】:2014-06-12 12:19:11
【问题描述】:

我是 php 上的 imagemagic aka imagick 的新手,我正在尝试使用 php 代码关注 this thread。我曾尝试将此徽标应用到 T 恤上,但无法通过遵循这些威胁来做到这一点,因为我无法在 php 中找到大多数方法,例如使用置换贴图开始。我尝试的是以下代码:

$image = new Imagick($_SERVER['DOCUMENT_ROOT'] . '/images/VYLZsoD.jpg');    
$logo = new Imagick($_SERVER['DOCUMENT_ROOT'] . '/images/logo.png');
$logo->resizeImage(200, 200, imagick::FILTER_LANCZOS, 1, TRUE);    
header("Content-Type: image/jpg");

$image->compositeimage($logo, Imagick::COMPOSITE_DEFAULT, 400, 260); 
$image->flattenImages();

echo $image;

我想使用线程中显示的步骤来创建面具等,以便使用 php 代码(而不是通过命令)将徽标应用到 T 恤上。我什至使用“COMPOSITE_OVERLAY”使徽标看起来像是 T 恤的一部分,但由于透明度,徽标的原始颜色似乎减少了, .

  1. 请告诉我如何在 php 中使用 imagick 存档更好的结果(不减少徽标的颜色)
  2. 我可以在 T 恤上标记一个区域,这样当我拖动徽标时,它就不会显示在 T 恤边框之外?

【问题讨论】:

  • 可以发源图片吗?
  • @Danack 谢谢。我刚刚上传了它们。查看原帖

标签: php imagemagick imagick


【解决方案1】:

您问题的第二部分,如何让折痕“很好地”显示出来可能是个坏主意。尝试它有两个问题:

i) T 恤的变形是物理位移。尽管您可以让折痕照明显示出来,但如果没有相同的物理位移,很难让徽标看起来很逼真。

ii) 颜色的表现确实不一致。只是让徽标变亮/变暗与 T 恤折痕相同的量可能会产生不切实际的效果。例如深色 T 恤 + 折痕 = 亮 50% 的背景。明亮的蓝色徽标 + 50% 更亮的折痕效果 = 看起来不真实的蓝色高光。

我建议使用平底 T 恤作为背景,因为不切实际的效果往往会分散人们的注意力。但你可以这样做:

function getAverageColorString(\Imagick $imagick) {

    $tshirtCrop = clone $imagick;
    $tshirtCrop->cropimage(100, 100, 90, 50);
    $stats = $tshirtCrop->getImageChannelStatistics();
    $averageRed = $stats[\Imagick::CHANNEL_RED]['mean'];
    $averageRed = intval(255 * $averageRed / \Imagick::getQuantum());
    $averageGreen = $stats[\Imagick::CHANNEL_GREEN]['mean'];
    $averageGreen = intval(255 * $averageGreen / \Imagick::getQuantum());
    $averageBlue = $stats[\Imagick::CHANNEL_BLUE]['mean'];
    $averageBlue = intval(255 * $averageBlue / \Imagick::getQuantum());
    $colorString = "rgb($averageRed, $averageGreen, $averageBlue)";

    return $colorString;
}


$tshirt = new \Imagick(realpath("../images/tshirt/tshirt.jpg"));
$logo = new \Imagick(realpath("../images/tshirt/Logo.png"));
$logo->resizeImage(100, 100, \Imagick::FILTER_LANCZOS, 1, TRUE);

$tshirt->setImageFormat('png');

//First lets find the creases
//Get the average color of the tshirt and make a new image from it.
$colorString = getAverageColorString($tshirt);
$creases = new \Imagick();
$creases->newpseudoimage(
   $tshirt->getImageWidth(),
   $tshirt->getImageHeight(), 
   "XC:".$colorString
);

//Composite difference finds the creases
$creases->compositeimage($tshirt, \Imagick::COMPOSITE_DIFFERENCE, 0, 0);
$creases->setImageFormat('png');
//We need the image negated for the maths to work later. 
$creases->negateimage(true);
//We also want "no crease" to equal 50% gray later
//$creases->brightnessContrastImage(-50, 0); //This isn't in Imagick head yet, but is more sensible than the modulate function.
$creases->modulateImage(50, 100, 100);

//Copy the logo into an image the same size as the shirt image
//to make life easier
$logoCentre = new \Imagick();
$logoCentre->newpseudoimage(
   $tshirt->getImageWidth(),
   $tshirt->getImageHeight(),
   "XC:none"
);
$logoCentre->setImageFormat('png');
$logoCentre->compositeimage($logo, \Imagick::COMPOSITE_SRCOVER, 110, 75);

//Save a copy of the tshirt sized logo
$logoCentreMask = clone $logoCentre;

//Blend the creases with the logo
$logoCentre->compositeimage($creases, \Imagick::COMPOSITE_MODULATE, 0, 0);

//Mask the logo so that only the pixels under the logo come through
$logoCentreMask->compositeimage($logoCentre, \Imagick::COMPOSITE_SRCIN, 0, 0);

//Composite the creased logo onto the shirt
$tshirt->compositeimage($logoCentreMask, \Imagick::COMPOSITE_DEFAULT, 0, 0);

//And Robert is your father's brother
header("Content-Type: image/png");
echo $tshirt->getImageBlob();

生成如下图像:

【讨论】:

  • 我一定会试试这个。有没有另一种方法可以得到这个“\Imagick::getQuantum()”,它说它是一个未定义的方法。
  • ` $max = $image->getQuantumRange(); $max = $max["quantumRangeLong"];` - 该函数将在 Imagick 的下一个版本中。
  • 知道为什么我会得到黑色徽标吗?
  • 并非如此。您发布的代码对我有用。我只能假设您使用的是带有错误的 ImageMagick 版本。例如这是i.stack.imgur.com/0Uypu.png 的图像,其中包含徽标位置/大小。您可能应该测试每个步骤以查看徽标变为黑色的位置。
【解决方案2】:

您发布的输出图像与我在运行您的代码时看到的输出图像不同。显然稍微调整位置,我看到的输出图像并没有减少颜色。

如果您没有看到相同的内容,则可能是您的 ImageMagick 版本中的错误。您可以尝试使用复合方法 COMPOSITE_ATOP,它应该通过不同的混合方法产生相同的结果。

对于您的第二个问题,如何将徽标覆盖限制在 T 恤的边缘,您可以通过在 T 恤上创建一个蒙版,使用 COMPOSITE_SRCIN 将徽标绘制到该蒙版上,然后将结果绘制到T恤:

    $tshirt = new \Imagick(realpath("../images/tshirt/tshirt.jpg"));
    $logo = new \Imagick(realpath("../images/tshirt/Logo.png"));
    $logo->resizeImage(100, 100, \Imagick::FILTER_LANCZOS, 1, TRUE);

    $tshirt->setImageFormat('png');

    $max = $image->getQuantumRange();
    $max = $max["quantumRangeLong"];

    //Create a mask by cloning the shirt,
    $mask = clone $tshirt;
    //Negating the image,
    $mask->negateimage(true);
    //Make it transparent everywhere that it is now white.
    $mask->transparentPaintImage(
        'black', 
        0, 
        0.1 * $max, 
        false
    );

    //Paint the logo onto the mask, SRCIN just uses the logo's color
    $mask->compositeimage($logo, \Imagick::COMPOSITE_SRCIN, 210, 75);
    //Paint the result of the logo + mask onto the tshirt.
    $tshirt->compositeimage($mask, \Imagick::COMPOSITE_DEFAULT, 0, 0);
    //Merge the image with a non-deprecated function.
    $tshirt->mergeimagelayers(\Imagick::LAYERMETHOD_COALESCE);

    header("Content-Type: image/png");
    echo $tshirt->getImageBlob();
}

这会产生类似的东西:

这是否是一个好主意是另一回事。

【讨论】:

  • 第二个选项很棒。奇迹般有效。我认为我的输出图像放在这里是为了表明,当我嵌入图像时,我需要表明它实际上是 T 恤的一部分,就像标志在这里和那里被压碎一样,就像在原始源 T 恤中一样。我在这里放的是“COMPOSITE_OVERLAY”并设置了透明度级别,以便粉碎的材料也显示在 android 徽标中。但是当我透明 android 标志并将其与 T 恤复合时,绿色已经褪色。将您的示例用于第二个选项,我怎样才能在您的徽标上显示压碎的材料?
  • 您需要做的是对图像进行卷积以产生“折痕”蒙版,然后将其应用于徽标 - 但是在 ImageMagick 中这似乎可能会被破坏 - stackoverflow.com/questions/24184801/…
  • 你能提供一个示例代码吗?老实说,我不是 imagemagick 专业人士。
【解决方案3】:

这是我第二个问题的最终代码:

<?php

// Let's check whether we can perform the magick.
if (TRUE !== extension_loaded('imagick')) {
    throw new Exception('Imagick extension is not loaded.');
}

// This check is an alternative to the previous one.
// Use the one that suits you better.
if (TRUE !== class_exists('Imagick')) {
    throw new Exception('Imagick class does not exist.');
}

function getAverageColorString(\Imagick $imagick) {

    $max = $imagick->getquantumrange(); 
    $max = $max["quantumRangeLong"];
    
    $tshirtCrop = clone $imagick;
    $tshirtCrop->cropimage(100, 100, 90, 50);
    $stats = $tshirtCrop->getImageChannelStatistics();
    $averageRed = $stats[\Imagick::CHANNEL_RED]['mean'];
    $averageRed = intval(255 * $averageRed / $max);
    $averageGreen = $stats[\Imagick::CHANNEL_GREEN]['mean'];
    $averageGreen = intval(255 * $averageGreen / $max);
    $averageBlue = $stats[\Imagick::CHANNEL_BLUE]['mean'];
    $averageBlue = intval(255 * $averageBlue / $max);
    $colorString = "rgb($averageRed, $averageGreen, $averageBlue)";

    return $colorString;
}

//final product
$tshirt = new \Imagick($_SERVER['DOCUMENT_ROOT'] . '/images/VYLZsoD.jpg');
$logo = new \   Imagick($_SERVER['DOCUMENT_ROOT'] . '/logo.png');
$logo->resizeImage(100, 100, imagick::FILTER_LANCZOS, 1, TRUE);

$tshirt->setImageFormat('png');

//First lets find the creases
//Get the average color of the tshirt and make a new image from it.
$colorString = getAverageColorString($tshirt);
$creases = new \Imagick();
$creases->newpseudoimage(
   $tshirt->getImageWidth(),
   $tshirt->getImageHeight(), 
   "XC:".$colorString
);

//Composite difference finds the creases
$creases->compositeimage($tshirt, \Imagick::COMPOSITE_DIFFERENCE, 0, 0);
$creases->setImageFormat('png');
//We need the image negated for the maths to work later. 
$creases->negateimage(true);
//We also want "no crease" to equal 50% gray later
//$creases->brightnessContrastImage(-50, 0); //This isn't in Imagick head yet, but is more sensible than the modulate function.
$creases->modulateImage(50, 100, 100);

//Copy the logo into an image the same size as the shirt image
//to make life easier
$logoCentre = new \Imagick();
$logoCentre->newpseudoimage(
   $tshirt->getImageWidth(),
   $tshirt->getImageHeight(),
   "XC:none"
);
$logoCentre->setImageFormat('png');
$logoCentre->compositeimage($logo, \Imagick::COMPOSITE_SRCOVER, 110, 75);

//Save a copy of the tshirt sized logo
$logoCentreMask = clone $logoCentre;

//Blend the creases with the logo
$logoCentre->compositeimage($creases, \Imagick::COMPOSITE_MODULATE, 0, 0);

//Mask the logo so that only the pixels under the logo come through
$logoCentreMask->compositeimage($logoCentre, \Imagick::COMPOSITE_SRCIN, 0, 0);

//Composite the creased logo onto the shirt
$tshirt->compositeimage($logoCentreMask, \Imagick::COMPOSITE_DEFAULT, 0, 0);

//And Robert is your father's brother
header("Content-Type: image/png");
echo $tshirt->getImageBlob();
?>

输出

【讨论】:

    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 2014-10-05
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    相关资源
    最近更新 更多