pixielity/laravel-color-thief

Color extraction and palette generation utilities

Installs: 0

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Forks: 0

pkg:composer/pixielity/laravel-color-thief

v1.0.0 2026-02-09 03:23 UTC

This package is auto-updated.

Last update: 2026-02-09 00:43:28 UTC


README

ColorThief

Color extraction and palette generation utilities for the Pixielity Framework, providing easy-to-use methods for extracting dominant colors and color palettes from images.

Table of Contents

Overview

The ColorThief package wraps the popular ColorThief PHP library with Laravel-specific features including automatic caching, facade support, and color manipulation utilities. Extract dominant colors and generate color palettes from any image source.

Features

  • Dominant Color Extraction: Get the main color from any image
  • Color Palette Generation: Extract multiple colors to create palettes
  • Multiple Image Sources: Support for file paths, URLs, GD resources, Imagick instances, and binary strings
  • Automatic Caching: Built-in 30-day caching for performance
  • Color Manipulation: Lighten, darken, and adjust color lightness
  • Hex Color Support: All colors returned as hex codes
  • Laravel Integration: Facade and service provider included
  • Octane Safe: No request-specific state, fully compatible with Laravel Octane

Installation

The ColorThief package is part of the Framework package:

composer require pixielity/color-thief

The service provider is automatically registered via Laravel's package discovery.

Usage

Using the Facade

use Pixielity\ColorThief\Facades\ColorThief;

// Get dominant color from image
$dominantColor = ColorThief::getDominantColor('/path/to/image.jpg');
// Returns: "#3a5f8b"

// Get color palette
$palette = ColorThief::getColorPalette('/path/to/image.jpg', 5);
// Returns: ["#3a5f8b", "#8b3a5f", "#5f8b3a", "#8b5f3a", "#5f3a8b"]

// Lighten a color
$lighter = ColorThief::lightenColor('#3a5f8b', 20);
// Returns: "#6a8fbb"

// Darken a color
$darker = ColorThief::darkenColor('#3a5f8b', 20);
// Returns: "#0a2f5b"

Using Dependency Injection

use Pixielity\ColorThief\Contracts\ColorThief;

class ImageService
{
    public function __construct(
        private ColorThief $colorThief
    ) {}

    public function extractColors(string $imagePath): array
    {
        return [
            'dominant' => $this->colorThief->getDominantColor($imagePath),
            'palette' => $this->colorThief->getColorPalette($imagePath, 5),
        ];
    }
}

Using Service Container

// Resolve from container
$colorThief = app(Pixielity\ColorThief\ColorThief::class);

// Or use contract
$colorThief = app(Pixielity\ColorThief\Contracts\ColorThiefInterface::class);

API Reference

getDominantColor()

Extract the dominant (most prominent) color from an image.

public function getDominantColor(
    mixed $sourceImage,
    int $quality = 10,
    ?array $area = null
): string

Parameters:

  • $sourceImage (mixed) - Image source (file path, URL, GD resource, Imagick instance, or binary string)
  • $quality (int) - Sampling quality from 1 (best) to 10 (fastest). Default: 10
  • $area (array|null) - Optional area to sample [x, y, width, height]

Returns:

  • string - Hex color code (e.g., "#3a5f8b")

Examples:

use Pixielity\ColorThief\Facades\ColorThief;

// From file path
$color = ColorThief::getDominantColor('/path/to/image.jpg');

// From URL
$color = ColorThief::getDominantColor('https://example.com/image.jpg');

// With higher quality (slower but more accurate)
$color = ColorThief::getDominantColor('/path/to/image.jpg', 1);

// Sample specific area [x, y, width, height]
$color = ColorThief::getDominantColor('/path/to/image.jpg', 10, [0, 0, 100, 100]);

// From GD resource
$gd = imagecreatefromjpeg('/path/to/image.jpg');
$color = ColorThief::getDominantColor($gd);

// From binary string
$binary = file_get_contents('/path/to/image.jpg');
$color = ColorThief::getDominantColor($binary);

getColorPalette()

Extract a palette of colors from an image.

public function getColorPalette(
    mixed $sourceImage,
    int $colorCount = 10,
    int $quality = 10,
    ?array $area = null
): array

Parameters:

  • $sourceImage (mixed) - Image source
  • $colorCount (int) - Number of colors to extract. Default: 10
  • $quality (int) - Sampling quality from 1 (best) to 10 (fastest). Default: 10
  • $area (array|null) - Optional area to sample [x, y, width, height]

Returns:

  • array<string> - Array of hex color codes

Examples:

use Pixielity\ColorThief\Facades\ColorThief;

// Get 5 colors
$palette = ColorThief::getColorPalette('/path/to/image.jpg', 5);
// Returns: ["#3a5f8b", "#8b3a5f", "#5f8b3a", "#8b5f3a", "#5f3a8b"]

// Get 10 colors with high quality
$palette = ColorThief::getColorPalette('/path/to/image.jpg', 10, 1);

// Sample specific area
$palette = ColorThief::getColorPalette('/path/to/image.jpg', 5, 10, [0, 0, 200, 200]);

// Get many colors for detailed palette
$palette = ColorThief::getColorPalette('/path/to/image.jpg', 20);

lightenColor()

Lighten a color by a specified percentage.

public function lightenColor(string $hexColor, int $percentage): string

Parameters:

  • $hexColor (string) - Hex color code (e.g., "#3a5f8b" or "3a5f8b")
  • $percentage (int) - Percentage to lighten (0-100)

Returns:

  • string - Lightened hex color code

Examples:

use Pixielity\ColorThief\Facades\ColorThief;

$original = '#3a5f8b';

// Lighten by 20%
$lighter = ColorThief::lightenColor($original, 20);
// Returns: "#6a8fbb"

// Lighten by 50%
$muchLighter = ColorThief::lightenColor($original, 50);
// Returns: "#9abfdb"

// Create a gradient
$gradient = [
    ColorThief::lightenColor($original, 0),   // Original
    ColorThief::lightenColor($original, 25),  // Slightly lighter
    ColorThief::lightenColor($original, 50),  // Medium lighter
    ColorThief::lightenColor($original, 75),  // Very light
];

darkenColor()

Darken a color by a specified percentage.

public function darkenColor(string $hexColor, int $percentage): string

Parameters:

  • $hexColor (string) - Hex color code (e.g., "#3a5f8b" or "3a5f8b")
  • $percentage (int) - Percentage to darken (0-100)

Returns:

  • string - Darkened hex color code

Examples:

use Pixielity\ColorThief\Facades\ColorThief;

$original = '#3a5f8b';

// Darken by 20%
$darker = ColorThief::darkenColor($original, 20);
// Returns: "#0a2f5b"

// Darken by 50%
$muchDarker = ColorThief::darkenColor($original, 50);
// Returns: "#00001b"

// Create a dark gradient
$gradient = [
    ColorThief::darkenColor($original, 0),   // Original
    ColorThief::darkenColor($original, 25),  // Slightly darker
    ColorThief::darkenColor($original, 50),  // Medium darker
    ColorThief::darkenColor($original, 75),  // Very dark
];

adjustColorLightness()

Adjust the lightness of a color by a specific value.

public function adjustColorLightness(string $hexColor, int $adjustment): string

Parameters:

  • $hexColor (string) - Hex color code
  • $adjustment (int) - Adjustment value (-255 to 255). Positive lightens, negative darkens

Returns:

  • string - Adjusted hex color code

Examples:

use Pixielity\ColorThief\Facades\ColorThief;

$original = '#3a5f8b';

// Lighten by 50 units
$lighter = ColorThief::adjustColorLightness($original, 50);

// Darken by 50 units
$darker = ColorThief::adjustColorLightness($original, -50);

// No change
$same = ColorThief::adjustColorLightness($original, 0);

Caching

All color extraction and manipulation operations are automatically cached for 30 days to improve performance.

Cache Strategy

  • TTL: 30 days (2,592,000 seconds)
  • Key Format: color_thief_{operation}_{parameters}
  • Deterministic: Same input always produces same output, perfect for long-term caching

Cache Keys

// Dominant color
"color_thief_/path/to/image.jpg"

// Color palette
"color_thief_color_palette_/path/to/image.jpg_5_10"

// Lighten color
"color_thief_lighten_color_#3a5f8b_20"

// Darken color
"color_thief_darken_color_#3a5f8b_20"

Manual Cache Management

use Illuminate\Support\Facades\Cache;

// Clear all ColorThief cache
Cache::flush(); // Clears all cache

// Clear specific image cache
$cacheKey = app(Pixielity\ColorThief\ColorThief::class)
    ->generateCacheKey('/path/to/image.jpg');
Cache::forget($cacheKey);

Color Manipulation

Creating Color Variations

use Pixielity\ColorThief\Facades\ColorThief;

$baseColor = '#3a5f8b';

// Create a complete color scheme
$colorScheme = [
    'base' => $baseColor,
    'light' => ColorThief::lightenColor($baseColor, 30),
    'lighter' => ColorThief::lightenColor($baseColor, 60),
    'dark' => ColorThief::darkenColor($baseColor, 30),
    'darker' => ColorThief::darkenColor($baseColor, 60),
];

Generating Theme Colors

// Extract colors from brand logo
$logo = '/path/to/logo.png';
$palette = ColorThief::getColorPalette($logo, 5);

// Create theme with variations
$theme = [
    'primary' => $palette[0],
    'primary-light' => ColorThief::lightenColor($palette[0], 20),
    'primary-dark' => ColorThief::darkenColor($palette[0], 20),
    'secondary' => $palette[1],
    'accent' => $palette[2],
];

Creating Gradients

$startColor = '#3a5f8b';
$steps = 5;

$gradient = [];
for ($i = 0; $i < $steps; $i++) {
    $percentage = ($i / ($steps - 1)) * 100;
    $gradient[] = ColorThief::lightenColor($startColor, (int)$percentage);
}

Best Practices

1. Use Appropriate Quality Settings

// For thumbnails or quick previews - use default quality (10)
$color = ColorThief::getDominantColor($image, 10);

// For production use - use medium quality (5)
$color = ColorThief::getDominantColor($image, 5);

// For critical color matching - use best quality (1)
$color = ColorThief::getDominantColor($image, 1);

2. Sample Relevant Areas

// Sample only the product, not the background
$productArea = [50, 50, 300, 300]; // [x, y, width, height]
$productColor = ColorThief::getDominantColor($image, 10, $productArea);

// Sample the top portion for header colors
$headerArea = [0, 0, 1920, 200];
$headerColor = ColorThief::getDominantColor($image, 10, $headerArea);

3. Request Appropriate Palette Sizes

// For simple themes - 3-5 colors
$palette = ColorThief::getColorPalette($image, 5);

// For detailed palettes - 10-15 colors
$palette = ColorThief::getColorPalette($image, 12);

// Avoid excessive colors (slow and unnecessary)
// ❌ Bad
$palette = ColorThief::getColorPalette($image, 50);

4. Handle Errors Gracefully

try {
    $color = ColorThief::getDominantColor($imagePath);
} catch (\Exception $e) {
    // Fallback to default color
    $color = '#3a5f8b';
    Log::warning('Color extraction failed', [
        'image' => $imagePath,
        'error' => $e->getMessage()
    ]);
}

5. Process Images Asynchronously

use Illuminate\Support\Facades\Queue;

// Queue color extraction for large images
Queue::push(function () use ($imagePath) {
    $colors = ColorThief::getColorPalette($imagePath, 10, 1);

    // Store results
    cache()->put("image_colors_{$imagePath}", $colors, now()->addDays(30));
});

6. Validate Color Inputs

function isValidHexColor(string $color): bool
{
    return (bool) preg_match('/^#?[0-9A-Fa-f]{6}$/', $color);
}

if (isValidHexColor($userColor)) {
    $lighter = ColorThief::lightenColor($userColor, 20);
}

Testing

Unit Testing

use Tests\TestCase;
use Pixielity\ColorThief\Facades\ColorThief;

class ColorThiefTest extends TestCase
{
    public function test_extracts_dominant_color(): void
    {
        $imagePath = __DIR__ . '/fixtures/test-image.jpg';

        $color = ColorThief::getDominantColor($imagePath);

        $this->assertIsString($color);
        $this->assertMatchesRegularExpression('/^#[0-9a-f]{6}$/i', $color);
    }

    public function test_generates_color_palette(): void
    {
        $imagePath = __DIR__ . '/fixtures/test-image.jpg';

        $palette = ColorThief::getColorPalette($imagePath, 5);

        $this->assertIsArray($palette);
        $this->assertCount(5, $palette);

        foreach ($palette as $color) {
            $this->assertMatchesRegularExpression('/^#[0-9a-f]{6}$/i', $color);
        }
    }

    public function test_lightens_color(): void
    {
        $original = '#3a5f8b';
        $lighter = ColorThief::lightenColor($original, 20);

        $this->assertNotEquals($original, $lighter);
        $this->assertMatchesRegularExpression('/^#[0-9a-f]{6}$/i', $lighter);
    }

    public function test_darkens_color(): void
    {
        $original = '#3a5f8b';
        $darker = ColorThief::darkenColor($original, 20);

        $this->assertNotEquals($original, $darker);
        $this->assertMatchesRegularExpression('/^#[0-9a-f]{6}$/i', $darker);
    }
}

Integration Testing

public function test_extracts_colors_from_uploaded_image(): void
{
    Storage::fake('public');

    $file = UploadedFile::fake()->image('test.jpg', 600, 400);
    $path = $file->store('images', 'public');
    $fullPath = Storage::disk('public')->path($path);

    $color = ColorThief::getDominantColor($fullPath);
    $palette = ColorThief::getColorPalette($fullPath, 5);

    $this->assertIsString($color);
    $this->assertCount(5, $palette);
}

Troubleshooting

Image Not Found

Problem: Exception thrown when image path is invalid

Solution:

if (file_exists($imagePath)) {
    $color = ColorThief::getDominantColor($imagePath);
} else {
    Log::error("Image not found: {$imagePath}");
    $color = '#000000'; // Fallback
}

Memory Limit Exceeded

Problem: Large images cause memory errors

Solution:

// Resize image before color extraction
$image = Image::make($largePath)->resize(800, null, function ($constraint) {
    $constraint->aspectRatio();
});

$tempPath = storage_path('temp/resized.jpg');
$image->save($tempPath);

$color = ColorThief::getDominantColor($tempPath);

unlink($tempPath);

Slow Performance

Problem: Color extraction takes too long

Solutions:

  1. Use lower quality setting (higher number)
  2. Resize images before processing
  3. Sample smaller areas
  4. Process asynchronously
  5. Ensure caching is enabled
// Fast extraction
$color = ColorThief::getDominantColor($image, 10); // Quality 10 (fastest)

// Sample smaller area
$color = ColorThief::getDominantColor($image, 10, [0, 0, 200, 200]);

Invalid Color Output

Problem: Colors don't match visual appearance

Solutions:

  1. Use better quality setting (lower number)
  2. Sample specific areas instead of entire image
  3. Increase palette size for more options
// Better quality
$color = ColorThief::getDominantColor($image, 1);

// Sample relevant area
$color = ColorThief::getDominantColor($image, 5, [100, 100, 400, 400]);

Common Use Cases

Product Image Colors

class ProductService
{
    public function extractProductColors(Product $product): void
    {
        $imagePath = storage_path("app/public/{$product->image}");

        $product->update([
            'primary_color' => ColorThief::getDominantColor($imagePath),
            'color_palette' => ColorThief::getColorPalette($imagePath, 5),
        ]);
    }
}

Dynamic Theme Generation

class ThemeService
{
    public function generateThemeFromLogo(string $logoPath): array
    {
        $palette = ColorThief::getColorPalette($logoPath, 3);

        return [
            'primary' => $palette[0],
            'primary-light' => ColorThief::lightenColor($palette[0], 30),
            'primary-dark' => ColorThief::darkenColor($palette[0], 30),
            'secondary' => $palette[1],
            'accent' => $palette[2],
        ];
    }
}

Image Search by Color

class ImageSearchService
{
    public function findSimilarColorImages(string $targetColor): Collection
    {
        return Image::all()->filter(function ($image) use ($targetColor) {
            $imageColor = ColorThief::getDominantColor($image->path);
            return $this->colorDistance($imageColor, $targetColor) < 50;
        });
    }

    private function colorDistance(string $color1, string $color2): float
    {
        // Calculate color distance using RGB values
        // Implementation details...
    }
}

Related Packages

External Resources

License

MIT License - Part of the Pixielity Framework package.