fix: enhance image reference detection and optimize image processing
- Added support for detecting file URLs in prompts using fileURLToPath for accurate path resolution. - Updated image loading logic to default to JPEG format for optimized image processing. - Improved error handling in image optimization to continue processing on failures.
This commit is contained in:
committed by
Peter Steinberger
parent
7bfc77db25
commit
8c0e290db1
@@ -1,5 +1,6 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
import type { ImageContent } from "@mariozechner/pi-ai";
|
||||
|
||||
@@ -119,6 +120,18 @@ export function detectImageReferences(prompt: string): DetectedImageRef[] {
|
||||
refs.push({ raw, type: "url", resolved: raw });
|
||||
}
|
||||
|
||||
// Pattern for file:// URLs - treat as paths since loadWebMedia handles them
|
||||
const fileUrlPattern =
|
||||
/file:\/\/[^\s<>"'`\]]+\.(?:png|jpe?g|gif|webp|bmp|tiff?|heic|heif)/gi;
|
||||
while ((match = fileUrlPattern.exec(prompt)) !== null) {
|
||||
const raw = match[0];
|
||||
if (seen.has(raw.toLowerCase())) continue;
|
||||
seen.add(raw.toLowerCase());
|
||||
// Use fileURLToPath for proper handling (e.g., file://localhost/path)
|
||||
const resolved = fileURLToPath(raw);
|
||||
refs.push({ raw, type: "path", resolved });
|
||||
}
|
||||
|
||||
// Pattern for file paths (absolute, relative, or home)
|
||||
// Matches:
|
||||
// - /absolute/path/to/file.ext (including paths with special chars like Messages/Attachments)
|
||||
@@ -127,8 +140,8 @@ export function detectImageReferences(prompt: string): DetectedImageRef[] {
|
||||
// - ~/home/path.ext
|
||||
const pathPattern = /(?:^|\s|["'`(])((\.\.?\/|[~/])[^\s"'`()[\]]*\.(?:png|jpe?g|gif|webp|bmp|tiff?|heic|heif))/gi;
|
||||
while ((match = pathPattern.exec(prompt)) !== null) {
|
||||
const raw = match[1] || match[0];
|
||||
addPathRef(raw);
|
||||
// Use capture group 1 (the path without delimiter prefix); skip if undefined
|
||||
if (match[1]) addPathRef(match[1]);
|
||||
}
|
||||
|
||||
return refs;
|
||||
@@ -205,7 +218,8 @@ export async function loadImageFromRef(
|
||||
}
|
||||
|
||||
// EXIF orientation is already normalized by loadWebMedia -> resizeToJpeg
|
||||
const mimeType = media.contentType ?? "image/png";
|
||||
// Default to JPEG since optimization converts images to JPEG format
|
||||
const mimeType = media.contentType ?? "image/jpeg";
|
||||
const data = media.buffer.toString("base64");
|
||||
|
||||
return { type: "image", data, mimeType };
|
||||
|
||||
@@ -161,23 +161,27 @@ export async function optimizeImageToJpeg(
|
||||
|
||||
for (const side of sides) {
|
||||
for (const quality of qualities) {
|
||||
const out = await resizeToJpeg({
|
||||
buffer,
|
||||
maxSide: side,
|
||||
quality,
|
||||
withoutEnlargement: true,
|
||||
});
|
||||
const size = out.length;
|
||||
if (!smallest || size < smallest.size) {
|
||||
smallest = { buffer: out, size, resizeSide: side, quality };
|
||||
}
|
||||
if (size <= maxBytes) {
|
||||
return {
|
||||
buffer: out,
|
||||
optimizedSize: size,
|
||||
resizeSide: side,
|
||||
try {
|
||||
const out = await resizeToJpeg({
|
||||
buffer,
|
||||
maxSide: side,
|
||||
quality,
|
||||
};
|
||||
withoutEnlargement: true,
|
||||
});
|
||||
const size = out.length;
|
||||
if (!smallest || size < smallest.size) {
|
||||
smallest = { buffer: out, size, resizeSide: side, quality };
|
||||
}
|
||||
if (size <= maxBytes) {
|
||||
return {
|
||||
buffer: out,
|
||||
optimizedSize: size,
|
||||
resizeSide: side,
|
||||
quality,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// Continue trying other size/quality combinations
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user