Created
November 5, 2020 07:05
-
-
Save davidhellmann/f03cc6ad569b1a7a965e213e06dcefa5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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