feat: add manual crop mode
- CropOverlay component with draggable/resizable region - Maintains target device aspect ratio - Rule of thirds grid overlay - Dark mask outside crop area - Updates ImagePreview to show overlay in manual mode - Updates photonWorker to handle manual crop regions - Also fixes top/bottom crop modes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -199,24 +199,47 @@ async function processImage(
|
||||
const width = img.get_width();
|
||||
const height = img.get_height();
|
||||
const targetAspect = device.width / device.height;
|
||||
const currentAspect = width / height;
|
||||
|
||||
let cropX1: number, cropY1: number, cropX2: number, cropY2: number;
|
||||
|
||||
if (currentAspect > targetAspect) {
|
||||
const newWidth = Math.max(1, Math.floor(height * targetAspect));
|
||||
const xOffset = Math.floor((width - newWidth) / 2);
|
||||
cropX1 = Math.max(0, xOffset);
|
||||
cropY1 = 0;
|
||||
cropX2 = Math.min(width, cropX1 + newWidth);
|
||||
cropY2 = height;
|
||||
if (config.crop.mode === 'manual' && config.crop.region) {
|
||||
// Manual crop: use the provided region
|
||||
const region = config.crop.region;
|
||||
cropX1 = Math.max(0, Math.round(region.x));
|
||||
cropY1 = Math.max(0, Math.round(region.y));
|
||||
cropX2 = Math.min(width, Math.round(region.x + region.width));
|
||||
cropY2 = Math.min(height, Math.round(region.y + region.height));
|
||||
} else {
|
||||
const newHeight = Math.max(1, Math.floor(width / targetAspect));
|
||||
const yOffset = Math.floor((height - newHeight) / 2);
|
||||
cropX1 = 0;
|
||||
cropY1 = Math.max(0, yOffset);
|
||||
cropX2 = width;
|
||||
cropY2 = Math.min(height, cropY1 + newHeight);
|
||||
// Auto crop modes: center, top, bottom
|
||||
const currentAspect = width / height;
|
||||
|
||||
if (currentAspect > targetAspect) {
|
||||
const newWidth = Math.max(1, Math.floor(height * targetAspect));
|
||||
let xOffset: number;
|
||||
if (config.crop.mode === 'top' || config.crop.mode === 'bottom') {
|
||||
xOffset = Math.floor((width - newWidth) / 2);
|
||||
} else {
|
||||
xOffset = Math.floor((width - newWidth) / 2);
|
||||
}
|
||||
cropX1 = Math.max(0, xOffset);
|
||||
cropY1 = 0;
|
||||
cropX2 = Math.min(width, cropX1 + newWidth);
|
||||
cropY2 = height;
|
||||
} else {
|
||||
const newHeight = Math.max(1, Math.floor(width / targetAspect));
|
||||
let yOffset: number;
|
||||
if (config.crop.mode === 'top') {
|
||||
yOffset = 0;
|
||||
} else if (config.crop.mode === 'bottom') {
|
||||
yOffset = height - newHeight;
|
||||
} else {
|
||||
yOffset = Math.floor((height - newHeight) / 2);
|
||||
}
|
||||
cropX1 = 0;
|
||||
cropY1 = Math.max(0, yOffset);
|
||||
cropX2 = width;
|
||||
cropY2 = Math.min(height, cropY1 + newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if (cropX2 > cropX1 && cropY2 > cropY1) {
|
||||
|
||||
Reference in New Issue
Block a user