---
title: "Отримання домінантного кольору зображення в Laravel"
url: https://laravelukraine.com/blog/viznacennia-dominantnogo-kolyoru-zobrazen-u-laravel
date: 2026-08-07
source: https://laravel-news.com/laravel-image-dominant-color?utm_medium=feed&utm_source=feedpress.me&utm_campaign=Feed%3A+laravelnews
---

# Отримання домінантного кольору зображення в Laravel

Зображення, що ще не завантажилося, залишає дірку на сторінці. Звичайні рішення - сірий блок, розмитий thumbnail у HTML або взагалі нічого. Дешевша альтернатива, що покриває більшість потреб - заповнити простір середнім кольором фото. Так макет виглядає навмисним ще до того, як завантажиться перший піксель справжнього зображення.

Laravel 13.24 додав метод `dominantColor()` до вбудованого API для роботи із зображеннями, який повертає цей колір без окремого пакунка. У цій статті розглянемо, як отримати колір, де його зберігати та як ним користуватися.

## Налаштування

Drайвери GD та Imagick компонента для роботі із зображеннями базуються на Intervention Image - це рекомендована, а не обов'язкова залежність:

```
composer require intervention/image:^4.0
```

Більше нічого не потрібно. Визначення домінантного кольору працює на обох драйверах.

## Отримання домінантного кольору

Викличте `dominantColor()` на будь-якому екземплярі зображення - отримаєте hex-рядок:

```
use Illuminate\Support\Facades\Image;
$color = Image::fromPath(storage_path('app/photo.jpg'))->dominantColor();
// "#8a6f4c"
```

Реалізація зменшує копію зображення до одного пікселя та зчитує його значення. Це саме середнє значення, а не найчастіший колір - тому фото червоного амбара в зеленому полі дасть каламутний оливковий, а не червоний. Для плейсхолдера це саме те, що потрібно: колір має лежати за всім зображенням, а не представляти його об'єкт.

Префікс `#` завжди включений. Зображення з альфа-каналом повертають восьмизначну форму (`#rrggbbaa`), тому враховуйте це при визначенні розміру колонки.

Перетворення застосовуються перед вибіркою кольору - ви отримуєте колір зображення, яке збираєтесь зберегти, а не оригіналу:

```
$color = Image::fromStorage('uploads/photo.jpg')
 ->crop(800, 600, x: 200, y: 0)
 ->dominantColor();
```

Обріжте небо - і колір зміниться.

## Збереження домінантного кольору при завантаженні

Колір корисний лише тоді, коли він доступний при рендерингу сторінки. Тому обчисліть його один раз при завантаженні та зберігайте в моделі. Почніть із колонки:

```
Schema::create('photos', function (Blueprint $table) {
 $table->id();
 $table->string('path');
 $table->string('dominant_color', 9)->nullable();
 $table->timestamps();
});
```

Потім у контролері створіть зображення один раз і використовуйте екземпляр повторно:

```
use App\Models\Photo;

public function store(Request $request)
{
 $request->validate([
 'photo' => ['required', 'image', 'max:12288'],
 ]);

 $photo = $request->image('photo')
 ->orient()
 ->scale(width: 1600)
 ->optimize();

 return Photo::create([
 'path' => $photo->store('photos'),
 'dominant_color' => $photo->dominantColor(),
 ]);
}
```

Порядок тут важливий: `store()` виконує pipeline, кешує оброблені байти в екземплярі та очищає pipeline. Наступний виклик `dominantColor()` на тому ж екземплярі бере ці закешовані байти без додаткової роботи. Поміняйте рядки місцями - і колір обчислюватиметься для одноразового клону pipeline, а `store()` обробить зображення вдруге. Той самий результат, вдвічі більше роботи.

Значення також мемоізується для кожного екземпляра - повторний виклик `dominantColor()` нічого не коштує. Оскільки кожне перетворення повертає новий екземпляр, thumbnail, відгалужений від того самого джерела, обчислює власний колір замість успадкування:

```
$source = Image::fromStorage('uploads/photo.jpg')->orient();
$thumbnail = $source->cover(300, 300);
$display = $source->scale(width: 1600);

$thumbnail->dominantColor(); // вибірка з обрізаного квадрата
$display->dominantColor(); // вибірка з повного кадру
```

## Використання домінантного кольору як плейсхолдера

Маючи колір у моделі, шаблон стає фоновим кольором блоку, що вже має правильне співвідношення сторін:

```
<div class="aspect-[3/2] overflow-hidden rounded-lg"
 style="background-color: {{ $photo->dominant_color }}">
 <img src="{{ Storage::url($photo->path) }}"
 alt="{{ $photo->caption }}"
 loading="lazy"
 class="h-full w-full object-cover">
</div>
```

Кольоровий блок малюється з першим кадром, зображення з'являється поверх нього, коли завантажиться, і сторінка ніколи не перебудовується. Це добре поєднується з `loading="lazy"` у довгій галереї, де більшість зображень не завантажується, поки читач не прокрутить.

## Читабельний текст поверх кольору

Підписи чи іконки, розміщені поверх плейсхолдера, мають залишатися розбірливими незалежно від того, це фото снігового поля чи нічного неба. Відносна яскравість дає розумний поріг у кілька рядків:

```
namespace App\Support;

class Color
{
 public static function isLight(string $hex): bool
 {
 [$r, $g, $b] = sscanf(substr($hex, 0, 7), '#%02x%02x%02x');
 // Rec. 709 luma, 0-255.
 return (0.2126 * $r + 0.7152 * $g + 0.0722 * $b) > 140;
 }
}
```

```
<figcaption class="{{ Color::isLight($photo->dominant_color) ? 'text-gray-900' : 'text-white' }}">
 {{ $photo->caption }}
</figcaption>
```

## Заповнення letterbox та обертання

Та сама вибірка доступна як фонове значення всередині перетворення. Передача `dominant` у `contain()` заповнює letterbox-смуги власним кольором зображення замість фіксованого, який ви вибрали заздалегідь:

```
Image::fromUpload($request->file('photo'))
 ->contain(1200, 800, background: 'dominant')
 ->store('photos');
```

Портретне фото, доповнене до альбомного формату, отримує смуги, що належать фото - це виглядає набагато краще в сітці, ніж білі чи чорні смуги на кожній третій плитці. `rotate()` приймає те саме значення для кутів, що відкриваються:

```
$image->rotate(8, background: 'dominant');
```

В обох випадках вибірка відбувається для зображення на цьому етапі pipeline - обрізка раніше в ланцюжку змінює заповнення.

## Що це не є

`dominantColor()` повертає один усереднений колір. Це не екстрактор палітри, і він не знайде акцентний колір, який вибрав би дизайнер. Якщо вам потрібен набір репрезентативних зразків або перцептивна кластеризація, що ігнорує великий плоский фон - це не та функція, і спеціалізована бібліотека залишається правильним вибором.

Для плейсхолдерів, letterbox-заповнення та тонування картки за її власним зображенням один усереднений колір - це вся робота, і тепер він постачається з фреймворком.

## Додаткове читання

- Практичний посібник з вбудованої обробки зображень Laravel охоплює решту API: зміна розміру, обрізка, конвертація форматів та зберігання
- Image Dominant Color та підтримка HEIC у Laravel 13.24 містить повні примітки до релізу
- Функцію додав [@dr-codswallop](https://github.com/dr-codswallop) у [#60932](https://github.com/laravel/framework/pull/60932)
