Skip to main content
Glama
dds.ts4.44 kB
import sharp from 'sharp'; const DDS_MAGIC = 0x20534444; // "DDS " const DDPF_FOURCC = 0x4; const FOURCC_DXT5 = 0x35545844; // "DXT5" interface DDSHeader { width: number; height: number; mipMapCount: number; pixelFormat: { flags: number; fourCC: number; }; } function readHeader(buffer: Buffer): DDSHeader { const magic = buffer.readUInt32LE(0); if (magic !== DDS_MAGIC) { throw new Error('Invalid DDS file'); } return { height: buffer.readUInt32LE(12), width: buffer.readUInt32LE(16), mipMapCount: buffer.readUInt32LE(28), pixelFormat: { flags: buffer.readUInt32LE(80), fourCC: buffer.readUInt32LE(84), }, }; } function decodeDXT5Block(block: Buffer, output: Uint8Array, outOffset: number, stride: number): void { // Alpha block (8 bytes) const alpha0 = block[0]; const alpha1 = block[1]; const alphaBits = block[2] | (block[3] << 8) | (block[4] << 16) | (block[5] << 24) | ((block[6] | (block[7] << 8)) * 0x100000000); const alphaTable = new Uint8Array(8); alphaTable[0] = alpha0; alphaTable[1] = alpha1; if (alpha0 > alpha1) { for (let i = 2; i < 8; i++) { alphaTable[i] = Math.round(((8 - i) * alpha0 + (i - 1) * alpha1) / 7); } } else { for (let i = 2; i < 6; i++) { alphaTable[i] = Math.round(((6 - i) * alpha0 + (i - 1) * alpha1) / 5); } alphaTable[6] = 0; alphaTable[7] = 255; } // Color block (8 bytes starting at offset 8) const c0 = block.readUInt16LE(8); const c1 = block.readUInt16LE(10); const colorBits = block.readUInt32LE(12); const colors = new Uint8Array(16); // Decode RGB565 colors[0] = ((c0 >> 11) & 0x1F) * 255 / 31; colors[1] = ((c0 >> 5) & 0x3F) * 255 / 63; colors[2] = (c0 & 0x1F) * 255 / 31; colors[3] = 255; colors[4] = ((c1 >> 11) & 0x1F) * 255 / 31; colors[5] = ((c1 >> 5) & 0x3F) * 255 / 63; colors[6] = (c1 & 0x1F) * 255 / 31; colors[7] = 255; // Interpolated colors colors[8] = (2 * colors[0] + colors[4]) / 3; colors[9] = (2 * colors[1] + colors[5]) / 3; colors[10] = (2 * colors[2] + colors[6]) / 3; colors[11] = 255; colors[12] = (colors[0] + 2 * colors[4]) / 3; colors[13] = (colors[1] + 2 * colors[5]) / 3; colors[14] = (colors[2] + 2 * colors[6]) / 3; colors[15] = 255; // Decode 4x4 block for (let row = 0; row < 4; row++) { for (let col = 0; col < 4; col++) { const pixelIndex = row * 4 + col; const colorIndex = (colorBits >> (pixelIndex * 2)) & 0x3; const alphaIndex = Number((BigInt(alphaBits) >> BigInt(pixelIndex * 3)) & 0x7n); const outPos = outOffset + row * stride + col * 4; output[outPos] = colors[colorIndex * 4]; output[outPos + 1] = colors[colorIndex * 4 + 1]; output[outPos + 2] = colors[colorIndex * 4 + 2]; output[outPos + 3] = alphaTable[alphaIndex]; } } } function decodeDXT5(buffer: Buffer, width: number, height: number): Uint8Array { const output = new Uint8Array(width * height * 4); const blocksX = Math.ceil(width / 4); const blocksY = Math.ceil(height / 4); const stride = width * 4; let blockOffset = 0; for (let by = 0; by < blocksY; by++) { for (let bx = 0; bx < blocksX; bx++) { const block = buffer.subarray(blockOffset, blockOffset + 16); const outOffset = by * 4 * stride + bx * 4 * 4; decodeDXT5Block(block, output, outOffset, stride); blockOffset += 16; } } return output; } export async function decodeDDS(buffer: Buffer): Promise<Buffer> { const header = readHeader(buffer); if (!(header.pixelFormat.flags & DDPF_FOURCC)) { throw new Error('DDS file does not use FourCC format'); } if (header.pixelFormat.fourCC !== FOURCC_DXT5) { throw new Error(`Unsupported DDS format: ${header.pixelFormat.fourCC.toString(16)}`); } const dataOffset = 128; // Standard DDS header size const compressedData = buffer.subarray(dataOffset); const rawPixels = decodeDXT5(compressedData, header.width, header.height); return sharp(rawPixels, { raw: { width: header.width, height: header.height, channels: 4, }, }) .png() .toBuffer(); } export function getDDSInfo(buffer: Buffer): { width: number; height: number; format: string } { const header = readHeader(buffer); return { width: header.width, height: header.height, format: header.pixelFormat.fourCC === FOURCC_DXT5 ? 'DXT5' : 'unknown', }; }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Revenant30102000/wotblitz-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server