mirror of
https://github.com/immich-app/immich.git
synced 2026-01-25 19:04:42 -08:00
feat: web editor
This commit is contained in:
@@ -994,6 +994,7 @@
|
||||
"editor_close_without_save_prompt": "The changes will not be saved",
|
||||
"editor_close_without_save_title": "Close editor?",
|
||||
"editor_confirm_reset_all_changes": "Are you sure you want to reset all changes?",
|
||||
"editor_filters": "Filters",
|
||||
"editor_flip_horizontal": "Flip horizontal",
|
||||
"editor_flip_vertical": "Flip vertical",
|
||||
"editor_orientation": "Orientation",
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
) {
|
||||
return 'ImagePanaramaViewer';
|
||||
}
|
||||
if (assetViewerManager.isShowEditor && editManager.selectedTool?.type === EditToolType.Transform) {
|
||||
if (assetViewerManager.isShowEditor) {
|
||||
return 'CropArea';
|
||||
}
|
||||
return 'PhotoViewer';
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { websocketEvents } from '$lib/stores/websocket';
|
||||
import { getAssetEdits, type AssetResponseDto } from '@immich/sdk';
|
||||
import { Button, HStack, IconButton } from '@immich/ui';
|
||||
import { mdiClose } from '@mdi/js';
|
||||
import { mdiClose, mdiCrop, mdiPalette } from '@mdi/js';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
|
||||
onMount(async () => {
|
||||
const edits = await getAssetEdits({ id: asset.id });
|
||||
await editManager.activateTool(EditToolType.Transform, asset, edits);
|
||||
await editManager.init(asset, edits);
|
||||
editManager.activateTool(EditToolType.Transform);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
editManager.cleanup();
|
||||
onDestroy(async () => {
|
||||
await editManager.cleanup();
|
||||
});
|
||||
|
||||
async function applyEdits() {
|
||||
@@ -65,6 +66,31 @@
|
||||
<Button shape="round" size="small" onclick={applyEdits} loading={editManager.isApplyingEdits}>{$t('save')}</Button>
|
||||
</HStack>
|
||||
|
||||
<HStack class="mt-4 gap-0 mx-4">
|
||||
<Button
|
||||
leadingIcon={mdiCrop}
|
||||
variant={editManager.selectedTool?.type === EditToolType.Transform ? 'filled' : 'outline'}
|
||||
onclick={() => editManager.activateTool(EditToolType.Transform)}
|
||||
class="rounded-r-none"
|
||||
shape="round"
|
||||
size="small"
|
||||
fullWidth
|
||||
>
|
||||
Transform
|
||||
</Button>
|
||||
<Button
|
||||
leadingIcon={mdiPalette}
|
||||
variant={editManager.selectedTool?.type === EditToolType.Filter ? 'filled' : 'outline'}
|
||||
onclick={() => editManager.activateTool(EditToolType.Filter)}
|
||||
class="rounded-l-none"
|
||||
shape="round"
|
||||
size="small"
|
||||
fullWidth
|
||||
>
|
||||
Filter
|
||||
</Button>
|
||||
</HStack>
|
||||
|
||||
<section>
|
||||
{#if editManager.selectedTool}
|
||||
<editManager.selectedTool.component />
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<script lang="ts">
|
||||
import { editManager } from '$lib/managers/edit/edit-manager.svelte';
|
||||
import { filterManager } from '$lib/managers/edit/filter-manager.svelte';
|
||||
import { getAssetMediaUrl } from '$lib/utils';
|
||||
import { filters } from '$lib/utils/filters';
|
||||
import { AssetMediaSize } from '@immich/sdk';
|
||||
import { Text } from '@immich/ui';
|
||||
import { t } from 'svelte-i18n';
|
||||
|
||||
let asset = $derived(editManager.currentAsset);
|
||||
</script>
|
||||
|
||||
<div class="mt-3 px-4">
|
||||
<div class="flex h-10 w-full items-center justify-between text-sm mt-2">
|
||||
<h2>{$t('editor_filters')}</h2>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-3 gap-4 mt-2">
|
||||
{#if asset}
|
||||
{#each filters as filter (filter.name)}
|
||||
{@const isSelected = filterManager.selectedFilter === filter}
|
||||
<button type="button" onclick={() => filterManager.selectFilter(filter)} class="flex flex-col items-center">
|
||||
<div class="w-20 h-20 rounded-md overflow-hidden {isSelected ? 'ring-3 ring-immich-primary' : ''}">
|
||||
<img
|
||||
src={getAssetMediaUrl({
|
||||
id: asset.id,
|
||||
cacheKey: asset.thumbhash,
|
||||
edited: false,
|
||||
size: AssetMediaSize.Thumbnail,
|
||||
})}
|
||||
alt="{filter.name} thumbnail"
|
||||
class="w-full h-full object-cover"
|
||||
style="filter: url(#{filter.cssId})"
|
||||
/>
|
||||
</div>
|
||||
<Text size="small" class="mt-1" color={isSelected ? 'primary' : undefined}>{filter.name}</Text>
|
||||
</button>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" style="position:absolute">
|
||||
<defs>
|
||||
{#each filters as filter (filter.name)}
|
||||
<filter id={filter.cssId} color-interpolation-filters="sRGB">
|
||||
<feColorMatrix type="matrix" values={filter.svgFilter} />
|
||||
</filter>
|
||||
{/each}
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { filterManager } from '$lib/managers/edit/filter-manager.svelte';
|
||||
import { transformManager } from '$lib/managers/edit/transform-manager.svelte';
|
||||
import { getAssetMediaUrl } from '$lib/utils';
|
||||
import { getAltText } from '$lib/utils/thumbnail-util';
|
||||
@@ -78,6 +79,14 @@
|
||||
bind:this={transformManager.overlayEl}
|
||||
></div>
|
||||
</button>
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" style="position:absolute">
|
||||
<defs>
|
||||
<filter id="currentFilter" color-interpolation-filters="sRGB">
|
||||
<feColorMatrix type="matrix" values={filterManager.selectedFilter.svgFilter} />
|
||||
</filter>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
@@ -150,6 +159,7 @@
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
transition: transform 0.15s ease;
|
||||
filter: url(#currentFilter);
|
||||
}
|
||||
|
||||
.crop-frame {
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
import FilterTool from '$lib/components/asset-viewer/editor/filter-tool/filter-tool.svelte';
|
||||
import TransformTool from '$lib/components/asset-viewer/editor/transform-tool/transform-tool.svelte';
|
||||
import { filterManager } from '$lib/managers/edit/filter-manager.svelte';
|
||||
import { transformManager } from '$lib/managers/edit/transform-manager.svelte';
|
||||
import { waitForWebsocketEvent } from '$lib/stores/websocket';
|
||||
import { editAsset, removeAssetEdits, type AssetEditsDto, type AssetResponseDto } from '@immich/sdk';
|
||||
import { ConfirmModal, modalManager, toastManager } from '@immich/ui';
|
||||
import { mdiCropRotate } from '@mdi/js';
|
||||
import { ConfirmModal, modalManager, toastManager, type MaybePromise } from '@immich/ui';
|
||||
import { mdiCropRotate, mdiPalette } from '@mdi/js';
|
||||
import type { Component } from 'svelte';
|
||||
|
||||
export type EditAction = AssetEditsDto['edits'][number];
|
||||
export type EditActions = EditAction[];
|
||||
|
||||
export interface EditToolManager {
|
||||
onActivate: (asset: AssetResponseDto, edits: EditActions) => Promise<void>;
|
||||
onDeactivate: () => void;
|
||||
resetAllChanges: () => Promise<void>;
|
||||
onActivate: (asset: AssetResponseDto, edits: EditActions) => MaybePromise<void>;
|
||||
onDeactivate: () => MaybePromise<void>;
|
||||
resetAllChanges: () => MaybePromise<void>;
|
||||
hasChanges: boolean;
|
||||
edits: EditAction[];
|
||||
}
|
||||
|
||||
export enum EditToolType {
|
||||
Transform = 'transform',
|
||||
Filter = 'filter',
|
||||
}
|
||||
|
||||
export interface EditTool {
|
||||
@@ -36,6 +39,12 @@ export class EditManager {
|
||||
component: TransformTool,
|
||||
manager: transformManager,
|
||||
},
|
||||
{
|
||||
type: EditToolType.Filter,
|
||||
icon: mdiPalette,
|
||||
component: FilterTool,
|
||||
manager: filterManager,
|
||||
},
|
||||
];
|
||||
|
||||
currentAsset = $state<AssetResponseDto | null>(null);
|
||||
@@ -69,32 +78,32 @@ export class EditManager {
|
||||
return confirmed;
|
||||
}
|
||||
|
||||
reset() {
|
||||
async reset() {
|
||||
for (const tool of this.tools) {
|
||||
tool.manager.onDeactivate?.();
|
||||
await tool.manager.onDeactivate?.();
|
||||
}
|
||||
this.selectedTool = this.tools[0];
|
||||
}
|
||||
|
||||
async activateTool(toolType: EditToolType, asset: AssetResponseDto, edits: AssetEditsDto) {
|
||||
this.hasAppliedEdits = false;
|
||||
if (this.selectedTool?.type === toolType) {
|
||||
return;
|
||||
}
|
||||
|
||||
async init(asset: AssetResponseDto, edits: AssetEditsDto) {
|
||||
this.currentAsset = asset;
|
||||
|
||||
this.selectedTool?.manager.onDeactivate?.();
|
||||
for (const tool of this.tools) {
|
||||
await tool.manager.onActivate?.(asset, edits.edits);
|
||||
}
|
||||
this.selectedTool = this.tools[0];
|
||||
}
|
||||
|
||||
activateTool(toolType: EditToolType) {
|
||||
const newTool = this.tools.find((t) => t.type === toolType);
|
||||
if (newTool) {
|
||||
this.selectedTool = newTool;
|
||||
await newTool.manager.onActivate?.(asset, edits.edits);
|
||||
}
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
async cleanup() {
|
||||
for (const tool of this.tools) {
|
||||
tool.manager.onDeactivate?.();
|
||||
await tool.manager.onDeactivate?.();
|
||||
}
|
||||
this.currentAsset = null;
|
||||
this.selectedTool = null;
|
||||
|
||||
42
web/src/lib/managers/edit/filter-manager.svelte.ts
Normal file
42
web/src/lib/managers/edit/filter-manager.svelte.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { EditActions, EditToolManager } from '$lib/managers/edit/edit-manager.svelte';
|
||||
import { EditFilter, filters } from '$lib/utils/filters';
|
||||
import { AssetEditAction, type AssetEditActionFilter, type AssetResponseDto, type FilterParameters } from '@immich/sdk';
|
||||
|
||||
class FilterManager implements EditToolManager {
|
||||
selectedFilter: EditFilter = $state(filters[0]);
|
||||
|
||||
hasChanges = $derived(!this.selectedFilter.isIdentity);
|
||||
edits = $derived<EditActions>(
|
||||
this.hasChanges
|
||||
? [
|
||||
{
|
||||
action: AssetEditAction.Filter,
|
||||
parameters: this.selectedFilter.dtoParameters,
|
||||
} as AssetEditActionFilter,
|
||||
]
|
||||
: [],
|
||||
);
|
||||
|
||||
resetAllChanges() {
|
||||
this.selectedFilter = filters[0];
|
||||
}
|
||||
|
||||
onActivate(asset: AssetResponseDto, edits: EditActions) {
|
||||
const filterEdits = edits.filter((edit) => edit.action === AssetEditAction.Filter);
|
||||
if (filterEdits.length > 0) {
|
||||
const dtoFilter = EditFilter.fromDto(filterEdits[0].parameters as FilterParameters, 'Custom');
|
||||
this.selectedFilter = filters.find((filter) => filter.equals(dtoFilter)) ?? filters[0];
|
||||
}
|
||||
}
|
||||
|
||||
onDeactivate() {
|
||||
this.resetAllChanges();
|
||||
}
|
||||
|
||||
selectFilter(filter: EditFilter) {
|
||||
this.selectedFilter = filter;
|
||||
console.log('Selected filter:', filter);
|
||||
}
|
||||
}
|
||||
|
||||
export const filterManager = new FilterManager();
|
||||
218
web/src/lib/utils/filters.ts
Normal file
218
web/src/lib/utils/filters.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import type { FilterParameters } from '@immich/sdk';
|
||||
|
||||
export class EditFilter {
|
||||
name: string;
|
||||
|
||||
rrBias: number;
|
||||
rgBias: number;
|
||||
rbBias: number;
|
||||
grBias: number;
|
||||
ggBias: number;
|
||||
gbBias: number;
|
||||
brBias: number;
|
||||
bgBias: number;
|
||||
bbBias: number;
|
||||
|
||||
rOffset: number;
|
||||
gOffset: number;
|
||||
bOffset: number;
|
||||
|
||||
static identity = new EditFilter('Normal', 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
|
||||
|
||||
constructor(
|
||||
name: string,
|
||||
rrBias: number,
|
||||
rgBias: number,
|
||||
rbBias: number,
|
||||
grBias: number,
|
||||
ggBias: number,
|
||||
gbBias: number,
|
||||
brBias: number,
|
||||
bgBias: number,
|
||||
bbBias: number,
|
||||
rOffset: number,
|
||||
gOffset: number,
|
||||
bOffset: number,
|
||||
) {
|
||||
this.name = name;
|
||||
this.rrBias = rrBias;
|
||||
this.rgBias = rgBias;
|
||||
this.rbBias = rbBias;
|
||||
this.grBias = grBias;
|
||||
this.ggBias = ggBias;
|
||||
this.gbBias = gbBias;
|
||||
this.brBias = brBias;
|
||||
this.bgBias = bgBias;
|
||||
this.bbBias = bbBias;
|
||||
this.rOffset = rOffset;
|
||||
this.gOffset = gOffset;
|
||||
this.bOffset = bOffset;
|
||||
}
|
||||
|
||||
get dtoParameters(): FilterParameters {
|
||||
return {
|
||||
rrBias: this.rrBias,
|
||||
rgBias: this.rgBias,
|
||||
rbBias: this.rbBias,
|
||||
grBias: this.grBias,
|
||||
ggBias: this.ggBias,
|
||||
gbBias: this.gbBias,
|
||||
brBias: this.brBias,
|
||||
bgBias: this.bgBias,
|
||||
bbBias: this.bbBias,
|
||||
rOffset: this.rOffset,
|
||||
gOffset: this.gOffset,
|
||||
bOffset: this.bOffset,
|
||||
};
|
||||
}
|
||||
|
||||
get svgFilter(): string {
|
||||
return `
|
||||
${this.rrBias} ${this.rgBias} ${this.rbBias} 0 ${this.rOffset}
|
||||
${this.grBias} ${this.ggBias} ${this.gbBias} 0 ${this.gOffset}
|
||||
${this.brBias} ${this.bgBias} ${this.bbBias} 0 ${this.bOffset}
|
||||
0 0 0 1 0
|
||||
`;
|
||||
}
|
||||
|
||||
static fromDto(params: FilterParameters, name: string): EditFilter {
|
||||
return new EditFilter(
|
||||
name,
|
||||
params.rrBias,
|
||||
params.rgBias,
|
||||
params.rbBias,
|
||||
params.grBias,
|
||||
params.ggBias,
|
||||
params.gbBias,
|
||||
params.brBias,
|
||||
params.bgBias,
|
||||
params.bbBias,
|
||||
params.rOffset,
|
||||
params.gOffset,
|
||||
params.bOffset,
|
||||
);
|
||||
}
|
||||
|
||||
static fromMatrix(matrix: number[], name: string): EditFilter {
|
||||
return new EditFilter(
|
||||
name,
|
||||
matrix[0],
|
||||
matrix[1],
|
||||
matrix[2],
|
||||
matrix[5],
|
||||
matrix[6],
|
||||
matrix[7],
|
||||
matrix[10],
|
||||
matrix[11],
|
||||
matrix[12],
|
||||
matrix[15],
|
||||
matrix[16],
|
||||
matrix[17],
|
||||
);
|
||||
}
|
||||
|
||||
get isIdentity(): boolean {
|
||||
return this.equals(EditFilter.identity);
|
||||
}
|
||||
|
||||
equals(other: EditFilter): boolean {
|
||||
return (
|
||||
this.rrBias === other.rrBias &&
|
||||
this.rgBias === other.rgBias &&
|
||||
this.rbBias === other.rbBias &&
|
||||
this.grBias === other.grBias &&
|
||||
this.ggBias === other.ggBias &&
|
||||
this.gbBias === other.gbBias &&
|
||||
this.brBias === other.brBias &&
|
||||
this.bgBias === other.bgBias &&
|
||||
this.bbBias === other.bbBias &&
|
||||
this.rOffset === other.rOffset &&
|
||||
this.gOffset === other.gOffset &&
|
||||
this.bOffset === other.bOffset
|
||||
);
|
||||
}
|
||||
|
||||
get cssId(): string {
|
||||
return this.name.toLowerCase().replaceAll(/\s+/g, '-');
|
||||
}
|
||||
}
|
||||
|
||||
export const filters: EditFilter[] = [
|
||||
//Original
|
||||
EditFilter.fromMatrix([1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0], 'Original'),
|
||||
//Vintage
|
||||
EditFilter.fromMatrix([0.8, 0.1, 0.1, 0, 20, 0.1, 0.8, 0.1, 0, 20, 0.1, 0.1, 0.8, 0, 20, 0, 0, 0, 1, 0], 'Vintage'),
|
||||
//Mood
|
||||
EditFilter.fromMatrix([1.2, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 10, 0, 0, 0, 1, 0], 'Mood'),
|
||||
//Crisp
|
||||
EditFilter.fromMatrix([1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1, 0], 'Crisp'),
|
||||
//Cool
|
||||
EditFilter.fromMatrix([0.9, 0, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0], 'Cool'),
|
||||
//Blush
|
||||
EditFilter.fromMatrix([1.1, 0.1, 0.1, 0, 10, 0.1, 1, 0.1, 0, 10, 0.1, 0.1, 1, 0, 5, 0, 0, 0, 1, 0], 'Blush'),
|
||||
//Sunkissed
|
||||
EditFilter.fromMatrix([1.3, 0, 0.1, 0, 15, 0, 1.1, 0.1, 0, 10, 0, 0, 0.9, 0, 5, 0, 0, 0, 1, 0], 'Sunkissed'),
|
||||
//Fresh
|
||||
EditFilter.fromMatrix([1.2, 0, 0, 0, 20, 0, 1.2, 0, 0, 20, 0, 0, 1.1, 0, 20, 0, 0, 0, 1, 0], 'Fresh'),
|
||||
//Classic
|
||||
EditFilter.fromMatrix([1.1, 0, -0.1, 0, 10, -0.1, 1.1, 0.1, 0, 5, 0, -0.1, 1.1, 0, 0, 0, 0, 0, 1, 0], 'Classic'),
|
||||
//Lomo-ish
|
||||
EditFilter.fromMatrix([1.5, 0, 0.1, 0, 0, 0, 1.45, 0, 0, 0, 0.1, 0, 1.3, 0, 0, 0, 0, 0, 1, 0], 'Lomo-ish'),
|
||||
//Nashville
|
||||
EditFilter.fromMatrix(
|
||||
[1.2, 0.15, -0.15, 0, 15, 0.1, 1.1, 0.1, 0, 10, -0.05, 0.2, 1.25, 0, 5, 0, 0, 0, 1, 0],
|
||||
'Nashville',
|
||||
),
|
||||
//Valencia
|
||||
EditFilter.fromMatrix([1.15, 0.1, 0.1, 0, 20, 0.1, 1.1, 0, 0, 10, 0.1, 0.1, 1.2, 0, 5, 0, 0, 0, 1, 0], 'Valencia'),
|
||||
//Clarendon
|
||||
EditFilter.fromMatrix([1.2, 0, 0, 0, 10, 0, 1.25, 0, 0, 10, 0, 0, 1.3, 0, 10, 0, 0, 0, 1, 0], 'Clarendon'),
|
||||
//Moon
|
||||
EditFilter.fromMatrix(
|
||||
[0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0.33, 0.33, 0.33, 0, 0, 0, 0, 0, 1, 0],
|
||||
'Moon',
|
||||
),
|
||||
//Willow
|
||||
EditFilter.fromMatrix([0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0.5, 0.5, 0.5, 0, 20, 0, 0, 0, 1, 0], 'Willow'),
|
||||
//Kodak
|
||||
EditFilter.fromMatrix([1.3, 0.1, -0.1, 0, 10, 0, 1.25, 0.1, 0, 10, 0, -0.1, 1.1, 0, 5, 0, 0, 0, 1, 0], 'Kodak'),
|
||||
//Sunset
|
||||
EditFilter.fromMatrix([1.5, 0.2, 0, 0, 0, 0.1, 0.9, 0.1, 0, 0, -0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0], 'Sunset'),
|
||||
//Noir
|
||||
EditFilter.fromMatrix([1.3, -0.3, 0.1, 0, 0, -0.1, 1.2, -0.1, 0, 0, 0.1, -0.2, 1.3, 0, 0, 0, 0, 0, 1, 0], 'Noir'),
|
||||
//Dreamy
|
||||
EditFilter.fromMatrix([1.1, 0.1, 0.1, 0, 0, 0.1, 1.1, 0.1, 0, 0, 0.1, 0.1, 1.1, 0, 15, 0, 0, 0, 1, 0], 'Dreamy'),
|
||||
//Sepia
|
||||
EditFilter.fromMatrix(
|
||||
[0.393, 0.769, 0.189, 0, 0, 0.349, 0.686, 0.168, 0, 0, 0.272, 0.534, 0.131, 0, 0, 0, 0, 0, 1, 0],
|
||||
'Sepia',
|
||||
),
|
||||
//Radium
|
||||
EditFilter.fromMatrix(
|
||||
[1.438, -0.062, -0.062, 0, 0, -0.122, 1.378, -0.122, 0, 0, -0.016, -0.016, 1.483, 0, 0, 0, 0, 0, 1, 0],
|
||||
'Radium',
|
||||
),
|
||||
//Aqua
|
||||
EditFilter.fromMatrix(
|
||||
[0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.7873, 0.2848, 0.9278, 0, 0, 0, 0, 0, 1, 0],
|
||||
'Aqua',
|
||||
),
|
||||
//Purple Haze
|
||||
EditFilter.fromMatrix([1.3, 0, 1.2, 0, 0, 0, 1.1, 0, 0, 0, 0.2, 0, 1.3, 0, 0, 0, 0, 0, 1, 0], 'Purple Haze'),
|
||||
//Lemonade
|
||||
EditFilter.fromMatrix([1.2, 0.1, 0, 0, 0, 0, 1.1, 0.2, 0, 0, 0.1, 0, 0.7, 0, 0, 0, 0, 0, 1, 0], 'Lemonade'),
|
||||
//Caramel
|
||||
EditFilter.fromMatrix([1.6, 0.2, 0, 0, 0, 0.1, 1.3, 0.1, 0, 0, 0, 0.1, 0.9, 0, 0, 0, 0, 0, 1, 0], 'Caramel'),
|
||||
//Peachy
|
||||
EditFilter.fromMatrix([1.3, 0.5, 0, 0, 0, 0.2, 1.1, 0.3, 0, 0, 0.1, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0], 'Peachy'),
|
||||
//Neon
|
||||
EditFilter.fromMatrix([1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 1, 0], 'Neon'),
|
||||
//Cold Morning
|
||||
EditFilter.fromMatrix([0.9, 0.1, 0.2, 0, 0, 0, 1, 0.1, 0, 0, 0.1, 0, 1.2, 0, 0, 0, 0, 0, 1, 0], 'Cold Morning'),
|
||||
//Lush
|
||||
EditFilter.fromMatrix([0.9, 0.2, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.1, 0, 0, 0, 0, 0, 1, 0], 'Lush'),
|
||||
//Urban Neon
|
||||
EditFilter.fromMatrix([1.1, 0, 0.3, 0, 0, 0, 0.9, 0.3, 0, 0, 0.3, 0.1, 1.2, 0, 0, 0, 0, 0, 1, 0], 'Urban Neon'),
|
||||
//Monochrome
|
||||
EditFilter.fromMatrix([0.6, 0.2, 0.2, 0, 0, 0.2, 0.6, 0.2, 0, 0, 0.2, 0.2, 0.7, 0, 0, 0, 0, 0, 1, 0], 'Monochrome'),
|
||||
];
|
||||
Reference in New Issue
Block a user