Files
immich/web/src/lib/utils/editor.ts
Brandon Wees f467a5e2c8 fix(web): edit order handling (#25496)
* fix(web): edit order handling

* chore: tests

* simplify normalization function

* chore: refactor

---------

Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2026-01-27 10:55:10 -06:00

44 lines
1.3 KiB
TypeScript

import type { EditActions } from '$lib/managers/edit/edit-manager.svelte';
import type { MirrorParameters, RotateParameters } from '@immich/sdk';
import { compose, flipX, flipY, identity, rotate } from 'transformation-matrix';
const isCloseToZero = (x: number, epsilon: number = 1e-15) => Math.abs(x) < epsilon;
export const normalizeTransformEdits = (
edits: EditActions,
): {
rotation: number;
mirrorHorizontal: boolean;
mirrorVertical: boolean;
} => {
const { a, b, c, d } = buildAffineFromEdits(edits);
const rotation = ((isCloseToZero(a) ? Math.asin(c) : Math.acos(a)) * 180) / Math.PI;
return {
rotation: rotation < 0 ? 360 + rotation : rotation,
mirrorHorizontal: false,
mirrorVertical: isCloseToZero(a) ? b === c : a === -d,
};
};
export const buildAffineFromEdits = (edits: EditActions) =>
compose(
identity(),
...edits.map((edit) => {
switch (edit.action) {
case 'rotate': {
const parameters = edit.parameters as RotateParameters;
const angleInRadians = (-parameters.angle * Math.PI) / 180;
return rotate(angleInRadians);
}
case 'mirror': {
const parameters = edit.parameters as MirrorParameters;
return parameters.axis === 'horizontal' ? flipY() : flipX();
}
default: {
return identity();
}
}
}),
);