Skip to content

Instantly share code, notes, and snippets.

@mikeemoo
Last active April 19, 2021 16:14
Show Gist options
  • Save mikeemoo/3780b4d98732f6bfd7b0b662cc02db66 to your computer and use it in GitHub Desktop.
Save mikeemoo/3780b4d98732f6bfd7b0b662cc02db66 to your computer and use it in GitHub Desktop.
Node - Image to DDS
//@ts-ignore
import dxt from 'dxt-js';
import { createCanvas, loadImage } from 'canvas';
import fs from 'fs';
import { Buffer } from 'buffer';
(async () => {
const image = await loadImage('${__dirname}/input.jpg');
const { width, height } = image;
const canvas = createCanvas(width, height);
const ctx = canvas.getContext('2d')
ctx.drawImage(image, 0, 0);
ctx.scale(1, -1);
// need to check this is actually correct
const pitch = Math.floor(((width * height) * 4 + 7) / 8);
let offset = 0;
const headerBuffer = Buffer.allocUnsafe(128);
headerBuffer.write('DDS ', offset++ * 4, 'ascii'); // [0] magic
headerBuffer.writeUInt32LE(124, offset++ * 4); // [1] header size
headerBuffer.writeUInt32LE(528391, offset++ * 4); // [2] flags
headerBuffer.writeUInt32LE(height, offset++ * 4); // [3] height
headerBuffer.writeUInt32LE(width, offset++ * 4); // [4] width
headerBuffer.writeUInt32LE(pitch, offset++ * 4); // [5] pitch
headerBuffer.writeUInt32LE(0, offset++ * 4); // [6] depth
headerBuffer.writeUInt32LE(1, offset++ * 4); // [7] mipMapCount
for (let i = 0; i < 11; i++) {
headerBuffer.writeUInt32LE(0, offset++ * 4); // [8 - 18] reserved
}
headerBuffer.writeUInt32LE(32, offset++ * 4); // [19] pf size
headerBuffer.writeUInt32LE(5, offset++ * 4); // [20] pf flags
headerBuffer.write('DXT1', offset++ * 4, 'ascii'); // [21] pf fourcc
headerBuffer.writeUInt32LE(32, offset++ * 4); // [22] pf rgbbitcount
headerBuffer.writeUInt32LE(0xFF000000, offset++ * 4);// [23] pf rbitmask
headerBuffer.writeUInt32LE(0xFF0000, offset++ * 4); // [24] pf gbitmask
headerBuffer.writeUInt32LE(0xFF00, offset++ * 4); // [25] pf bbitmask
headerBuffer.writeUInt32LE(0xFF, offset++ * 4); // [26] pf abitmask
headerBuffer.writeUInt32LE(0x1000, offset++ * 4); // [27] caps
headerBuffer.writeUInt32LE(0, offset++ * 4); // [28] caps2
headerBuffer.writeUInt32LE(0, offset++ * 4); // [29] caps3
headerBuffer.writeUInt32LE(0, offset++ * 4); // [30] reserved2
let flags = dxt.flags.DXT1 | dxt.flags.ColourIterativeClusterFit | dxt.flags.ColourMetricPerceptual;
const compressed = dxt.compress(
ctx.getImageData(0, 0, width, height).data,
width,
height,
flags
);
let finalBuffer = Buffer.concat([
headerBuffer,
Buffer.from(compressed)
]);
fs.writeFileSync(`${__dirname}/output.dds`, finalBuffer);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment