A production-ready Laravel 11 CLI application for automated flambient photography processing with ImageMagick local blending and Imagen AI cloud enhancement.
Flambient Photography: A real estate photography technique combining ambient (natural light) and flash (artificial light) exposures using advanced blending to create perfectly balanced, professional interior photos.
- Features
- Architecture
- Installation
- Quick Start
- Usage
- Configuration
- Testing
- Project Structure
- API Documentation
- Future Improvements
- Contributing
Local Processing: - โ Flexible EXIF Classification - Choose from 6+ fields (Flash, Exposure Mode, White Balance, ISO, etc.) - โ Dual EXIF Extraction - Numeric values for logic + human-readable labels for display - โ Smart Image Grouping - Automatic pairing of ambient/flash sequences by timestamp - โ ImageMagick Blending - 7-step flambient algorithm with customizable parameters - โ Batch Processing - Handle hundreds of images efficiently
Cloud Enhancement (Optional): - โ Imagen AI Integration - Native PHP client for automated cloud enhancement - โ Progress Tracking - Real-time upload/processing/download progress with emojis - โ Automatic Polling - Monitor AI processing until completion (up to 2 hours) - โ JPEG Export - Automatic conversion and download of enhanced images - โ Resume Capability - Save project UUID to database for later access
- โ Laravel Prompts - Beautiful interactive CLI with validation
- โ Type Safety - PHP 8.2+ read only classes, backed enums
- โ Database State - SQLite tracks all workflow execution
- โ Comprehensive Testing - 46 PHPUnit tests with 100% Http::fake() coverage
- โ Error Handling - Graceful failures with actionable messages
- โ Configurable - Environment-based settings with sane defaults
- โ State Machine - 8-step workflow with explicit transitions
- โ Audit Trail - Database logging of all operations
- โ Progress Indicators - Spinners, tables, emoji status updates
- โ Resumable - Pause/resume long-running operations
- โ Testable - Mock all external dependencies (exiftool, ImageMagick, Imagen API)
This application represents a complete architectural redesign from fragile shell scripts to a robust, Laravel-native system with a plugin-based architecture for image processing techniques.
<<<<<<< HEAD
- Plugin Architecture - Modular script generators for different processing techniques
- Explicit State Management - All workflow state persisted to SQLite
- Type Safety - Enums, DTOs, readonly classes throughout
- Separation of Concerns - Services for EXIF, ImageMagick, Imagen AI
- Laravel-Native - HTTP client, Prompts, Collections, Eloquent
- Testability - All external dependencies mockable
The application uses a ScriptGeneratorInterface pattern allowing multiple image processing techniques:
FlambientProcessCommand
โ
ScriptGeneratorRegistry โ [FlambientGenerator, HDRGenerator, DMECGenerator, ...]
โ
ImageMagickService (generic executor)
Benefits:
- โ Add new processing techniques without modifying core code
- โ Each technique is self-contained with its own configuration
- โ Easy to test individual generators independently
- โ Future-proof for new ImageMagick workflows =======
- Explicit State Management - All workflow state persisted to SQLite
- Type Safety - Enums, DTOs, readonly classes throughout
- Separation of Concerns - Services for EXIF, ImageMagick, Imagen AI
- Laravel-Native - HTTP client, Prompts, Collections, Eloquent
- Testability - All external dependencies mockable
origin/main
| Step | Name | Purpose | Skippable |
|---|---|---|---|
| 1 | Prepare | Validate inputs, create workspace | โ |
| 2 | Analyze | Extract EXIF, classify & group images | โ |
| 3 | Process | Generate & execute ImageMagick scripts | โ |
| 4 | Upload | Upload blended images to Imagen AI | โ
--local |
| 5 | Edit | Submit for AI enhancement | โ
--local |
| 6 | Monitor | Poll processing status | โ
--local |
| 7 | Export | Convert to JPEG format | โ
--local |
| 8 | Download | Retrieve enhanced images | โ
--local |
workflow_runs
โโโ id (UUID primary key)
โโโ project_name (string, unique)
โโโ config (JSON snapshot)
โโโ status (pending|running|completed|failed|paused)
โโโ imagen_project_uuid (nullable)
โโโ total_images_processed, total_groups_created
workflow_steps
โโโ workflow_run_id (foreign key)
โโโ step_name (prepare|analyze|process|upload|monitor|export|download|finalize)
โโโ status, input_data, output_data (JSON)
โโโ duration_seconds, retry_count
workflow_files
โโโ workflow_run_id (foreign key)
โโโ original_path, processed_path
โโโ file_type (ambient|flash|blended)
โโโ exif_data (JSON)- PHP 8.2+ with SQLite extension
- Composer for dependency management
- ImageMagick (
magickcommand available) - exiftool for EXIF metadata extraction
- Imagen AI API key (optional, for cloud enhancement)
# 1. Clone repository
git clone https://github.com/davepeloso/flambient.git
cd terminal-flazsh
# 2. Install dependencies
composer install
# 3. Configure environment
cp .env.example .env
php artisan key:generate
# 4. Set up database
touch database/database.sqlite
php artisan migrate
# 5. (Optional) Configure Imagen AI
# Edit .env and add:
# IMAGEN_AI_API_KEY=your_key_here
# IMAGEN_PROFILE_KEY=309406# Check PHP version
php -v # Should be 8.2+
# Check ImageMagick
magick -version
# Check exiftool
exiftool -ver
# Run tests
php artisan testphp artisan flambient:process \
--project="(date '+%m-%d-%y')_ID$(gshuf -i 10000-99999 -n 1)" \
--dir="public/123-main-street" \
--local
echo "$(date '+%m-%d-%y')_ID$(gshuf -i 10000-99999 -n 1)"
ID="$(date '+%m-%d-%y')_ID$(gshuf -i 10000-99999 -n 1)"
echo "$ID"This will: 1. Extract EXIF metadata from your images 2. Classify images as Ambient or Flash based on EXIF fields 3. Group images by timestamp 4. Generate ImageMagick blend scripts 5. Create blended flambient images in storage/flambient/my-first-shoot/flambient/
php artisan flambient:process \
--project="real-estate-shoot" \
--dir="/path/to/images"This will: 1. Perform local ImageMagick blending (steps 1-3) 2. Upload blended images to Imagen AI (step 4) 3. Monitor AI processing with real-time progress (step 5-6) 4. Export and download enhanced images (steps 7-8) 5. Save both blended and enhanced versions locally
Simply run without arguments for a guided experience:
php artisan flambient:processThe CLI will interactively prompt for: - Project name - Image directory - EXIF classification strategy - Processing mode (local vs. cloud)
php artisan flambient:process [options]
Options:
--project=NAME Project name (unique identifier)
--dir=PATH Directory containing JPG images
--output=PATH Output directory (default: storage/flambient/{project})
--local Skip cloud processing (ImageMagick only)During analysis, you'll choose which EXIF field to use for classifying Ambient vs. Flash:
โ Which EXIF field should identify Ambient images? โโโโโ
โ โ Flash (Flash = 16 for Ambient) โ
โ โ Exposure Program โ
โ โ Exposure Mode โ
โ โ White Balance โ
โ โ ISO Value โ
โ โ Shutter Speed โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Choose the field that differs between your ambient and flash shots
You can optionally view sample EXIF data first:
โ How many sample images to display? โโโโโโโโโโโโโโโโโโโโ
โ โ 3 samples โ
โ โ 5 samples โ
โ โ 10 samples โ
โ โ 25 samples โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโ
โ Filename โ Flash โ ExposureProgram โ ExposureMode โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโค
โ IMG_001.jpg โ 16 (No Flash) โ 1 (Manual) โ 0 (Auto) โ
โ IMG_002.jpg โ 0 (Flash Fired) โ 2 (Program AE) โ 1 (Manual) โ
โ IMG_003.jpg โ 16 (No Flash) โ 1 (Manual) โ 0 (Auto) โ
โโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโ
Step 1/3: Preparing workspace
โ ง Validating inputs and creating directories...
โ Workspace created: /storage/flambient/my-shoot
Step 2/3: Analyzing images
โ ง Extracting EXIF metadata and grouping images...
โ Classified 54 images into 27 groups (9 Ambient, 18 Flash)
Step 3/3: Processing with ImageMagick
โ ง Generating and executing ImageMagick scripts...
โ Created 27 blended images in 8.5s
Steps 4-8: Skipped (local-only mode - Imagen AI processing disabled)
โ Processing complete!
Output: /storage/flambient/my-shoot/flambient/
Images: 27
Step 4/8: Upload to Imagen AI
โ This will upload 27 blended images to Imagen AI for enhancement.
โ Proceed with Imagen AI upload and processing? โโโโโ
โ โ Yes / โ No โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ง Creating Imagen AI project...
โ Project created: abc-123-def-456
View at: https://app.imagen-ai.com/projects/abc-123-def-456
Uploading 27 images to Imagen AI...
Uploaded 5/27: flambient_01.jpg
Uploaded 10/27: flambient_05.jpg
โ Upload complete: 27/27 files (100% success)
Step 6/8: Monitoring AI processing
This typically takes 10-30 minutes depending on image count.
โณ Processing: 0% - queued
๐ Processing: 25% - editing
โก Processing: 50% - editing
๐ Processing: 90% - editing
๐ Processing: 100% - completed
โ AI editing complete!
Step 8/8: Downloading enhanced images
Downloaded 5/27: edited_01.jpg
Downloaded 10/27: edited_05.jpg
โ Download complete: 27/27 files (100% success)
Output: /storage/flambient/my-shoot/edited/
๐ Workflow Complete SUCCESS
โโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Metric โ Value โ
โโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Project Name โ my-shoot โ
โ Total Duration โ 25 minutes โ
โ Images Processedโ 54 โ
โ Groups Created โ 27 โ
โ Blended Output โ /storage/.../flambient/ โ
โ Enhanced Output โ /storage/.../edited/ โ
โ Imagen Project โ abc-123-def-456 โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐จ Blended images: /storage/flambient/my-shoot/flambient/
โจ Enhanced images: /storage/flambient/my-shoot/edited/
๐ Imagen project: https://app.imagen-ai.com/projects/abc-123-def-456
Edit .env to configure:
IMAGEN_AI_API_KEY=your_api_key_here
IMAGEN_API_BASE_URL=https://api-beta.imagen-ai.com/v1
IMAGEN_PROFILE_KEY=309406
IMAGEN_TIMEOUT=30
IMAGEN_POLL_INTERVAL=30 # Seconds between status checks
IMAGEN_POLL_MAX_ATTEMPTS=240 # Max attempts (240 ร 30s = 2 hours)IMAGEMAGICK_BINARY=magick
IMAGEMAGICK_LEVEL_LOW=40% # Ambient mask threshold
IMAGEMAGICK_LEVEL_HIGH=140% # Ambient mask upper bound
IMAGEMAGICK_GAMMA=1.0 # Gamma correction
IMAGEMAGICK_OUTPUT_PREFIX=flambient
IMAGEMAGICK_DARKEN_EXPORT=false # Export darkened flash composite
IMAGEMAGICK_DARKEN_SUFFIX=_tmpFLAMBIENT_STORAGE_PATH= # Default: storage/flambient
FLAMBIENT_KEEP_TEMP=false # Keep temporary files
FLAMBIENT_PARALLEL_UPLOADS=5 # Concurrent uploads
FLAMBIENT_PARALLEL_DOWNLOADS=5 # Concurrent downloadsAdvanced settings in config/flambient.php:
return [
'imagen' => [
'api_key' => env('IMAGEN_AI_API_KEY'),
'base_url' => env('IMAGEN_API_BASE_URL', 'https://api-beta.imagen-ai.com/v1'),
'profile_key' => env('IMAGEN_PROFILE_KEY', 309406),
'timeout' => env('IMAGEN_TIMEOUT', 30),
'poll_interval' => env('IMAGEN_POLL_INTERVAL', 30),
'poll_max_attempts' => env('IMAGEN_POLL_MAX_ATTEMPTS', 240),
],
'imagemagick' => [
'level_low' => env('IMAGEMAGICK_LEVEL_LOW', '40%'),
'level_high' => env('IMAGEMAGICK_LEVEL_HIGH', '140%'),
'gamma' => env('IMAGEMAGICK_GAMMA', '1.0'),
],
];php artisan testExpected output:
PASS Tests\Unit\ExifServiceTest
โ it extracts exif metadata from images
โ it classifies images using flash strategy
โ it classifies images using exposure program strategy
... (11 tests)
PASS Tests\Unit\ImageMagickServiceTest
โ it generates imagemagick scripts for groups
โ it generates correct mgk script content
... (9 tests)
PASS Tests\Unit\ImagenClientTest
โ it creates a project
โ it handles create project failure
... (18 tests)
PASS Tests\Feature\FlambientProcessCommandTest
โ it processes flambient workflow end to end
โ it allows selecting different classification strategies
... (8 tests)
Tests: 46 passed (117 assertions)
Duration: 2.34s
# EXIF extraction and classification
php artisan test --filter=ExifServiceTest
# ImageMagick script generation
php artisan test --filter=ImageMagickServiceTest
# Imagen AI client
php artisan test --filter=ImagenClientTest
# End-to-end workflow
php artisan test --filter=FlambientProcessCommandTestThe test suite covers:
- โ EXIF extraction (numeric + pretty)
- โ Image classification (6 strategies)
- โ Image grouping by timestamp
- โ ImageMagick script generation
- โ Imagen AI client (all endpoints)
- โ Upload/download with progress
- โ Polling with status tracking
- โ End-to-end workflow command
- โ Error handling and retries
- โ Success rate calculations
All external dependencies (exiftool, ImageMagick, Imagen API) are mocked using Process::fake() and Http::fake().
terminal-flazsh/
โโโ app/
โ โโโ Console/Commands/
โ โ โโโ FlambientProcessCommand.php # Main interactive CLI
โ โ
โ โโโ DataObjects/
โ โ โโโ WorkflowConfig.php # Immutable configuration DTO
โ โ โโโ ProcessingResult.php # Step result DTO
โ โ
โ โโโ Enums/
โ โ โโโ WorkflowStatus.php # Workflow states
โ โ โโโ StepName.php # Workflow steps
โ โ โโโ ImageType.php # ambient|flash|blended
โ โ โโโ ImageClassificationStrategy.php # EXIF field selection
โ โ
โ โโโ Models/
โ โ โโโ WorkflowRun.php # Main workflow record
โ โ โโโ WorkflowStep.php # Individual step tracking
โ โ โโโ WorkflowFile.php # Processed file tracking
โ โ
โ โโโ Providers/
โ โ โโโ ImageProcessorServiceProvider.php # Register script generators
โ โ
โ โโโ Services/
โ โ โโโ ImageProcessor/ # NEW: Plugin-based architecture
โ โ โ โโโ Contracts/
โ โ โ โ โโโ ScriptGeneratorInterface.php # Generator contract
โ โ โ โโโ Generators/
โ โ โ โ โโโ FlambientGenerator.php # Flambient technique
โ โ โ โ โโโ HDRMergeGenerator.php # HDR (future)
โ โ โ โ โโโ FocusStackGenerator.php # Focus stacking (future)
โ โ โ โ โโโ DMECGenerator.php # D-MEC technique (future)
โ โ โ โโโ ExifService.php # EXIF extraction & classification
โ โ โ โโโ ImageMagickService.php # Generic script executor
โ โ โ โโโ ScriptGeneratorRegistry.php # Generator management
โ โ โ
โ โ โโโ ImagenAI/
โ โ โโโ ImagenClient.php # Complete API client
โ โ โโโ ImagenException.php # Custom exception
โ โ โโโ DTOs.php # All Imagen DTOs & enums
โ โ
โ โโโ ...
โ
โโโ config/
โ โโโ flambient.php # Centralized configuration
โ
โโโ database/
โ โโโ database.sqlite # SQLite database
โ โโโ migrations/
โ โโโ *_create_workflow_runs_table.php
โ โโโ *_create_workflow_steps_table.php
โ โโโ *_create_workflow_files_table.php
โ
โโโ tests/
โ โโโ Unit/
โ โ โโโ ExifServiceTest.php # 11 tests
โ โ โโโ ImageMagickServiceTest.php # 9 tests
โ โ โโโ ImagenClientTest.php # 18 tests
โ โ
โ โโโ Feature/
โ โโโ FlambientProcessCommandTest.php # 8 tests
โ
โโโ ARCHITECTURE_REDESIGN.md # Original architectural analysis
โโโ IMAGEN_INTEGRATION.md # Imagen AI integration guide
โโโ README.md # This file
To add a new image processing technique, implement ScriptGeneratorInterface:
use App\Services\ImageProcessor\Contracts\ScriptGeneratorInterface;
class MyCustomGenerator implements ScriptGeneratorInterface
{
public function getKey(): string
{
return 'my-custom'; // Unique identifier
}
public function getName(): string
{
return 'My Custom Technique';
}
public function getDescription(): string
{
return 'Description of what this technique does';
}
public function getClassificationStrategy(): ?string
{
return 'flash'; // or 'exposure_program', 'custom', null
}
public function getConfigurationSchema(): array
{
return [
'parameter_one' => [
'type' => 'text',
'label' => 'Parameter One',
'default' => '100%',
'description' => 'What this parameter controls',
],
];
}
public function generateScript(
array $images,
array $config,
string $outputPath
): string {
// Build your ImageMagick script here
$script = [];
$script[] = "# My Custom Processing";
$script[] = "( " . implode(" ", $images['ambient']) . " )";
$script[] = "-write \"{$outputPath}\"";
return implode("\n", $script);
}
}Then register it in ImageProcessorServiceProvider:
public function register(): void
{
$this->app->singleton(ScriptGeneratorRegistry::class, function () {
$registry = new ScriptGeneratorRegistry();
$registry->register(new FlambientGenerator());
$registry->register(new MyCustomGenerator()); // Add your generator
return $registry;
});
}<<<<<<< HEAD
use App\Services\ImageProcessor\ExifService;
=======
``` php
use App\Services\Flambient\ExifService;
>>>>>>> origin/main
use App\Enums\ImageClassificationStrategy;
$service = new ExifService(
strategy: ImageClassificationStrategy::ExposureMode,
ambientValue: 0 // Auto = Ambient
);
// Extract EXIF with both numeric and human-readable values
$metadata = $service->extractMetadata('/path/to/images');
// Get sample values for user preview
$samples = $service->getSampleExifValues('/path/to/images', count: 10);
// Group images by ambient/flash sequences
$groups = $service->groupImages($metadata);<<<<<<< HEAD
use App\Services\ImageProcessor\ImageMagickService;
use App\Services\ImageProcessor\ScriptGeneratorRegistry;
=======
``` php
use App\Services\Flambient\ImageMagickService;
>>>>>>> origin/main
$service = new ImageMagickService(binary: 'magick');
$registry = app(ScriptGeneratorRegistry::class);
// Get a generator
$generator = $registry->get('flambient');
// Generate .mgk scripts for all groups
$scripts = $service->generateScripts(
generator: $generator,
groups: $groups,
config: ['level_low' => '40%', 'level_high' => '140%'],
imageDirectory: '/path/to/images',
scriptsDirectory: '/path/to/scripts',
outputDirectory: '/path/to/output'
);
// Execute all scripts
$result = $service->executeAllScripts('/path/to/scripts');
// Returns: ['success' => true, 'output' => '...', 'error' => '...']use App\Services\ImagenAI\ImagenClient;
use App\Services\ImagenAI\ImagenEditOptions;
use App\Services\ImagenAI\ImagenPhotographyType;
$client = new ImagenClient();
// Quick workflow (all-in-one)
$result = $client->quickEdit(
filePaths: ['/path/to/flambient_01.jpg', ...],
profileKey: '309406',
outputDirectory: '/path/to/output',
editOptions: new ImagenEditOptions(
crop: true,
windowPull: true,
photographyType: ImagenPhotographyType::REAL_ESTATE
)
);
// Or step-by-step:
$project = $client->createProject('My Shoot');
$uploadResult = $client->uploadImages($project->uuid, $filePaths);
$client->startEditing($project->uuid, '309406');
$editStatus = $client->pollEditStatus($project->uuid);
$client->exportProject($project->uuid);
$exportLinks = $client->getExportLinks($project->uuid);
$downloadResult = $client->downloadFiles($exportLinks, '/output');For complete API reference, see: - IMAGEN_INTEGRATION.md - Imagen AI client guide - ARCHITECTURE_REDESIGN.md - Architectural overview
<<<<<<< HEAD Current: Plugin architecture implemented with Flambient generator Status: โ Ready to add new generators - infrastructure complete!
The plugin architecture is now live! Adding new processing techniques is as simple as:
- Create a new class implementing
ScriptGeneratorInterface - Register it in
ImageProcessorServiceProvider - No core code changes needed!
Potential Generators to Add:
HDRMergeGenerator- HDR tone mapping with multiple exposuresDMECGenerator- Dissimilar Multiple Exposure Composition (cherry-pick attributes)WindowPullGenerator- Specialized window light enhancementFocusStackGenerator- Focus stacking for deep depth of fieldPerspectiveFixGenerator- Vertical/horizontal correctionFlashBalanceGenerator- Auto-balance flash intensityCustomGenerator- User-defined .mgk script templates
Example Implementation:
See the "Creating a New Generator" section in API Documentation for a complete example.
Migration to Generic Command (Optional Phase 4):
# Future: Generic command with technique selection
php artisan process:images --technique=flambient
php artisan process:images --technique=hdr-merge
php artisan process:images --technique=dmec
# Current: Flambient-specific command (works with plugin architecture)
php artisan flambient:process --local
=======
**Current:** Single flambient blend algorithm **Future:** Multiple processing profiles to choose from
``` bash
php artisan flambient:process --profile=hdr-merge
php artisan flambient:process --profile=window-pull
php artisan flambient:process --profile=flash-balance
php artisan flambient:process --profile=customPotential Profiles: - flambient (default) - Standard ambient/flash blend - hdr-merge - HDR tone mapping with multiple exposures - window-pull - Specialized window light enhancement - flash-balance - Auto-balance flash intensity - perspective-fix - Vertical/horizontal correction - custom - User-defined .mgk script templates
Implementation Plan:
// app/Enums/ProcessingProfile.php
enum ProcessingProfile: string {
case Flambient = 'flambient';
case HdrMerge = 'hdr-merge';
case WindowPull = 'window-pull';
case FlashBalance = 'flash-balance';
public function getScriptTemplate(): string;
public function getDefaultParams(): array;
}
// app/Services/Flambient/ScriptGenerator.php
class ScriptGenerator {
public function generate(ProcessingProfile $profile, array $params): string;
}
>>>>>>> origin/mainCurrent: Post-processing of existing JPGs Future: Live ingestion during wireless camera tethering
# Watch mode - monitor Capture One output folder
php artisan flambient:watch \
--capture-one-session=/path/to/session \
--auto-process \
--interval=30s
# Output:
โ ง Watching for new images...
โ Detected IMG_001.jpg (Ambient)
โ Detected IMG_002.jpg (Flash)
โก Auto-processing group 1 (2 images)
โ Blended: flambient_01.jpgFeatures: - File watcher - Monitor Capture One Capture folder - Real-time classification - Instant EXIF analysis on import - Auto-grouping - Smart pairing based on shoot sequence - Progressive processing - Process groups as they complete - Live preview - Optional web server for client viewing - Pause/resume - Control processing during shoot - Backup strategy - Copy originals before processing
Implementation Plan:
// app/Console/Commands/FlambientWatchCommand.php
class FlambientWatchCommand extends Command {
protected $signature = 'flambient:watch
{--capture-one-session= : Capture One session folder}
{--auto-process : Auto-process complete groups}
{--interval=30s : Check interval}';
public function handle() {
$watcher = new CaptureOneWatcher(
sessionPath: $this->option('capture-one-session'),
autoProcess: $this->option('auto-process')
);
$watcher->watch();
}
}
// app/Services/CaptureOne/CaptureOneWatcher.php
class CaptureOneWatcher {
public function watch(): void {
while (true) {
$newFiles = $this->detectNewFiles();
$completeGroups = $this->findCompleteGroups($newFiles);
if ($this->autoProcess && !empty($completeGroups)) {
$this->processGroups($completeGroups);
}
sleep($this->interval);
}
}
private function detectNewFiles(): array;
private function findCompleteGroups(array $files): array;
private function processGroups(array $groups): void;
}
// app/Services/CaptureOne/SessionParser.php
class SessionParser {
public function parseSession(string $path): CaptureOneSession;
public function getCaptureFolder(): string;
public function getOutputSettings(): array;
}Capture One Session Structure:
CaptureOneSession/
โโโ Capture/ # New images appear here
โ โโโ IMG_001.jpg
โ โโโ IMG_002.jpg
โ โโโ ...
โโโ Output/ # Processed images (optional)
โโโ Cache/ # Capture One metadata
โโโ Settings/ # Session settings
Benefits: - โ Faster turnaround - Process during shoot, not after - โ Immediate feedback - See blended results in real-time - โ Client preview - Show progress to clients on-site - โ Reduce post-processing - Images ready when shoot ends - โ Better organization - Auto-naming and grouping
# 1. Create feature branch
git checkout -b feature/my-feature
# 2. Make changes and add tests
# Edit app/Services/...
# Edit tests/Unit/...
# 3. Run tests
php artisan test
# 4. Format code
./vendor/bin/pint
# 5. Commit and push
git add .
git commit -m "feat: add my feature"
git push origin feature/my-feature
# 6. Create pull request- PSR-12 coding style (enforced by Laravel Pint)
- Type safety - Use type hints, return types, readonly classes
- Test coverage - Add tests for all new features
- Documentation - Update README and inline docs
- Laravel conventions - Follow Laravel best practices
All new features must include: - โ Unit tests for services/classes - โ Feature tests for commands - โ Mock external dependencies (Http::fake(), Process::fake()) - โ Assertions for success and failure cases
MIT License - see LICENSE for details
- Laravel Framework - Elegant PHP framework
- Laravel Prompts - Beautiful CLI interactions
- ImageMagick - Image processing powerhouse
- Imagen AI - Cloud-based photo enhancement
- ExifTool - Comprehensive EXIF metadata extraction
For issues, questions, or feature requests:
- GitHub Issues: Create an issue
- Documentation: See
/docsfolder for detailed guides - Architecture: Read ARCHITECTURE_REDESIGN.md <<<<<<< HEAD
- Refactoring Plan: Read docs/refactoring-plan.md
- Imagen Integration: Read IMAGEN_INTEGRATION.md
Major Refactoring: Transformed from tightly-coupled Flambient-only processing to a modular, plugin-based architecture.
What Changed:
โ New Plugin System
ScriptGeneratorInterface- Contract for all processing techniquesScriptGeneratorRegistry- Central registry for generatorsFlambientGenerator- Extracted flambient logic into a pluginImageProcessorServiceProvider- Service provider for generator registration
โ Refactored Services
- Moved from
App\Services\Flambient\*toApp\Services\ImageProcessor\* ImageMagickServicenow generic (accepts any generator)ExifServicemoved to ImageProcessor namespaceFlambientProcessCommandupdated to use registry pattern
โ Backwards Compatible
- Existing
php artisan flambient:processcommand still works - Same workflow and CLI experience
- No breaking changes for users
Benefits:
- ๐ฏ Add new techniques without modifying core code
- ๐งฉ Each technique is self-contained and testable
- ๐ Easy to implement D-MEC, HDR, Focus Stacking, etc.
- ๐ฆ Future-proof architecture for growth
See: docs/refactoring-plan.md for complete implementation details.
=======
- Imagen Integration: Read IMAGEN_INTEGRATION.md
origin/main
Built with โค๏ธ using Laravel 11, PHP 8.2, and modern development practices
Production-ready flambient photography automation for professional photographers