Skip to content

Instantly share code, notes, and snippets.

@davidhellmann
Created November 5, 2020 07:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidhellmann/f03cc6ad569b1a7a965e213e06dcefa5 to your computer and use it in GitHub Desktop.
Save davidhellmann/f03cc6ad569b1a7a965e213e06dcefa5 to your computer and use it in GitHub Desktop.
<?php
namespace modules;
use Craft;
// Elements
use craft\elements\Asset;
use craft\elements\Category;
// Events
use spacecatninja\imagerx\services\ImagerService;
use yii\base\Event;
use craft\events\ModelEvent;
// Misc
use craft\events\RegisterTemplateRootsEvent;
use craft\web\View;
use spacecatninja\imagerx\services\ImagerColorService;
class ColorExtract extends \yii\base\Module
{
public function __construct($id, $parent = null, array $config = [])
{
Craft::setAlias('@modules', $this->getBasePath());
// Base template directory
Event::on(View::class, View::EVENT_REGISTER_CP_TEMPLATE_ROOTS, function(RegisterTemplateRootsEvent $e) {
if (is_dir($baseDir = $this->getBasePath() . DIRECTORY_SEPARATOR . 'templates')) {
$e->roots[$this->id] = $baseDir;
}
});
// Set this as the global instance of this module class
static::setInstance($this);
parent::__construct($id, $parent, $config);
}
public function init()
{
parent::init();
// Captures an asset being saved.
Event::on(
Asset::class,
Asset::EVENT_AFTER_SAVE,
function(ModelEvent $event) {
// Make sure this is a new asset being created
if ($event->isNew) {
// Isolate the asset from the event
/** @var Asset $asset */
$asset = $event->sender;
// Make sure this is an asset that Imager can eat.
if ($asset->kind !== 'image' || !in_array(strtolower($asset->getExtension()), ImagerService::getConfig()->safeFileFormats, true)) {
return;
}
// Below are settings for the getColorPalette function in Imager-X
// Number of colors (there seems to be a bug, you need to add 1 to the number you want)
$colorCount = 9;
// The lowest the longest it will take
$quality = 10;
$colorValue = 'rgb';
// Precision used when reducing the possible amount of values
// - A value of 1 will result in no reduction, the maximum number of distinct values will be 16,777,216.
// - A value of 16 will result in a maximum number of 4,096.
$precision = 52;
// Fetch the color palette from the image
$fullPalette = (new ImagerColorService)->getColorPalette($asset, $colorCount, $quality, $colorValue);
// Approximate colors
$palette = array_map(static function ($rgb) use ($precision) {
return ImagerColorService::rgb2hex(
[
round($rgb[0] / $precision) * $precision,
round($rgb[1] / $precision) * $precision,
round($rgb[2] / $precision) * $precision,
]
);
}, $fullPalette);
// Define an array to store the colors we'll want to add to our asset
$allColors = [];
// Iterate over each colors
foreach ($palette as $color) {
// Does this color already exist?
$exists = Category::find()
->title($color)
->one();
if($exists) {
// the color already exists, we use its ID
$allColors[] = $exists->id;
} else {
// It's a new color, let's create it
$newColor = new Category();
$newColor->groupId = 15; // Adjust this to be the correct category id
$newColor->title = $color;
$newColor->setFieldValue('assetColor', $color);
$newColor->setFieldValue('assetColorRgb', implode(",", ImagerColorService::hex2rgb($color)));
$newColor = Craft::$app->elements->saveElement($newColor);
if (!$newColor) {
Craft::error('Couldn’t save the entry "' . $newColor->title . '"', __METHOD__);
}
$savedColor = Category::find()
->title($color)
->one();
$allColors[] = $savedColor->id;
}
}
// Add the colors to the asset colors field
$this->_addColorsToAsset($asset->id, $allColors);
}
}
);
}
private function _addColorsToAsset($assetId, $allColors) {
// Fetch our asset
$asset = Asset::find()
->id($assetId)
->one();
// Set the the colors field values
$asset->setFieldValue('assetColorPalette', $allColors);
// Save our asset
if (!Craft::$app->elements->saveElement($asset)) {
Craft::error('Couldn’t save the colors on the asset "' . $asset->title . '"', __METHOD__);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment