123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- "use strict";
- let interlaceUtils = require("./interlace");
- let pixelBppMapper = [
- // 0 - dummy entry
- function () {},
- // 1 - L
- // 0: 0, 1: 0, 2: 0, 3: 0xff
- function (pxData, data, pxPos, rawPos) {
- if (rawPos === data.length) {
- throw new Error("Ran out of data");
- }
- let pixel = data[rawPos];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = 0xff;
- },
- // 2 - LA
- // 0: 0, 1: 0, 2: 0, 3: 1
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 1 >= data.length) {
- throw new Error("Ran out of data");
- }
- let pixel = data[rawPos];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = data[rawPos + 1];
- },
- // 3 - RGB
- // 0: 0, 1: 1, 2: 2, 3: 0xff
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 2 >= data.length) {
- throw new Error("Ran out of data");
- }
- pxData[pxPos] = data[rawPos];
- pxData[pxPos + 1] = data[rawPos + 1];
- pxData[pxPos + 2] = data[rawPos + 2];
- pxData[pxPos + 3] = 0xff;
- },
- // 4 - RGBA
- // 0: 0, 1: 1, 2: 2, 3: 3
- function (pxData, data, pxPos, rawPos) {
- if (rawPos + 3 >= data.length) {
- throw new Error("Ran out of data");
- }
- pxData[pxPos] = data[rawPos];
- pxData[pxPos + 1] = data[rawPos + 1];
- pxData[pxPos + 2] = data[rawPos + 2];
- pxData[pxPos + 3] = data[rawPos + 3];
- },
- ];
- let pixelBppCustomMapper = [
- // 0 - dummy entry
- function () {},
- // 1 - L
- // 0: 0, 1: 0, 2: 0, 3: 0xff
- function (pxData, pixelData, pxPos, maxBit) {
- let pixel = pixelData[0];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = maxBit;
- },
- // 2 - LA
- // 0: 0, 1: 0, 2: 0, 3: 1
- function (pxData, pixelData, pxPos) {
- let pixel = pixelData[0];
- pxData[pxPos] = pixel;
- pxData[pxPos + 1] = pixel;
- pxData[pxPos + 2] = pixel;
- pxData[pxPos + 3] = pixelData[1];
- },
- // 3 - RGB
- // 0: 0, 1: 1, 2: 2, 3: 0xff
- function (pxData, pixelData, pxPos, maxBit) {
- pxData[pxPos] = pixelData[0];
- pxData[pxPos + 1] = pixelData[1];
- pxData[pxPos + 2] = pixelData[2];
- pxData[pxPos + 3] = maxBit;
- },
- // 4 - RGBA
- // 0: 0, 1: 1, 2: 2, 3: 3
- function (pxData, pixelData, pxPos) {
- pxData[pxPos] = pixelData[0];
- pxData[pxPos + 1] = pixelData[1];
- pxData[pxPos + 2] = pixelData[2];
- pxData[pxPos + 3] = pixelData[3];
- },
- ];
- function bitRetriever(data, depth) {
- let leftOver = [];
- let i = 0;
- function split() {
- if (i === data.length) {
- throw new Error("Ran out of data");
- }
- let byte = data[i];
- i++;
- let byte8, byte7, byte6, byte5, byte4, byte3, byte2, byte1;
- switch (depth) {
- default:
- throw new Error("unrecognised depth");
- case 16:
- byte2 = data[i];
- i++;
- leftOver.push((byte << 8) + byte2);
- break;
- case 4:
- byte2 = byte & 0x0f;
- byte1 = byte >> 4;
- leftOver.push(byte1, byte2);
- break;
- case 2:
- byte4 = byte & 3;
- byte3 = (byte >> 2) & 3;
- byte2 = (byte >> 4) & 3;
- byte1 = (byte >> 6) & 3;
- leftOver.push(byte1, byte2, byte3, byte4);
- break;
- case 1:
- byte8 = byte & 1;
- byte7 = (byte >> 1) & 1;
- byte6 = (byte >> 2) & 1;
- byte5 = (byte >> 3) & 1;
- byte4 = (byte >> 4) & 1;
- byte3 = (byte >> 5) & 1;
- byte2 = (byte >> 6) & 1;
- byte1 = (byte >> 7) & 1;
- leftOver.push(byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8);
- break;
- }
- }
- return {
- get: function (count) {
- while (leftOver.length < count) {
- split();
- }
- let returner = leftOver.slice(0, count);
- leftOver = leftOver.slice(count);
- return returner;
- },
- resetAfterLine: function () {
- leftOver.length = 0;
- },
- end: function () {
- if (i !== data.length) {
- throw new Error("extra data found");
- }
- },
- };
- }
- function mapImage8Bit(image, pxData, getPxPos, bpp, data, rawPos) {
- // eslint-disable-line max-params
- let imageWidth = image.width;
- let imageHeight = image.height;
- let imagePass = image.index;
- for (let y = 0; y < imageHeight; y++) {
- for (let x = 0; x < imageWidth; x++) {
- let pxPos = getPxPos(x, y, imagePass);
- pixelBppMapper[bpp](pxData, data, pxPos, rawPos);
- rawPos += bpp; //eslint-disable-line no-param-reassign
- }
- }
- return rawPos;
- }
- function mapImageCustomBit(image, pxData, getPxPos, bpp, bits, maxBit) {
- // eslint-disable-line max-params
- let imageWidth = image.width;
- let imageHeight = image.height;
- let imagePass = image.index;
- for (let y = 0; y < imageHeight; y++) {
- for (let x = 0; x < imageWidth; x++) {
- let pixelData = bits.get(bpp);
- let pxPos = getPxPos(x, y, imagePass);
- pixelBppCustomMapper[bpp](pxData, pixelData, pxPos, maxBit);
- }
- bits.resetAfterLine();
- }
- }
- exports.dataToBitMap = function (data, bitmapInfo) {
- let width = bitmapInfo.width;
- let height = bitmapInfo.height;
- let depth = bitmapInfo.depth;
- let bpp = bitmapInfo.bpp;
- let interlace = bitmapInfo.interlace;
- let bits;
- if (depth !== 8) {
- bits = bitRetriever(data, depth);
- }
- let pxData;
- if (depth <= 8) {
- pxData = Buffer.alloc(width * height * 4);
- } else {
- pxData = new Uint16Array(width * height * 4);
- }
- let maxBit = Math.pow(2, depth) - 1;
- let rawPos = 0;
- let images;
- let getPxPos;
- if (interlace) {
- images = interlaceUtils.getImagePasses(width, height);
- getPxPos = interlaceUtils.getInterlaceIterator(width, height);
- } else {
- let nonInterlacedPxPos = 0;
- getPxPos = function () {
- let returner = nonInterlacedPxPos;
- nonInterlacedPxPos += 4;
- return returner;
- };
- images = [{ width: width, height: height }];
- }
- for (let imageIndex = 0; imageIndex < images.length; imageIndex++) {
- if (depth === 8) {
- rawPos = mapImage8Bit(
- images[imageIndex],
- pxData,
- getPxPos,
- bpp,
- data,
- rawPos
- );
- } else {
- mapImageCustomBit(
- images[imageIndex],
- pxData,
- getPxPos,
- bpp,
- bits,
- maxBit
- );
- }
- }
- if (depth === 8) {
- if (rawPos !== data.length) {
- throw new Error("extra data found");
- }
- } else {
- bits.end();
- }
- return pxData;
- };
|