PHPackages                             povly/moonshine-image-editor - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Image &amp; Media](/categories/media)
4. /
5. povly/moonshine-image-editor

ActiveLibrary[Image &amp; Media](/categories/media)

povly/moonshine-image-editor
============================

Image editor for MoonShine Media Manager powered by Filerobot

v1.3.0(3w ago)122↓100%MITPHPPHP ^8.2

Since May 17Pushed 3w agoCompare

[ Source](https://github.com/povly/moonshine-image-editor)[ Packagist](https://packagist.org/packages/povly/moonshine-image-editor)[ RSS](/packages/povly-moonshine-image-editor/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (6)Dependencies (4)Versions (7)Used By (0)

MoonShine Image Editor
======================

[](#moonshine-image-editor)

[![Preview](resources/images/preview.jpg)](resources/images/preview.jpg)

Image editor for [MoonShine](https://moonshine-laravel.com/) admin panel powered by [Filerobot Image Editor](https://github.com/scaleflex/filerobot-image-editor). Integrates with [MoonShine Media Manager](https://github.com/yurizoom/moonshine-media-manager) to provide in-browser image editing with automatic optimization and WebP/AVIF conversion.

Features
--------

[](#features)

- Full-featured image editor: adjust, annotate, crop, resize, rotate, filters, finetune, watermark
- Format selector (PNG/JPG) in modal toolbar — defaults to original format, separate from editor
- **Automatic optimization on upload** via Media Manager events — images are optimized and converted when uploaded through the file manager
- **Automatic cleanup on delete** — WebP/AVIF conversions are removed when the source image is deleted
- **Admin settings page** — manage optimization quality, conversion toggles, and queue settings directly from MoonShine panel (stored in DB)
- **Batch optimization** — scan and re-process existing images with real-time progress bar, detailed logs (webp vs original, avif vs webp), and file filter
- Optimization with size comparison (keeps smaller version)
- Optional WebP/AVIF conversion with size-aware cleanup
- Queue support for async processing
- Localization support (EN, RU) via Laravel lang files
- No CDN dependencies — all assets are local
- Imagick driver support with automatic fallback to GD
- Integrates as a file action button in Media Manager

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 11+ / 12+
- MoonShine 4.x
- `yurizoom/moonshine-media-manager` ^4.0
- `intervention/image-laravel` ^1.0 (installs `intervention/image` ^3.0 automatically)
- PHP Imagick extension (recommended) or GD

Installation
------------

[](#installation)

```
composer require povly/moonshine-image-editor
```

### Image Optimization Dependency

[](#image-optimization-dependency)

For image optimization and format conversion (WebP/AVIF) to work, install Intervention Image:

```
composer require intervention/image-laravel
```

> **Note:** Only `intervention/image-laravel` is needed — it automatically installs `intervention/image` as a dependency.

Publish the Intervention Image config (optional):

```
php artisan vendor:publish --provider="Intervention\Image\Laravel\ServiceProvider"
```

This creates `config/image.php` where you can set the default driver (GD or Imagick).

Publish assets:

```
php artisan vendor:publish --tag=image-editor-assets
```

Optionally publish config and translations:

```
php artisan vendor:publish --tag=image-editor-config --tag=image-editor-lang --force
```

Or everything at once:

```
php artisan vendor:publish --tag=image-editor-assets --tag=image-editor-config --tag=image-editor-lang --force
```

Run migrations (creates `image_editor_settings` table):

```
php artisan migrate
```

Setup
-----

[](#setup)

### 1. Register assets

[](#1-register-assets)

Add the package JS and CSS to your MoonShine layout's `assets()` method:

```
use MoonShine\AssetManager\Css;
use MoonShine\AssetManager\Js;

protected function assets(): array
{
    return [
        ...parent::assets(),
        Css::make('/vendor/image-editor/image-editor.css'),
        Js::make('/vendor/image-editor/filerobot-image-editor.min.js'),
        Js::make('/vendor/image-editor/image-editor.js'),
    ];
}
```

> **Note:** The built-in **Image Editor Settings** page automatically registers these assets when loaded, so you only need this step if you want the editor modal available on other pages (e.g., Media Manager).

### 2. Render the editor modal

[](#2-render-the-editor-modal)

Add the modal to your layout's `getContentComponents()` method:

```
use MoonShine\UI\Components\FlexibleRender;
use Povly\MoonShineImageEditor\Support\ImageEditorRenderer;

protected function getContentComponents(): array
{
    return [
        ...parent::getContentComponents(),
        FlexibleRender::make(
            app(ImageEditorRenderer::class)->renderModal(),
        ),
    ];
}
```

Alternatively, the legacy static helper still works:

```
FlexibleRender::make(
    \Povly\MoonShineImageEditor\ImageEditorServiceProvider::renderModal(),
);
```

The "Edit Image" button automatically appears in the Media Manager for image files. The listeners for upload optimization and delete cleanup are registered automatically — no additional setup required.

### 3. Image driver (recommended)

[](#3-image-driver-recommended)

For best PNG optimization, install the Imagick PHP extension:

```
# Arch / CachyOS
sudo pacman -S php-imagick
echo 'extension = imagick' | sudo tee /etc/php/conf.d/imagick.ini

# Ubuntu / Debian
sudo apt install php-imagick
```

The package auto-detects the driver — if Imagick is available it will be used, otherwise GD. You can also configure it explicitly in `config/image.php`:

```
return [
    'driver' => extension_loaded('imagick')
        ? \Intervention\Image\Drivers\Imagick\Driver::class
        : \Intervention\Image\Drivers\Gd\Driver::class,
];
```

> **Note:** GD cannot optimize PNG effectively — it often makes files larger. Imagick is strongly recommended for PNG support.

Configuration
-------------

[](#configuration)

Settings can be managed from the **MoonShine admin panel** (recommended) or via the config file. Database settings override config values at runtime.

Publish the config file (optional):

```
php artisan vendor:publish --tag=image-editor-config
```

```
// config/moonshine/image_editor.php
return [
    'available_formats' => ['png', 'jpg'],
    'quality' => ['jpg' => 82],
    'optimize' => [
        'enabled' => true,
        'strip_metadata' => true,
        'max_width' => null,
        'max_height' => null,
    ],
    'convert' => [
        'webp' => ['enabled' => false, 'quality' => 80],
        'avif' => ['enabled' => false, 'quality' => 65],
    ],
    'queue' => [
        'enabled' => false,
        'connection' => null,
        'queue' => 'images',
        'delay' => 60,
    ],
    'default_tabs' => ['Adjust', 'Annotate', 'Watermark', 'Finetune', 'Filters'],
    'default_tab' => null,
    'default_tool' => null,
    'overwrite_original' => false,
    'locale' => null,
    'theme' => [...],
    'watermark_gallery' => [],
];
```

### Config Options

[](#config-options)

OptionDefaultDescription`available_formats``['png', 'jpg']`Formats shown in the save dialog`quality.jpg``82`JPG quality (1–100). PNG is lossless, no quality setting.`optimize.enabled``true`Enable post-save optimization`optimize.strip_metadata``true`Strip EXIF/IPTC metadata`optimize.max_width``null`Max width (keeps aspect ratio)`optimize.max_height``null`Max height (keeps aspect ratio)`convert.webp.enabled``false`Generate WebP version`convert.webp.quality``80`WebP quality (1–100)`convert.avif.enabled``false`Generate AVIF version`convert.avif.quality``65`AVIF quality (1–100)`queue.enabled``false`Offload optimization to queue`queue.delay``60`Delay in seconds before processing`default_tabs``['Adjust', ...]`Visible editor tabs`overwrite_original``false`Overwrite original or save with `-edited` suffix`locale``null`Editor language (`null` = auto-detect)Localization
------------

[](#localization)

Translations are loaded from the package automatically. Supported languages:

- `en` — English (default)
- `ru` — Russian

To override translations, publish them:

```
php artisan vendor:publish --tag=image-editor-lang
```

Files will be published to `lang/vendor/image-editor/en/` and `lang/vendor/image-editor/ru/`.

How It Works
------------

[](#how-it-works)

### Image Editor

[](#image-editor)

1. User clicks the **"Edit Image"** button in Media Manager
2. A modal opens with the format selector toolbar and Filerobot Image Editor
3. The format selector defaults to the original image format
4. User edits the image (crop, filters, text, etc.)
5. On save, the selected format is used — image is uploaded to the same directory as the original
6. If `overwrite_original` is `false` (default), the file is saved with a `-edited` suffix
7. Post-save: optimization runs, WebP/AVIF generated if enabled
8. **Size comparison**: if optimized/conversion is larger → smaller version is kept

### Automatic Upload Optimization

[](#automatic-upload-optimization)

When a user uploads an image through the Media Manager:

1. `MediaManagerFileUploaded` event fires
2. `OptimizeUploadedImage` listener detects image files (jpg, png, gif, webp, avif)
3. Image is optimized (strip metadata, resize if configured)
4. WebP/AVIF versions generated if enabled
5. Supports queue for async processing

### Automatic Delete Cleanup

[](#automatic-delete-cleanup)

When a user deletes an image through the Media Manager:

1. `MediaManagerFileDeleted` event fires
2. `DeleteImageConversions` listener finds associated `.webp` and `.avif` files
3. Conversion files are removed automatically

### Size Comparison Logic

[](#size-comparison-logic)

```
Optimized file  ≥ original size?  → keep original
WebP            ≥ original size?  → delete WebP
AVIF            ≥ WebP size?      → delete AVIF
  (or ≥ original if no WebP)

```

### Admin Settings Page

[](#admin-settings-page)

The package adds a **"Image Editor Settings"** page to the MoonShine sidebar with two tabs:

#### Settings Tab

[](#settings-tab)

Configure optimization and conversion parameters stored in the database:

- **Quality** — JPG, WebP, AVIF quality (1–100)
- **Conversion** — enable/disable WebP and AVIF generation
- **Optimization** — strip metadata, max width/height
- **Queue** — enable async processing, delay

Settings are applied to the config at runtime on each request, so changes take effect immediately without editing config files.

#### Batch Optimization Tab

[](#batch-optimization-tab)

Re-process existing images with current settings:

1. Choose filter: **All images** (recreate conversions) or **Only without conversions** (skip files that already have webp/avif)
2. Scan files — shows count of matching originals (jpg/png/gif)
3. Start processing — runs via Laravel `Bus::batch` on the `images` queue
4. Real-time progress bar with processed/total counter
5. Detailed log showing per-file results:
    - Original: `photo.jpg (100 KB → 95 KB, -5%)`
    - WebP conversion: `→ photo.webp (95 KB → 50 KB, -47.4%, vs original)`
    - AVIF conversion: `→ photo.avif (50 KB → 30 KB, -40%, vs webp)`
    - Automatic deletion: `→ photo.webp deleted (larger than original)`

### Queue Worker Setup

[](#queue-worker-setup)

For batch processing (and async optimization), run a queue worker:

```
php artisan queue:work --queue=images
```

For production, use Supervisor to keep the worker running:

```
# /etc/supervisor/conf.d/moonshine-worker.conf
[program:moonshine-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/moonshine/artisan queue:work --queue=images --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
user=http
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/moonshine/storage/logs/worker.log
stopwaitsecs=3600
```

### Format Conversion Flow

[](#format-conversion-flow)

Filerobot always exports PNG regardless of the user's format choice. The server handles format conversion:

- **PNG → PNG**: re-encode to optimize file size (requires Imagick for effective compression)
- **PNG → JPG**: convert with configurable quality, progressive encoding, metadata stripping
- **JPG → PNG**: convert to lossless format
- **Same format**: optimize only (strip metadata, resize if configured)

Artisan Commands
----------------

[](#artisan-commands)

CommandDescription`image-editor:optimize {path} --disk=public --queue`Optimize a single image and generate conversions. Use `--queue` to dispatch async.`image-editor:clear-conversions --disk=public --path= --dry-run`Remove orphan WebP/AVIF files where the original image no longer exists. Use `--dry-run` to preview.`image-editor:reset-settings`Reset image editor settings stored in DB back to config defaults.```
# Optimize a single image
php artisan image-editor:optimize banners/photo.jpg

# Optimize on a specific disk, async
php artisan image-editor:optimize banners/photo.jpg --disk=s3 --queue

# Find orphan conversions in a directory
php artisan image-editor:clear-conversions --path=banners --dry-run

# Delete all orphan conversions
php artisan image-editor:clear-conversions

# Reset settings to defaults
php artisan image-editor:reset-settings
```

Security
--------

[](#security)

All controller endpoints are protected by MoonShine auth middleware. Additionally:

- **Settings whitelist** — only predefined keys are accepted (`quality`, `convert`, `optimize`, `queue`), unknown keys are silently ignored
- **Path traversal protection** — `../` and url-encoded variants are rejected in source paths
- **File type validation** — only image extensions (`jpg`, `jpeg`, `png`, `gif`, `webp`, `avif`) are processed
- **Batch limit** — max 500 files per batch operation
- **Settings validation** — quality values clamped to 1–100, dimensions capped at 10000px, types enforced

Publishing
----------

[](#publishing)

TagDescription`image-editor-assets`JS and CSS files to `public/vendor/image-editor/``image-editor-config`Config to `config/moonshine/image_editor.php``image-editor-lang`Translations to `lang/vendor/image-editor/``image-editor-migrations`Migrations to `database/migrations/`> **Note:** Migrations run automatically from the package via `loadMigrationsFrom()` when you run `php artisan migrate`. If you need to customize them or prefer having them in your project's `database/migrations/` directory, publish them explicitly:
>
> ```
> php artisan vendor:publish --tag=image-editor-migrations
> ```

License
-------

[](#license)

MIT

---

Related
-------

[](#related)

This package uses [Intervention Image](https://image.intervention.io/) for server-side image processing (optimization, format conversion, WebP/AVIF generation).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance95

Actively maintained with recent releases

Popularity11

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

6

Last Release

22d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c45731473f81a2d7789044af4e7d58c1497e64478298dee4b82a16c21dfb5c39?d=identicon)[povly](/maintainers/povly)

---

Top Contributors

[![povly](https://avatars.githubusercontent.com/u/48402954?v=4)](https://github.com/povly "povly (24 commits)")

---

Tags

imageoptimizationeditorWebpavifmoonshinefilerobot

### Embed Badge

![Health badge](/badges/povly-moonshine-image-editor/health.svg)

```
[![Health](https://phpackages.com/badges/povly-moonshine-image-editor/health.svg)](https://phpackages.com/packages/povly-moonshine-image-editor)
```

###  Alternatives

[intervention/image-laravel

Laravel Integration of Intervention Image

1558.1M158](/packages/intervention-image-laravel)[intervention/image-driver-vips

libvips driver for Intervention Image

47144.1k10](/packages/intervention-image-driver-vips)[joshembling/image-optimizer

Optimize your Filament images before they reach your database.

112157.3k12](/packages/joshembling-image-optimizer)[danihidayatx/image-optimizer

Optimize your Filament images before they reach your database. Forked from joshembling/image-optimizer for Filament v4 &amp; v5 support.

3113.6k](/packages/danihidayatx-image-optimizer)[somehow-digital/typo3-media-processing

Media Processing

121.2k](/packages/somehow-digital-typo3-media-processing)[yurizoom/moonshine-media-manager

Media manager for MoonShine

111.8k1](/packages/yurizoom-moonshine-media-manager)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
