Download the PHP package asignua/filament-image-annotations without Composer

On this page you can find all versions of the php package asignua/filament-image-annotations. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package filament-image-annotations

Filament Image Annotations

Filament Image Annotations

Stand With Ukraine Tests

Draw arrows, rectangles, ellipses, lines, freehand pen strokes, a highlighter and text over any image in a Filament 5 panel, without touching the file. The annotations are a separate, tiny JSON layer in their own table: the original image is never modified, the markup can be edited or removed at any time, and the same layer can be shown read-only anywhere, in the panel or on your public site.

Screenshots

The editor: toolbar, colours and shapes over a photo

An annotate button next to every stored image of an upload

The read-only view with the show/hide toggle

Dark mode:

The editor in dark mode

Requirements

Optional: spatie/laravel-medialibrary and filament/spatie-laravel-media-library-plugin for Media Library images.

Installation

The service provider is auto-discovered. Registering the plugin on a panel is optional (it adds nothing yet):

The editor and the viewer are small Alpine components that are only downloaded by a page that uses them. Optionally publish the config (--tag=filament-image-annotations-config) and the translations (--tag=filament-image-annotations-translations).

Usage

Every entry point takes the image through ->image(...): an ImageSource, a Spatie Media, any class you registered (see Image sources), or a Closure returning one (it may take the usual $record). A Closure returning null means "no image here" and the button hides itself.

AnnotateImageAction: a button that opens the editor

It opens a full-screen modal with the editor, pre-filled with the stored layer; Save annotations writes it. The button is hidden for a record without an image and for a user who may not annotate it. Inside an ActionGroup it works like any other row action.

AnnotatedImageEntry: read-only view

The picture with the layer on top and a Show / Hide annotations toggle (with a count). With no layer, or for a viewer who may not see it, it is the plain picture. Without ->image() the entry's own state is the image.

<x-image-annotations::image>: anywhere

The same viewer for any Blade view, see Front end.

AnnotatedUpload: an Annotate button per file of an upload

A list appears under the upload: one row per stored image with a thumbnail, the name, the number of shapes (when there are any) and an Annotate button that opens the same editor as the action. Files that are not images are skipped.

ImageAnnotator: the editor as a form field

The state is the layer ({"v":1,"items":[...]}) and is sanitised on dehydrate. Use it in a custom page, wizard step or your own action. Saving is on you: call ImageAnnotations::store()->save($source, $user, $state).

Reading and writing from code

The editor

Tool Key Notes
Select / move V Click a shape to select it, drag to move it. Colour and width changes apply to the selection.
Arrow A Shift snaps to 45 degrees.
Rectangle R Drag any direction; Shift for a square.
Ellipse E Shift for a circle.
Line L Shift snaps to 45 degrees.
Pen P Freehand, smoothed.
Highlighter H A wide, translucent stroke.
Text T Click, type; Enter adds, Shift+Enter is a new line, Esc cancels.
Pin N A numbered marker; each click places the next number. Off by default, see Extending.
Shortcut Action
Ctrl/Cmd + Z Undo
Ctrl/Cmd + Shift + Z or Ctrl + Y Redo
Delete / Backspace Delete the selected shape

Eight colours, three stroke widths, Clear all (click twice to confirm). Mouse, touch and stylus all work; every button has an accessible name and aria-pressed.

Image sources

An ImageSource tells the plugin which image it is, where it lives and who may touch it:

Built in: Sources\MediaImageSource (a Spatie Media) and Sources\ModelPathImageSource ($record, $path, $disk). Both can be told how to build the URL (a signed or CDN URL, a private disk):

Teach the plugin your own image class, so ->image($thing) and <x-image-annotations::image :image="$thing"> accept it:

Extend Sources\AbstractImageSource to get the standard authorization (below) and implement owner().

Authorization

The default rule, for every source:

Replace the rule globally, once, for example in a service provider:

AnnotationStore::save() checks canAnnotate itself and throws AuthorizationException, so a forged request cannot bypass the buttons being hidden.

Configuration

config/filament-image-annotations.php:

Key Default
table image_annotations Table name.
palette 8 colours Ordered name => #hex. The first one is the fallback for an unknown colour.
widths [2, 4, 8] The three stroke widths of the toolbar; the middle one is the default.
limits.shapes 200 Shapes per image. The editor stops drawing and says so; the sanitiser drops the rest.
limits.points 2000 Points of one pen / highlighter stroke.
limits.text 500 Characters of a text shape.
user_model null The model of user_id; null = the default auth provider's model.

Stored format

One row per image: annotatable (morph), key (the file path for a file in a column, NULL for an image that is its own model), user_id (the last editor, no foreign key), shapes (JSON, written unescaped so Cyrillic text stays readable).

Coordinates are normalised 0..1 relative to the image, so the layer fits any size the image is shown at. Types: arrow, line, rect, ellipse (two points), pen, highlight (2 to limits.points points), text (one point and a non-empty text).

Support\ShapeSanitizer runs on everything that is saved or displayed, it never throws and drops what it cannot fix:

Text is never HTML-escaped on the way in, it is stored as typed and rendered with textContent, so <script> stays the literal text <script>.

Events and cleanup

The trait removes the rows on a hard delete only; a soft-deleted record can come back with its annotations.

Front end

<x-image-annotations::image> and AnnotatedImageEntry render the image, an <svg> overlay and a toggle. The layer is passed as escaped JSON in a data-layers attribute ([{key, label, color, items}]) and drawn by an Alpine component. With two or more layers a chip per layer appears next to the show/hide toggle.

On a public page the viewer needs Alpine and Filament's asset route (the component is fetched with x-load from Filament's assets, run php artisan filament:assets). Without them the plain image renders: no overlay, nothing broken. The component also checks canView for the current user; without permission it renders the plain image too, and the layer is not put in the page at all.

If your public pages cache HTML for everybody, remember the layer is rendered per viewer.

Pro

A paid Pro package is planned, built on the hooks already here (AnnotationStore is a singleton you can rebind, and user_id is kept for it):

Coming soon.

Extending

The free package is the base of the Pro one (layers per author, numbered pins with threads); these are the seams, all inert until something uses them.

Layers. AnnotationStore::layers($source, $user) returns a list<Support\Layer> (key, label, color, items, editable, meta). Free returns one layer, default, editable when the user may annotate. Rebind the store to return more: the viewer draws every layer with a chip each, and AnnotateImageAction passes the non-editable ones to the editor as read-only underlays (drawn below, not selectable, never saved into the state; visibility toggles are client-side only). Use them on a hand-built field with ImageAnnotator::make('x')->underlays([...])->layerKey('mine'). ImageAnnotations::layersFor($image) is the permission-aware list of non-empty layers.

Tools. The toolbar comes from config tools (default: all but pin) or per field: ImageAnnotator::make('x')->tools(['select', 'arrow', 'pin']).

Pins. Shape pin: one point plus an integer n (1..999). The sanitizer drops a pin with a missing or out-of-range n and renumbers duplicates within a layer to max + 1. A pin renders as a filled circle with a white number and carries data-id and data-pin on its SVG group. The pin tool (key N) places the highest number + 1.

JS events (bubbling CustomEvents, nothing in the free package listens to them):

Event detail Fired
image-annotations:pin-click {layer, id, n} click on a pin in the viewer, or with the select tool in the editor
image-annotations:change {items} every committed change in the editor (draw, move, undo, ...)
image-annotations:pin-added {id, n} the pin tool placed a pin
document.addEventListener('image-annotations:pin-click', (e) => openThread(e.detail.layer, e.detail.n))

Side panels. ImageAnnotations::addPanel(fn (ImageSource $source, string $context) => $html) adds HTML next to the editor canvas ($context = 'editor') and next to the annotated image in the viewer ('viewer'); return null for no panel. The panels and the canvas share a container marked data-ia-scope, so a panel can tell which events belong to its image. Nothing changes visually while no panel is registered.

Saved event. After a successful save AnnotateImageAction dispatches the Livewire event image-annotations:saved (ImageAnnotations::SAVED_EVENT) with image = ImageAnnotations::imageId($source), a non-secret sha1("morph class|id|key"). Anything on the page that shows annotation data (a pro panel, your own Livewire component) listens with #[On('image-annotations:saved')]; the Pro pin panel always re-reads, you may compare the id to filter.

Hidden by default. A layer whose meta['hidden'] is true starts switched off (its chip is still there).

Gotchas

Demo

A workbench is included (a post with a Media Library photo and a note with a plain FileUpload, both with the editor):

APP_URL must carry the port you serve on, or image URLs point to the wrong place.

Log in at /admin as [email protected] / password ([email protected] may not touch Alice's post). Inside Docker, publish a port for the container first.

Translations

The interface ships in English, Ukrainian, German, Spanish, French, Italian, Dutch, Polish, Brazilian Portuguese and Turkish under the filament-image-annotations::filament-image-annotations namespace. A test keeps every language in step with the English keys. Override a string by publishing the translations (--tag=filament-image-annotations-translations) and editing the copy in lang/vendor/filament-image-annotations.

AI agents

The package ships Laravel Boost guidelines (resources/boost/guidelines/core.blade.php) so a coding agent wires it up correctly.

Testing

Changelog

See CHANGELOG.md.

License

The MIT License (MIT). See LICENSE.md.


All versions of filament-image-annotations with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
filament/filament Version ^5.0
illuminate/contracts Version ^12.0|^13.0
spatie/laravel-package-tools Version ^1.16
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package asignua/filament-image-annotations contains the following files

Loading the files please wait ...