mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-14 07:27:47 +00:00
Color palette support in byos_laravel
This commit is contained in:
parent
c157dcf3b6
commit
9ee7bc1aac
7 changed files with 236 additions and 4 deletions
|
|
@ -9,6 +9,7 @@ enum ImageFormat: string
|
|||
case BMP3_1BIT_SRGB = 'bmp3_1bit_srgb';
|
||||
case PNG_8BIT_256C = 'png_8bit_256c';
|
||||
case PNG_2BIT_4C = 'png_2bit_4c';
|
||||
case PNG_INDEXED = 'png_indexed';
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
|
|
@ -18,6 +19,7 @@ enum ImageFormat: string
|
|||
self::BMP3_1BIT_SRGB => 'BMP3 1-bit sRGB 2c',
|
||||
self::PNG_8BIT_256C => 'PNG 8-bit Grayscale Gray 256c',
|
||||
self::PNG_2BIT_4C => 'PNG 2-bit Grayscale 4c',
|
||||
self::PNG_INDEXED => 'PNG indexed',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
app/Enums/PaletteName.php
Normal file
31
app/Enums/PaletteName.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Bnussbau\TrmnlPipeline\Data\RgbColor;
|
||||
use InvalidArgumentException;
|
||||
|
||||
enum PaletteName: string
|
||||
{
|
||||
case SPECTRA_6 = 'spectra_6';
|
||||
|
||||
/**
|
||||
* @return RgbColor[]
|
||||
*/
|
||||
public static function getPalette(PaletteName $palette): array
|
||||
{
|
||||
switch ($palette) {
|
||||
case PaletteName::SPECTRA_6:
|
||||
return [
|
||||
RgbColor::fromComponents(0, 0, 0),
|
||||
RgbColor::fromComponents(255, 255, 255),
|
||||
RgbColor::fromComponents(255, 255, 0),
|
||||
RgbColor::fromComponents(255, 0, 0),
|
||||
RgbColor::fromComponents(0, 255, 0),
|
||||
RgbColor::fromComponents(0, 0, 255),
|
||||
];
|
||||
default:
|
||||
throw new InvalidArgumentException('Invalid palette name');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
final class DeviceModel extends Model
|
||||
{
|
||||
|
|
@ -25,6 +26,11 @@ final class DeviceModel extends Model
|
|||
'published_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function palette(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Palette::class);
|
||||
}
|
||||
|
||||
public function getColorDepthAttribute(): ?string
|
||||
{
|
||||
if (! $this->bit_depth) {
|
||||
|
|
|
|||
32
app/Models/Palette.php
Normal file
32
app/Models/Palette.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
|
||||
/**
|
||||
* Palette model representing color palettes used by device models.
|
||||
*
|
||||
* @property int $id
|
||||
* @property string $name
|
||||
* @property string $description
|
||||
* @property string $palette JSON single dimension array where each entry is a 24-bit number
|
||||
* representing the RGB color code.
|
||||
*/
|
||||
final class Palette extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
protected $guarded = ['id'];
|
||||
|
||||
public function deviceModels(): HasMany
|
||||
{
|
||||
return $this->hasMany(DeviceModel::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ use App\Enums\ImageFormat;
|
|||
use App\Models\Device;
|
||||
use App\Models\DeviceModel;
|
||||
use App\Models\Plugin;
|
||||
use Bnussbau\TrmnlPipeline\Data\ColorType;
|
||||
use Bnussbau\TrmnlPipeline\Data\RgbColor;
|
||||
use Bnussbau\TrmnlPipeline\Stages\BrowserStage;
|
||||
use Bnussbau\TrmnlPipeline\Stages\ImageStage;
|
||||
use Bnussbau\TrmnlPipeline\TrmnlPipeline;
|
||||
|
|
@ -66,16 +68,21 @@ class ImageGenerationService
|
|||
->width($imageSettings['width'])
|
||||
->height($imageSettings['height'])
|
||||
->colors($imageSettings['colors'])
|
||||
->colorType($imageSettings['color_type'])
|
||||
->bitDepth($imageSettings['bit_depth'])
|
||||
->rotation($imageSettings['rotation'])
|
||||
->offsetX($imageSettings['offset_x'])
|
||||
->offsetY($imageSettings['offset_y'])
|
||||
->outputPath($outputPath);
|
||||
|
||||
// Apply dithering if requested by markup
|
||||
$shouldDither = self::markupContainsDitherImage($markup);
|
||||
if ($shouldDither) {
|
||||
$imageStage->dither();
|
||||
// TODO: actually resolve this merge conflict
|
||||
// // Apply dithering if requested by markup
|
||||
// $shouldDither = self::markupContainsDitherImage($markup);
|
||||
// if ($shouldDither) {
|
||||
// $imageStage->dither();
|
||||
// }
|
||||
if ($imageSettings['palette']) {
|
||||
$imageStage->palette($imageSettings['palette']);
|
||||
}
|
||||
|
||||
(new TrmnlPipeline())->pipe($browserStage)
|
||||
|
|
@ -110,11 +117,20 @@ class ImageGenerationService
|
|||
if ($device->deviceModel) {
|
||||
/** @var DeviceModel $model */
|
||||
$model = $device->deviceModel;
|
||||
$paletteRecord = $model->palette()->firstOr();
|
||||
$palette = null;
|
||||
if ($paletteRecord) {
|
||||
$palette = array_map(
|
||||
fn ($colorCode) => new RgbColor($colorCode),
|
||||
json_decode($paletteRecord->palette)
|
||||
);
|
||||
}
|
||||
|
||||
return [
|
||||
'width' => $model->width,
|
||||
'height' => $model->height,
|
||||
'colors' => $model->colors,
|
||||
'color_type' => ColorType::fromString($model->color_type),
|
||||
'bit_depth' => $model->bit_depth,
|
||||
'scale_factor' => $model->scale_factor,
|
||||
'rotation' => $model->rotation,
|
||||
|
|
@ -123,6 +139,7 @@ class ImageGenerationService
|
|||
'offset_y' => $model->offset_y,
|
||||
'image_format' => self::determineImageFormatFromModel($model),
|
||||
'use_model_settings' => true,
|
||||
'palette' => $palette,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -153,6 +170,9 @@ class ImageGenerationService
|
|||
private static function determineImageFormatFromModel(DeviceModel $model): string
|
||||
{
|
||||
// Map DeviceModel settings to ImageFormat
|
||||
if ($model->mime_type === 'image/png' && $model->palette()) {
|
||||
return ImageFormat::PNG_INDEXED->value;
|
||||
}
|
||||
if ($model->mime_type === 'image/bmp' && $model->bit_depth === 1) {
|
||||
return ImageFormat::BMP3_1BIT_SRGB->value;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue