ksubileau/color-thief-php
Extract dominant colors and palettes from images in PHP. Color Thief PHP ports the MMCQ algorithm and works with GD, Imagick, or Gmagick. Supports JPEG, PNG, GIF, and WebP, and accepts paths, URLs, resources, objects, or binary data.
## Getting Started
### Minimal Setup
1. **Installation**:
```bash
composer require ksubileau/color-thief-php
Ensure your server has GD, Imagick, or Gmagick installed (required for image processing).
First Use Case: Extract the dominant color from an image (e.g., for dynamic UI themes or accent colors):
use ColorThief\ColorThief;
// Path to image (local or remote URL)
$dominantColor = ColorThief::getColor('/path/to/image.jpg');
// Returns: array([r, g, b]) e.g., [253, 42, 152]
Key Files:
vendor/ksubileau/color-thief-php/src/ColorThief.php: Core class.vendor/ksubileau/color-thief-php/tests/: Test cases for edge cases (e.g., corrupted images, CMYK).Dynamic Theming:
Use getColor() to fetch a dominant color for CSS variables or UI elements:
$hexColor = ColorThief::getColor($imagePath, quality: 5, outputFormat: 'hex');
echo "<div style='background-color: {$hexColor};'>...</div>";
Color Palettes: Generate a palette for design tools or filters:
$palette = ColorThief::getPalette($imagePath, colorCount: 5);
// Returns: array([r1,g1,b1], [r2,g2,b2], ...)
Area-Specific Colors: Extract colors from a region (e.g., product images):
$area = ['x' => 100, 'y' => 50, 'w' => 200, 'h' => 150];
$localColor = ColorThief::getColor($imagePath, area: $area);
Adapter Selection: Force a specific image processor (e.g., for performance or CMYK support):
// Use Imagick (better for CMYK)
$color = ColorThief::getColor($imagePath, adapter: 'Imagick');
Laravel Blade: Cache results in a service provider to avoid reprocessing:
// app/Providers/AppServiceProvider.php
public function boot()
{
view()->composer('*', function ($view) {
$view->with('dominantColor', ColorThief::getColor(storage_path('app/image.jpg')));
});
}
Queue Jobs: Offload heavy processing (e.g., palette generation) to a queue:
// app/Jobs/GeneratePalette.php
public function handle()
{
$palette = ColorThief::getPalette($this->imagePath, colorCount: 10);
// Store in DB or cache
}
Validation: Sanitize image paths/URLs to prevent SSRF or path traversal:
use Illuminate\Support\Facades\Storage;
$imagePath = Storage::path('uploads/' . $request->validated('image'));
Memory Limits:
quality (e.g., 1) + large images may hit PHP’s memory_limit.quality: 5 and adjust based on server limits.memory_get_usage():
$start = memory_get_usage();
$color = ColorThief::getColor($imagePath, quality: 1);
$usage = memory_get_usage() - $start; // Check if > 100MB
Corrupted Images:
RuntimeException if GD/Imagick fails to load.try {
$color = ColorThief::getColor($imagePath);
} catch (\ColorThief\Exception\Exception $e) {
Log::error("Invalid image: {$imagePath}");
return response()->json(['error' => 'Invalid image'], 400);
}
CMYK Images:
adapter: 'Imagick' or ensure GD is compiled with CMYK support.Remote URLs:
allow_url_fopen is disabled.file_get_contents() with a stream context or a library like Guzzle:
$imageData = file_get_contents($remoteUrl, false, stream_context_create([
'http' => ['timeout' => 10]
]));
$color = ColorThief::getColor($imageData);
Solid Color Images:
$palette = ColorThief::getPalette($imagePath, colorCount: 5);
if (count(array_unique($palette)) === 1) {
$palette = [/* fallback palette */];
}
Log Adapter Choice:
Override ColorThief to log which adapter is used:
ColorThief::getColor($imagePath, adapter: 'Gd'); // Force GD for debugging
Profile Performance:
Use microtime() to measure execution time:
$start = microtime(true);
$color = ColorThief::getColor($imagePath, quality: 1);
$time = microtime(true) - $start; // Log if > 1s
Visual Validation: Compare results with the JavaScript Color Thief for consistency.
Custom Adapters:
Implement AdapterInterface for custom image sources (e.g., AWS S3):
class S3Adapter implements AdapterInterface {
public function load($source) { /* ... */ }
public function getImageWidth($image) { /* ... */ }
// ... other required methods
}
ColorThief::getColor($s3Path, adapter: new S3Adapter());
Post-Processing:
Use the Color object for advanced operations:
$colorObj = ColorThief::getColor($imagePath, outputFormat: 'obj');
$brightness = $colorObj->getBrightness(); // Custom method
Caching:
Cache results by image hash (e.g., md5(file_get_contents($path))):
$cacheKey = 'color:' . md5($imagePath);
$color = Cache::remember($cacheKey, now()->addHours(1), function () use ($imagePath) {
return ColorThief::getColor($imagePath);
});
Testing:
Mock the ColorThief class in unit tests:
$mock = Mockery::mock('overload:' . ColorThief::class);
$mock->shouldReceive('getColor')->andReturn([255, 0, 0]);
PHP Extensions:
if (!extension_loaded('gd') && !extension_loaded('imagick')) {
throw new \RuntimeException('No image processing extensions found.');
}
Output Formats:
hex is URL-safe (use for CSS/JS).rgb is human-readable (e.g., rgb(255, 0, 0)).obj enables custom methods (e.g., getHue()).Quality vs. Speed:
1: High accuracy, slow (use for static assets).10: Fast, lower accuracy (use for dynamic content).ColorThief::getColor($imagePath, quality: X).
```markdown
### Example: Full Laravel Controller
```php
use ColorThief\ColorThief;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class ImageController extends Controller
{
public function getDominantColor(Request $request)
{
$imagePath = $request->validate(['image' => 'required|image'])->file('image')->store('temp');
$cacheKey = 'color:' . md5($imagePath);
$color = Cache::remember($cacheKey, now()->addMinutes(30), function () use ($image
How can I help you explore Laravel packages today?