desktop/electron/promptImageResizer.cjs
Rama main · réplica de lectura del repositorio original.
'use strict'
/**
* Codex-aligned prompt image resize (high/auto):
* longest edge ≤ 2048 and ceil(w/32)*ceil(h/32) ≤ 2500.
*/
const PATCH_SIZE = 32
const MAX_DIMENSION = 2048
const MAX_PATCHES = 2500
const JPEG_QUALITY = 85
function computeTargetSize(width, height) {
if (width <= 0 || height <= 0) {
return { width: Math.max(1, width), height: Math.max(1, height) }
}
let w = width
let h = height
const maxSide = Math.max(w, h)
if (maxSide > MAX_DIMENSION) {
const scale = MAX_DIMENSION / maxSide
w = Math.floor(w * scale)
h = Math.floor(h * scale)
w = Math.max(1, w)
h = Math.max(1, h)
}
let patchW = Math.ceil(w / PATCH_SIZE)
let patchH = Math.ceil(h / PATCH_SIZE)
if (patchW * patchH > MAX_PATCHES) {
const scale = Math.sqrt(MAX_PATCHES / (patchW * patchH))
let newPatchW = Math.max(1, Math.floor(patchW * scale))
let newPatchH = Math.max(1, Math.floor(patchH * scale))
while (newPatchW * newPatchH > MAX_PATCHES) {
if (newPatchW >= newPatchH && newPatchW > 1) newPatchW--
else if (newPatchH > 1) newPatchH--
else break
}
return { width: newPatchW * PATCH_SIZE, height: newPatchH * PATCH_SIZE }
}
return { width: Math.round(w), height: Math.round(h) }
}
function fitsPromptLimits(width, height) {
if (width <= 0 || height <= 0) return false
if (width > MAX_DIMENSION || height > MAX_DIMENSION) return false
const patches = Math.ceil(width / PATCH_SIZE) * Math.ceil(height / PATCH_SIZE)
return patches <= MAX_PATCHES
}
/**
* @param {Buffer} buffer
* @param {string} mimeHint
* @param {typeof import('electron').nativeImage} nativeImage
* @returns {{ buffer: Buffer, mime: string, width: number, height: number, resized: boolean } | null}
*/
function resizeForPrompt(buffer, mimeHint, nativeImage) {
if (!buffer || !buffer.length || !nativeImage) return null
try {
const image = nativeImage.createFromBuffer(buffer)
if (image.isEmpty()) return null
const { width: srcW, height: srcH } = image.getSize()
if (!srcW || !srcH) return null
const target = computeTargetSize(srcW, srcH)
const needsResize = target.width !== srcW || target.height !== srcH
|| !fitsPromptLimits(srcW, srcH)
let outImage = image
if (needsResize) {
outImage = image.resize({
width: target.width,
height: target.height,
quality: 'better'
})
} else {
return {
buffer,
mime: mimeHint || 'image/png',
width: srcW,
height: srcH,
resized: false
}
}
const outMime = encodeMimeFor(mimeHint)
let outBuffer
if (outMime === 'image/jpeg') {
outBuffer = outImage.toJPEG(JPEG_QUALITY)
} else {
outBuffer = outImage.toPNG()
}
if (!outBuffer || !outBuffer.length) return null
const size = outImage.getSize()
return {
buffer: outBuffer,
mime: outMime === 'image/jpeg' ? 'image/jpeg' : 'image/png',
width: size.width || target.width,
height: size.height || target.height,
resized: true
}
} catch {
return null
}
}
function encodeMimeFor(mimeHint) {
const m = (mimeHint || '').split(';')[0].trim().toLowerCase()
if (m === 'image/jpeg' || m === 'image/jpg') return 'image/jpeg'
// GIF/WebP/PNG → PNG after resize (Electron nativeImage)
return 'image/png'
}
module.exports = {
PATCH_SIZE,
MAX_DIMENSION,
MAX_PATCHES,
JPEG_QUALITY,
computeTargetSize,
fitsPromptLimits,
resizeForPrompt
}