in src/engine/actvolume/actvol.js [307:433]
static saveVolumeSliceToFile(pixelsSrc, xDim, yDim, zDim, zSlice, fileName) {
const SIZE_HEADER = 14;
const SIZE_INFO = 40;
const COMPS_IN_COLOR = 3;
const numPixels = xDim * yDim;
let pixStride = COMPS_IN_COLOR * xDim;
pixStride = (pixStride + COMPS_IN_COLOR) & ~COMPS_IN_COLOR;
const totalBufSize = SIZE_HEADER + SIZE_INFO + numPixels * COMPS_IN_COLOR;
const buf = new Uint8Array(totalBufSize);
for (let j = 0; j < totalBufSize; j++) {
buf[j] = 0;
}
const BYTE_MASK = 255;
const BITS_IN_BYTE = 8;
// write header
const BYTES_IN_DWORD = 4;
let i = 0;
// bfType[16]
buf[i++] = 0x42;
buf[i++] = 0x4d;
// bfSize[32]
let bfSize = SIZE_HEADER + SIZE_INFO + pixStride * yDim;
buf[i++] = bfSize & BYTE_MASK;
bfSize >>= BITS_IN_BYTE;
buf[i++] = bfSize & BYTE_MASK;
bfSize >>= BITS_IN_BYTE;
buf[i++] = bfSize & BYTE_MASK;
bfSize >>= BITS_IN_BYTE;
buf[i++] = bfSize & BYTE_MASK;
// bfReserved1 + bfReserved2
i += BYTES_IN_DWORD;
// bfOffBits[32]
let bfOffBits = SIZE_HEADER + SIZE_INFO;
buf[i++] = bfOffBits & BYTE_MASK;
bfOffBits >>= BITS_IN_BYTE;
buf[i++] = bfOffBits & BYTE_MASK;
bfOffBits >>= BITS_IN_BYTE;
buf[i++] = bfOffBits & BYTE_MASK;
bfOffBits >>= BITS_IN_BYTE;
buf[i++] = bfOffBits & BYTE_MASK;
// write info
// biSize[32]
let biSize = SIZE_INFO;
buf[i++] = biSize & BYTE_MASK;
biSize >>= BITS_IN_BYTE;
buf[i++] = biSize & BYTE_MASK;
biSize >>= BITS_IN_BYTE;
buf[i++] = biSize & BYTE_MASK;
biSize >>= BITS_IN_BYTE;
buf[i++] = biSize & BYTE_MASK;
// biWidth[32]
let biWidth = xDim;
buf[i++] = biWidth & BYTE_MASK;
biWidth >>= BITS_IN_BYTE;
buf[i++] = biWidth & BYTE_MASK;
biWidth >>= BITS_IN_BYTE;
buf[i++] = biWidth & BYTE_MASK;
biWidth >>= BITS_IN_BYTE;
buf[i++] = biWidth & BYTE_MASK;
// biHeight[32]
let biHeight = yDim;
buf[i++] = biHeight & BYTE_MASK;
biHeight >>= BITS_IN_BYTE;
buf[i++] = biHeight & BYTE_MASK;
biHeight >>= BITS_IN_BYTE;
buf[i++] = biHeight & BYTE_MASK;
biHeight >>= BITS_IN_BYTE;
buf[i++] = biHeight & BYTE_MASK;
// biPlanes[16]
buf[i++] = 1;
buf[i++] = 0;
// biBitCount[16]
buf[i++] = 24;
buf[i++] = 0;
// biCompression[32]
i += BYTES_IN_DWORD;
// biSizeImage[32]
let biSizeImage = pixStride * yDim;
buf[i++] = biSizeImage & BYTE_MASK;
biSizeImage >>= BITS_IN_BYTE;
buf[i++] = biSizeImage & BYTE_MASK;
biSizeImage >>= BITS_IN_BYTE;
buf[i++] = biSizeImage & BYTE_MASK;
biSizeImage >>= BITS_IN_BYTE;
buf[i++] = biSizeImage & BYTE_MASK;
// biXPelsPerMeter[32]
i += BYTES_IN_DWORD;
// biYPelsPerMeter[32]
i += BYTES_IN_DWORD;
// biClrUsed[32]
i += BYTES_IN_DWORD;
// biClrImportant[32]
i += BYTES_IN_DWORD;
let j;
// get max volume
const offSlice = zSlice * xDim * yDim;
let valMax = 0;
for (j = 0; j < numPixels; j++) {
const valGrey = pixelsSrc[offSlice + j];
valMax = valGrey > valMax ? valGrey : valMax;
} // for (j)
console.log(`saveVolumeSlice. valMax = ${valMax}`);
// write pixels
const MAX_COLOR = 255;
for (j = 0; j < numPixels; j++) {
const valGrey = Math.floor((pixelsSrc[offSlice + j] * MAX_COLOR) / valMax);
// write rgb components
buf[i++] = valGrey;
buf[i++] = valGrey;
buf[i++] = valGrey;
} // for (j)
// write buffer to file
const blob = new Blob([buf], { type: 'application/octet-stream' });
const url = URL.createObjectURL(blob);
const linkGen = document.createElement('a');
linkGen.setAttribute('href', url);
linkGen.setAttribute('download', fileName);
const eventGen = document.createEvent('MouseEvents');
eventGen.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
linkGen.dispatchEvent(eventGen);
}