Fotofeld mit Dateiauswahl, Einfügen per Strg+V, Zwischenablage-Schaltfläche und Drag & Drop; sichtbarer Foto-Button je Zeile. Foto wird beim Anlegen oder Speichern übernommen bzw. entfernt. Nextcloud meldet generierte Initialen-Avatare teils als eigene Profilbilder. Der Import erkennt Bilder mit dominanter Hintergrundfarbe und lässt sie aus; „Platzhalter-Fotos entfernen" bereinigt bereits importierte. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
44 lines
2.0 KiB
JavaScript
44 lines
2.0 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import zlib from 'node:zlib';
|
|
import { pngDominantShare, looksLikePlaceholder } from '../server/image.js';
|
|
|
|
/** Minimaler PNG-Encoder für Testbilder (RGB, 8 Bit, Filter 0). */
|
|
function png(width, height, pixel) {
|
|
const raw = Buffer.alloc((width * 3 + 1) * height);
|
|
for (let y = 0; y < height; y += 1) {
|
|
raw[y * (width * 3 + 1)] = 0;
|
|
for (let x = 0; x < width; x += 1) {
|
|
const [r, g, b] = pixel(x, y);
|
|
raw.set([r, g, b], y * (width * 3 + 1) + 1 + x * 3);
|
|
}
|
|
}
|
|
const chunk = (type, body) => {
|
|
const len = Buffer.alloc(4); len.writeUInt32BE(body.length);
|
|
const crc = Buffer.alloc(4); crc.writeUInt32BE(zlib.crc32(Buffer.concat([Buffer.from(type), body])) >>> 0);
|
|
return Buffer.concat([len, Buffer.from(type), body, crc]);
|
|
};
|
|
const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(width, 0); ihdr.writeUInt32BE(height, 4); ihdr[8] = 8; ihdr[9] = 2;
|
|
return Buffer.concat([Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), chunk('IHDR', ihdr), chunk('IDAT', zlib.deflateSync(raw)), chunk('IEND', Buffer.alloc(0))]);
|
|
}
|
|
|
|
test('Initialen-Platzhalter: eine Hintergrundfarbe mit Buchstaben wird erkannt', () => {
|
|
const img = png(64, 64, (x, y) => (x > 20 && x < 44 && y > 24 && y < 40 ? [40, 40, 40] : [230, 200, 150]));
|
|
const info = pngDominantShare(img);
|
|
assert.ok(info.share > 0.85, `share ${info.share}`);
|
|
assert.ok(looksLikePlaceholder(img));
|
|
});
|
|
|
|
test('Foto mit Farbverlauf ist kein Platzhalter', () => {
|
|
const img = png(64, 64, (x, y) => [x * 4, y * 4, (x + y) * 2]);
|
|
const info = pngDominantShare(img);
|
|
assert.ok(info.share < 0.1, `share ${info.share}`);
|
|
assert.ok(!looksLikePlaceholder(img));
|
|
});
|
|
|
|
test('JPEG und Unbekanntes werden nie als Platzhalter gewertet', () => {
|
|
assert.equal(looksLikePlaceholder(Buffer.from([0xff, 0xd8, 0xff, 0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0])), false);
|
|
assert.equal(pngDominantShare(Buffer.from('kein png')), null);
|
|
assert.equal(looksLikePlaceholder(null), false);
|
|
});
|