Files
photo-editor/src/core/images/sniff.js
Coder 401969cfdb
Some checks failed
test / test (push) Failing after 24s
v2: модульный монолит — очередь, персистентность, безопасность, SSE, тесты
Реализация целевого дизайна (docs/architecture/target-design.md):
- src/: модульная структура (config, logger, errors, http, core: auth/history/jobs/engines/comfy/codex/images)
- Очередь заданий: FIFO, кониурентность codex=1 / comfy-upscale=2, MAX_QUEUED_JOBS=5, JSONL-журнал и восстановление после рестарта (running → interrupted, upscale requeue)
- Персистентные сессии (sha256-хеши токенов), scrypt-хеш пароля, rate-limit входа, Origin-проверка, magic-byte валидация аплоадов
- Атомарная запись манифеста истории, каскадное удаление, URL с фактическим расширением + 302-алиас /image.jpg, миграция history/ → data/history
- Даунскейл sharp до 1024px перед Codex + масштабирование области референса
- SSE /api/events с фолбэком на polling, фронтенд переведён на ES-модули (public/js/)
- Тесты node:test + supertest (27), CI workflow test.yml, Docker/деплой: том kadr-data
- Документация: README, docs/architecture/
2026-08-27 12:52:27 +07:00

72 lines
1.5 KiB
JavaScript

"use strict";
const PNG_SIGNATURE = "89504e470d0a1a0a";
const HEIC_BRANDS = new Set([
"heic",
"heix",
"hevc",
"hevx",
"heim",
"heis",
"hevm",
"hevs",
"mif1",
"msf1",
"heif",
]);
/**
* Определяет тип изображения по сигнатуре первых байтов (magic bytes).
* @param {Buffer} buffer
* @returns {'jpeg' | 'png' | 'webp' | 'heic' | null}
*/
function sniffImageType(buffer) {
if (!Buffer.isBuffer(buffer) || buffer.length < 12) {
return null;
}
// JPEG: FF D8 FF
if (buffer[0] === 0xff && buffer[1] === 0xd8 && buffer[2] === 0xff) {
return "jpeg";
}
// PNG: 89 50 4E 47 0D 0A 1A 0A
if (buffer.subarray(0, 8).toString("hex") === PNG_SIGNATURE) {
return "png";
}
// WebP: RIFF....WEBP
if (
buffer.toString("ascii", 0, 4) === "RIFF" &&
buffer.toString("ascii", 8, 12) === "WEBP"
) {
return "webp";
}
// HEIC / HEIF: ftyp box
if (buffer.toString("ascii", 4, 8) === "ftyp") {
const majorBrand = buffer.toString("ascii", 8, 12).toLowerCase();
if (HEIC_BRANDS.has(majorBrand)) {
return "heic";
}
// Check compatible brands
const boxLength = buffer.readUInt32BE(0);
const limit = Math.min(buffer.length, boxLength > 0 ? boxLength : 64);
for (let offset = 16; offset + 4 <= limit; offset += 4) {
const brand = buffer.toString("ascii", offset, offset + 4).toLowerCase();
if (HEIC_BRANDS.has(brand)) {
return "heic";
}
}
}
return null;
}
module.exports = {
sniffImageType,
HEIC_BRANDS,
};