fix ALP generation and default to it

This commit is contained in:
zefie
2026-04-26 22:01:14 -04:00
parent 6342f51d22
commit 2232beacb7
2 changed files with 33 additions and 5 deletions

View File

@@ -1314,9 +1314,15 @@ async function sendToClient(socket, headers_obj, data = null) {
}
let imageArtemisType = 'ALP'
// Add last modified if not a dynamic script
if (socket_sessions[socket.id]) {
if (socket_sessions[socket.id].request_headers) {
if (socket_sessions[socket.id].request_headers.query) {
if (socket_sessions[socket.id].request_headers.query.forceALF) {
imageArtemisType = 'ALF';
}
}
if (socket_sessions[socket.id].request_headers.service_file_path) {
// Don't change Last-modified header if provided already
if (!headers['Last-Modified'] && !headers['minisrv-no-last-modified']) {
@@ -1354,7 +1360,7 @@ async function sendToClient(socket, headers_obj, data = null) {
if (minisrv_config.config.image_decoder.image_formats && minisrv_config.config.image_decoder.image_formats.includes(headers_obj[contype_key].toLowerCase())) {
const convertOpts = {
jpegQuality: minisrv_config.config.image_decoder.jpg_quality,
type: 'ALF'
type: imageArtemisType
};
if (minisrv_config.config.image_decoder.max_height > 0) convertOpts.maxHeight = minisrv_config.config.image_decoder.max_height;

View File

@@ -17,7 +17,6 @@
*
* ALP the alpha table is prefixed with a black (0,0,0) phantom entry so
* that palette index 0 is always fully-transparent black.
* ALP encoding does not yet work correctly.
* ALF the alpha table is suffixed with a black (0,0,0) phantom entry
* (last palette slot is fully-transparent black).
*
@@ -367,6 +366,25 @@ class WTVImage {
return { data: Buffer.concat(chunks), endOffset: offset };
}
/**
* Build the Artemis alpha lookup table payload for ALP/ALF.
*
* ALP stores its alpha table with a phantom transparent palette entry
* at index 0, so the payload omits that slot and encodes only the
* remaining indices.
* ALF stores its alpha table directly and may be left full-length.
*/
buildArtemisAlphaTable(type, alphaTable) {
if (type !== 'ALP') return Buffer.from(alphaTable);
// Drop the phantom transparent index 0, then trim trailing opaque values
// since ALP app payloads are typically truncated like ALF.
const table = alphaTable.slice(1);
let trimEnd = table.length - 1;
while (trimEnd >= 0 && table[trimEnd] === 0xFF) trimEnd--;
return Buffer.from(table.slice(0, trimEnd + 1));
}
// ---------------------------------------------------------------------------
// Artemis alpha extension codec
// ---------------------------------------------------------------------------
@@ -461,8 +479,12 @@ class WTVImage {
const rgba = Buffer.from(origData);
for (let i = 0; i < pixelCount; i++) {
const idx = indices[i];
if (type === 'ALP') {
rgba[i * 4 + 3] = (idx === 0) ? 0x00 : ((idx - 1 < alphaTable.length) ? alphaTable[idx - 1] : 0xFF);
} else {
rgba[i * 4 + 3] = (idx < alphaTable.length) ? alphaTable[idx] : 0xFF;
}
}
return { rgba, width, height, type };
}
@@ -697,7 +719,7 @@ class WTVImage {
realPalette[transparentIdx * 3 + 2] = 0;
}
const emitAlphaTable = fullAlpha;
const emitAlphaTable = this.buildArtemisAlphaTable(type, fullAlpha);
const hasTransparent = bestZeroIdx >= 0;
// Re-encode the LZW image stream from our (possibly swapped) indices.
@@ -917,7 +939,7 @@ class WTVImage {
// Emit full alphaTable (no truncation; WebTV may default missing
// entries to 0x00 transparent rather than 0xFF opaque).
const emitAlphaTable = finalAlpha;
const emitAlphaTable = this.buildArtemisAlphaTable(type, finalAlpha);
const minCodeSize = Math.max(2, Math.ceil(Math.log2(colors)));
const appExtBlock = this.buildAppExtension('Artemis ', type, emitAlphaTable);