Initial commit
This commit is contained in:
commit
e49726988c
5445 files changed
+1089914
No files matched your search
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 Andrew Lisowski
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
<div align="center">
|
||||
<img width="200" height="200"
|
||||
src="./logo.png">
|
||||
<h1>bmp-ts</h1>
|
||||
<p>A pure typescript <code>bmp</code> encoder and decoder.</p>
|
||||
</div
|
||||
|
||||
[](https://codecov.io/gh/hipstersmoothie/bmp-ts)
|
||||
[](https://github.com/prettier/prettier)
|
||||
|
||||
Supports decoding and encoding in all bit depths (1, 4, 8, 16, 24, 32).
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install bmp-ts
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Decoding
|
||||
|
||||
`decode` will return an object that includes all the header properties of the `bmp` image file and the data. See header definition [below](#header).
|
||||
|
||||
```js
|
||||
const bmp = require('bmp-ts').default;
|
||||
const bmpBuffer = fs.readFileSync('bit24.bmp');
|
||||
const bmpData = bmp.decode(bmpBuffer);
|
||||
```
|
||||
|
||||
#### Options
|
||||
|
||||
- toRGBA - switch the output to big endian RGBA, making it compatible with other libraries like `pngjs`
|
||||
|
||||
```js
|
||||
const bmp = require('bmp-ts').default;
|
||||
const bmpBuffer = fs.readFileSync('bit24.bmp');
|
||||
const bmpData = bmp.decode(bmpBuffer, { toRGBA: true });
|
||||
```
|
||||
|
||||
#### Supported Compression Methods
|
||||
|
||||
Currently compression is only supported during decoding. The following methods are implemented:
|
||||
|
||||
- NONE - Most common
|
||||
- BI_RLE8 - Can be used only with 8-bit/pixel bitmap
|
||||
- BI_RLE4 - Can be used only with 4-bit/pixel bitmaps
|
||||
- BI_BIT_FIELDS - Huffman 1D - BITMAPV2INFOHEADER: RGB bit field masks, BITMAPV3INFOHEADER+: RGBA
|
||||
- BI_ALPHA_BIT_FIELDS - RGBA bit field masks - only Windows CE 5.0 with .NET 4.0 or later
|
||||
|
||||
### Encoding
|
||||
|
||||
To encode an image all you need is a buffer with the image data, the height and the width. You can specify the bit depth of the output image by modifying `bitPP`. If you do not provide a value, the output image defaults to 24-bit.
|
||||
|
||||
All header fields are valid options to `encode` and will be encoded into the header.
|
||||
|
||||
```js
|
||||
const bmp = require('bmp-ts').default;
|
||||
const fs = require('fs');
|
||||
const bmpData = {
|
||||
data, // Buffer
|
||||
bitPP: 1 | 2 | 4 | 16 | 24 | 32, // The number of bits per pixel
|
||||
width, // Number
|
||||
height, // Number
|
||||
};
|
||||
|
||||
// Compression is not supported
|
||||
const rawData = bmp.encode(bmpData);
|
||||
fs.writeFileSync('./image.bmp', rawData.data);
|
||||
```
|
||||
|
||||
## Header
|
||||
|
||||
| Property | Type | Purpose |
|
||||
| --------------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| fileSize | number | The size of the BMP file in bytes |
|
||||
| reserve1 | number | Reserved; actual value depends on the application that creates the image |
|
||||
| reserve2 | number | Reserved; actual value depends on the application that creates the image |
|
||||
| offset | number | The offset, i.e. starting address, of the byte where the bitmap image data (pixel array) can be found. |
|
||||
| headerSize | number | The size of this header (12 bytes) |
|
||||
| width | number | The bitmap width in pixels (unsigned 16-bit) |
|
||||
| height | number | The bitmap height in pixels (unsigned 16-bit) |
|
||||
| planes | number | The number of color planes, must be 1 |
|
||||
| bitPP | number | The number of bits per pixel |
|
||||
| compress | number | The compression method being used. See the supported compression methods |
|
||||
| rawSize | number | The image size. This is the size of the raw bitmap data; a dummy 0 can be given for BI_RGB bitmaps. |
|
||||
| hr | number | The horizontal resolution of the image. (pixel per metre, signed integer) |
|
||||
| vr | number | The vertical resolution of the image. (pixel per metre, signed integer) |
|
||||
| colors | number | The number of colors in the color palette, or 0 to default to 2n |
|
||||
| importantColors | number | The number of important colors used, or 0 when every color is important; generally ignored |
|
||||
| palette | Color[] | The colors used to render the image. only used for 1, 4, and 8 bitPP images |
|
||||
| data | Byte[] | The data in ABGR |
|
||||
|
||||
### Color
|
||||
|
||||
The color palette is returned when decoding a 1, 4, or 8 bit image.
|
||||
|
||||
Color Format:
|
||||
|
||||
```json
|
||||
{
|
||||
"red": 255,
|
||||
"green": 255,
|
||||
"blue": 255,
|
||||
"quad": 255
|
||||
}
|
||||
```
|
||||
|
||||
To encode to 4 or 8 bit a color palette must be provided. 1 bit defaults to black and white but you can override this via palette.
|
||||
|
||||
```js
|
||||
const rawData = bmp.encode({
|
||||
data,
|
||||
bitPP: 8,
|
||||
width,
|
||||
height,
|
||||
palette: [
|
||||
{ red: 255, green: 255, blue: 255, quad: 0 },
|
||||
{ red: 255, green: 255, blue: 0, quad: 0 },
|
||||
{ red: 255, green: 0, blue: 255, quad: 0 },
|
||||
{ red: 255, green: 0, blue: 0, quad: 0 },
|
||||
{ red: 0, green: 255, blue: 255, quad: 0 },
|
||||
{ red: 0, green: 255, blue: 0, quad: 0 },
|
||||
{ red: 0, green: 0, blue: 255, quad: 0 },
|
||||
{ red: 0, green: 0, blue: 0, quad: 0 },
|
||||
],
|
||||
});
|
||||
|
||||
fs.writeFileSync('./image.bmp', rawData.data);
|
||||
```
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/// <reference types="node" />
|
||||
import { BmpCompression, BmpColor, BmpDecoderOptions, BmpImage } from './types.js';
|
||||
export default class BmpDecoder implements BmpImage {
|
||||
flag: string;
|
||||
fileSize: number;
|
||||
reserved1: number;
|
||||
reserved2: number;
|
||||
offset: number;
|
||||
headerSize: number;
|
||||
width: number;
|
||||
height: number;
|
||||
planes: number;
|
||||
bitPP: number;
|
||||
compression?: BmpCompression;
|
||||
rawSize: number;
|
||||
hr: number;
|
||||
vr: number;
|
||||
colors: number;
|
||||
importantColors: number;
|
||||
palette: BmpColor[];
|
||||
data: Buffer;
|
||||
private maskRed;
|
||||
private maskGreen;
|
||||
private maskBlue;
|
||||
private maskAlpha;
|
||||
private readonly toRGBA;
|
||||
private pos;
|
||||
private bottomUp;
|
||||
private readonly buffer;
|
||||
private readonly locRed;
|
||||
private readonly locGreen;
|
||||
private readonly locBlue;
|
||||
private readonly locAlpha;
|
||||
private shiftRed;
|
||||
private shiftGreen;
|
||||
private shiftBlue;
|
||||
private shiftAlpha;
|
||||
constructor(buffer: Buffer, { toRGBA }?: BmpDecoderOptions);
|
||||
private parseHeader;
|
||||
private parseRGBA;
|
||||
private bit1;
|
||||
private bit4;
|
||||
private bit8;
|
||||
private bit16;
|
||||
private bit24;
|
||||
private bit32;
|
||||
private scanImage;
|
||||
private readUInt32LE;
|
||||
private setPixelData;
|
||||
}
|
||||
+408
@@ -0,0 +1,408 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const header_types_js_1 = __importDefault(require("./header-types.js"));
|
||||
const mask_color_js_1 = __importDefault(require("./mask-color.js"));
|
||||
const types_js_1 = require("./types.js");
|
||||
class BmpDecoder {
|
||||
// Header
|
||||
flag;
|
||||
fileSize;
|
||||
reserved1;
|
||||
reserved2;
|
||||
offset;
|
||||
headerSize;
|
||||
width;
|
||||
height;
|
||||
planes;
|
||||
bitPP;
|
||||
compression;
|
||||
rawSize;
|
||||
hr;
|
||||
vr;
|
||||
colors;
|
||||
importantColors;
|
||||
palette;
|
||||
data;
|
||||
maskRed;
|
||||
maskGreen;
|
||||
maskBlue;
|
||||
maskAlpha;
|
||||
toRGBA;
|
||||
pos;
|
||||
bottomUp;
|
||||
buffer;
|
||||
locRed;
|
||||
locGreen;
|
||||
locBlue;
|
||||
locAlpha;
|
||||
shiftRed;
|
||||
shiftGreen;
|
||||
shiftBlue;
|
||||
shiftAlpha;
|
||||
constructor(buffer, { toRGBA } = { toRGBA: false }) {
|
||||
this.buffer = buffer;
|
||||
this.toRGBA = !!toRGBA;
|
||||
this.pos = 0;
|
||||
this.bottomUp = true;
|
||||
this.flag = this.buffer.toString('utf-8', 0, (this.pos += 2));
|
||||
if (this.flag !== 'BM') {
|
||||
throw new Error('Invalid BMP File');
|
||||
}
|
||||
this.locRed = this.toRGBA ? 0 : 3;
|
||||
this.locGreen = this.toRGBA ? 1 : 2;
|
||||
this.locBlue = this.toRGBA ? 2 : 1;
|
||||
this.locAlpha = this.toRGBA ? 3 : 0;
|
||||
this.parseHeader();
|
||||
this.parseRGBA();
|
||||
}
|
||||
parseHeader() {
|
||||
this.fileSize = this.readUInt32LE();
|
||||
this.reserved1 = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.reserved2 = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.offset = this.readUInt32LE();
|
||||
// End of BITMAP_FILE_HEADER
|
||||
this.headerSize = this.readUInt32LE();
|
||||
if (!(this.headerSize in header_types_js_1.default)) {
|
||||
throw new Error(`Unsupported BMP header size ${this.headerSize}`);
|
||||
}
|
||||
this.width = this.readUInt32LE();
|
||||
this.height = this.readUInt32LE();
|
||||
// negative value are possible here => implies bottom down
|
||||
this.height =
|
||||
this.height > 0x7fffffff ? this.height - 0x100000000 : this.height;
|
||||
this.planes = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.bitPP = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.compression = this.readUInt32LE();
|
||||
this.rawSize = this.readUInt32LE();
|
||||
this.hr = this.readUInt32LE();
|
||||
this.vr = this.readUInt32LE();
|
||||
this.colors = this.readUInt32LE();
|
||||
this.importantColors = this.readUInt32LE();
|
||||
// De facto defaults
|
||||
if (this.bitPP === 32) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x00ff0000;
|
||||
this.maskGreen = 0x0000ff00;
|
||||
this.maskBlue = 0x000000ff;
|
||||
}
|
||||
else if (this.bitPP === 16) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x7c00;
|
||||
this.maskGreen = 0x03e0;
|
||||
this.maskBlue = 0x001f;
|
||||
}
|
||||
// End of BITMAP_INFO_HEADER
|
||||
if (this.headerSize > header_types_js_1.default.BITMAP_INFO_HEADER ||
|
||||
this.compression === types_js_1.BmpCompression.BI_BIT_FIELDS ||
|
||||
this.compression === types_js_1.BmpCompression.BI_ALPHA_BIT_FIELDS) {
|
||||
this.maskRed = this.readUInt32LE();
|
||||
this.maskGreen = this.readUInt32LE();
|
||||
this.maskBlue = this.readUInt32LE();
|
||||
}
|
||||
// End of BITMAP_V2_INFO_HEADER
|
||||
if (this.headerSize > header_types_js_1.default.BITMAP_V2_INFO_HEADER ||
|
||||
this.compression === types_js_1.BmpCompression.BI_ALPHA_BIT_FIELDS) {
|
||||
this.maskAlpha = this.readUInt32LE();
|
||||
}
|
||||
// End of BITMAP_V3_INFO_HEADER
|
||||
if (this.headerSize > header_types_js_1.default.BITMAP_V3_INFO_HEADER) {
|
||||
this.pos +=
|
||||
header_types_js_1.default.BITMAP_V4_HEADER - header_types_js_1.default.BITMAP_V3_INFO_HEADER;
|
||||
}
|
||||
// End of BITMAP_V4_HEADER
|
||||
if (this.headerSize > header_types_js_1.default.BITMAP_V4_HEADER) {
|
||||
this.pos += header_types_js_1.default.BITMAP_V5_HEADER - header_types_js_1.default.BITMAP_V4_HEADER;
|
||||
}
|
||||
// End of BITMAP_V5_HEADER
|
||||
if (this.bitPP <= 8 || this.colors > 0) {
|
||||
const len = this.colors === 0 ? 1 << this.bitPP : this.colors;
|
||||
this.palette = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const blue = this.buffer.readUInt8(this.pos++);
|
||||
const green = this.buffer.readUInt8(this.pos++);
|
||||
const red = this.buffer.readUInt8(this.pos++);
|
||||
const quad = this.buffer.readUInt8(this.pos++);
|
||||
this.palette[i] = {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
quad,
|
||||
};
|
||||
}
|
||||
}
|
||||
// End of color table
|
||||
// Can the height ever be negative?
|
||||
if (this.height < 0) {
|
||||
this.height *= -1;
|
||||
this.bottomUp = false;
|
||||
}
|
||||
const coloShift = (0, mask_color_js_1.default)(this.maskRed, this.maskGreen, this.maskBlue, this.maskAlpha);
|
||||
this.shiftRed = coloShift.shiftRed;
|
||||
this.shiftGreen = coloShift.shiftGreen;
|
||||
this.shiftBlue = coloShift.shiftBlue;
|
||||
this.shiftAlpha = coloShift.shiftAlpha;
|
||||
}
|
||||
parseRGBA() {
|
||||
this.data = Buffer.alloc(this.width * this.height * 4);
|
||||
switch (this.bitPP) {
|
||||
case 1:
|
||||
this.bit1();
|
||||
break;
|
||||
case 4:
|
||||
this.bit4();
|
||||
break;
|
||||
case 8:
|
||||
this.bit8();
|
||||
break;
|
||||
case 16:
|
||||
this.bit16();
|
||||
break;
|
||||
case 24:
|
||||
this.bit24();
|
||||
break;
|
||||
default:
|
||||
this.bit32();
|
||||
}
|
||||
}
|
||||
bit1() {
|
||||
const xLen = Math.ceil(this.width / 8);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
let lastLine;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
if (line !== lastLine) {
|
||||
lastLine = line;
|
||||
}
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 8 * 4;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
if (x * 8 + i < this.width) {
|
||||
const rgb = this.palette[(b >> (7 - i)) & 0x1];
|
||||
this.data[location + i * this.locAlpha] = 0;
|
||||
this.data[location + i * 4 + this.locBlue] = rgb.blue;
|
||||
this.data[location + i * 4 + this.locGreen] = rgb.green;
|
||||
this.data[location + i * 4 + this.locRed] = rgb.red;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
bit4() {
|
||||
if (this.compression === types_js_1.BmpCompression.BI_RLE4) {
|
||||
this.data.fill(0);
|
||||
let lowNibble = false; //for all count of pixel
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.buffer.readUInt8(this.pos++);
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
lowNibble = false;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
// image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
// offset x, y
|
||||
const x = this.buffer.readUInt8(this.pos++);
|
||||
const y = this.buffer.readUInt8(this.pos++);
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
let c = this.buffer.readUInt8(this.pos++);
|
||||
for (let i = 0; i < b; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? c & 0x0f : (c & 0xf0) >> 4);
|
||||
if (i & 1 && i + 1 < b) {
|
||||
c = this.buffer.readUInt8(this.pos++);
|
||||
}
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
if ((((b + 1) >> 1) & 1) === 1) {
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? b & 0x0f : (b & 0xf0) >> 4);
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const xLen = Math.ceil(this.width / 2);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 2 * 4;
|
||||
const first4 = b >> 4;
|
||||
let rgb = this.palette[first4];
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = rgb.blue;
|
||||
this.data[location + 2] = rgb.green;
|
||||
this.data[location + 3] = rgb.red;
|
||||
if (x * 2 + 1 >= this.width) {
|
||||
// throw new Error('Something');
|
||||
return false;
|
||||
}
|
||||
const last4 = b & 0x0f;
|
||||
rgb = this.palette[last4];
|
||||
this.data[location + 4] = 0;
|
||||
this.data[location + 4 + 1] = rgb.blue;
|
||||
this.data[location + 4 + 2] = rgb.green;
|
||||
this.data[location + 4 + 3] = rgb.red;
|
||||
});
|
||||
}
|
||||
}
|
||||
bit8() {
|
||||
if (this.compression === types_js_1.BmpCompression.BI_RLE8) {
|
||||
this.data.fill(0);
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.buffer.readUInt8(this.pos++);
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
//image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
//offset x,y
|
||||
const x = this.buffer.readUInt8(this.pos++);
|
||||
const y = this.buffer.readUInt8(this.pos++);
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < b; i++) {
|
||||
const c = this.buffer.readUInt8(this.pos++);
|
||||
location = this.setPixelData(location, c);
|
||||
}
|
||||
// @ts-ignore
|
||||
const shouldIncrement = b & (1 === 1);
|
||||
if (shouldIncrement) {
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const mode = this.width % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 4;
|
||||
if (b < this.palette.length) {
|
||||
const rgb = this.palette[b];
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = rgb.blue;
|
||||
this.data[location + 2] = rgb.green;
|
||||
this.data[location + 3] = rgb.red;
|
||||
}
|
||||
else {
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = 0xff;
|
||||
this.data[location + 2] = 0xff;
|
||||
this.data[location + 3] = 0xff;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
bit16() {
|
||||
const padding = (this.width % 2) * 2;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = this.shiftAlpha(px);
|
||||
});
|
||||
}
|
||||
bit24() {
|
||||
const padding = this.width % 4;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const blue = this.buffer.readUInt8(this.pos++);
|
||||
const green = this.buffer.readUInt8(this.pos++);
|
||||
const red = this.buffer.readUInt8(this.pos++);
|
||||
this.data[loc + this.locRed] = red;
|
||||
this.data[loc + this.locGreen] = green;
|
||||
this.data[loc + this.locBlue] = blue;
|
||||
this.data[loc + this.locAlpha] = 0;
|
||||
});
|
||||
}
|
||||
bit32() {
|
||||
this.scanImage(0, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.readUInt32LE();
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = this.shiftAlpha(px);
|
||||
});
|
||||
}
|
||||
scanImage(padding = 0, width = this.width, processPixel) {
|
||||
for (let y = this.height - 1; y >= 0; y--) {
|
||||
const line = this.bottomUp ? y : this.height - 1 - y;
|
||||
for (let x = 0; x < width; x++) {
|
||||
const result = processPixel.call(this, x, line);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.pos += padding;
|
||||
}
|
||||
}
|
||||
readUInt32LE() {
|
||||
const value = this.buffer.readUInt32LE(this.pos);
|
||||
this.pos += 4;
|
||||
return value;
|
||||
}
|
||||
setPixelData(location, rgbIndex) {
|
||||
const { blue, green, red } = this.palette[rgbIndex];
|
||||
this.data[location + this.locAlpha] = 0;
|
||||
this.data[location + 1 + this.locBlue] = blue;
|
||||
this.data[location + 2 + this.locGreen] = green;
|
||||
this.data[location + 3 + this.locRed] = red;
|
||||
return location + 4;
|
||||
}
|
||||
}
|
||||
exports.default = BmpDecoder;
|
||||
//# sourceMappingURL=decoder.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/decoder.ts"],"names":[],"mappings":"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 truncated
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/// <reference types="node" />
|
||||
import { BmpColor, BmpImage } from './types.js';
|
||||
export default class BmpEncoder implements BmpImage {
|
||||
readonly fileSize: number;
|
||||
readonly reserved1: number;
|
||||
readonly reserved2: number;
|
||||
readonly offset: number;
|
||||
readonly width: number;
|
||||
readonly flag: string;
|
||||
readonly height: number;
|
||||
readonly planes: number;
|
||||
readonly bitPP: number;
|
||||
readonly compress: number;
|
||||
readonly hr: number;
|
||||
readonly vr: number;
|
||||
readonly colors: number;
|
||||
readonly importantColors: number;
|
||||
readonly rawSize: number;
|
||||
readonly headerSize: number;
|
||||
readonly data: Buffer;
|
||||
readonly palette: BmpColor[];
|
||||
private readonly extraBytes;
|
||||
private readonly buffer;
|
||||
private readonly bytesInColor;
|
||||
private pos;
|
||||
constructor(imgData: BmpImage);
|
||||
encode(): void;
|
||||
private writeHeader;
|
||||
private bit1;
|
||||
private bit4;
|
||||
private bit8;
|
||||
private bit16;
|
||||
private bit24;
|
||||
private bit32;
|
||||
private writeImage;
|
||||
private initColors;
|
||||
private writeUInt32LE;
|
||||
}
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const header_types_js_1 = __importDefault(require("./header-types.js"));
|
||||
function createInteger(numbers) {
|
||||
return numbers.reduce((final, n) => (final << 1) | n, 0);
|
||||
}
|
||||
function createColor(color) {
|
||||
return ((color.quad << 24) | (color.red << 16) | (color.green << 8) | color.blue);
|
||||
}
|
||||
class BmpEncoder {
|
||||
fileSize;
|
||||
reserved1;
|
||||
reserved2;
|
||||
offset;
|
||||
width;
|
||||
flag;
|
||||
height;
|
||||
planes;
|
||||
bitPP;
|
||||
compress;
|
||||
hr;
|
||||
vr;
|
||||
colors;
|
||||
importantColors;
|
||||
rawSize;
|
||||
headerSize;
|
||||
data;
|
||||
palette;
|
||||
extraBytes;
|
||||
buffer;
|
||||
bytesInColor;
|
||||
pos;
|
||||
constructor(imgData) {
|
||||
this.buffer = imgData.data;
|
||||
this.width = imgData.width;
|
||||
this.height = imgData.height;
|
||||
this.headerSize = header_types_js_1.default.BITMAP_INFO_HEADER;
|
||||
// Header
|
||||
this.flag = 'BM';
|
||||
this.bitPP = imgData.bitPP || 24;
|
||||
this.offset = 54;
|
||||
this.reserved1 = imgData.reserved1 || 0;
|
||||
this.reserved2 = imgData.reserved2 || 0;
|
||||
this.planes = 1;
|
||||
this.compress = 0;
|
||||
this.hr = imgData.hr || 0;
|
||||
this.vr = imgData.vr || 0;
|
||||
this.importantColors = imgData.importantColors || 0;
|
||||
this.colors = Math.min(2 ** (this.bitPP - 1 || 1), imgData.colors || Infinity);
|
||||
this.palette = imgData.palette || [];
|
||||
if (this.colors && this.bitPP < 16) {
|
||||
this.offset += this.colors * 4;
|
||||
}
|
||||
else {
|
||||
this.colors = 0;
|
||||
}
|
||||
switch (this.bitPP) {
|
||||
case 32:
|
||||
this.bytesInColor = 4;
|
||||
break;
|
||||
case 16:
|
||||
this.bytesInColor = 2;
|
||||
break;
|
||||
case 8:
|
||||
this.bytesInColor = 1;
|
||||
break;
|
||||
case 4:
|
||||
this.bytesInColor = 1 / 2;
|
||||
break;
|
||||
case 1:
|
||||
this.bytesInColor = 1 / 8;
|
||||
break;
|
||||
default:
|
||||
this.bytesInColor = 3;
|
||||
this.bitPP = 24;
|
||||
}
|
||||
const rowWidth = (this.width * this.bitPP) / 32;
|
||||
const rowBytes = Math.ceil(rowWidth);
|
||||
this.extraBytes = (rowBytes - rowWidth) * 4;
|
||||
// Why 2?
|
||||
this.rawSize = this.height * rowBytes * 4 + 2;
|
||||
this.fileSize = this.rawSize + this.offset;
|
||||
this.data = Buffer.alloc(this.fileSize, 0x1);
|
||||
this.pos = 0;
|
||||
this.encode();
|
||||
}
|
||||
encode() {
|
||||
this.pos = 0;
|
||||
this.writeHeader();
|
||||
switch (this.bitPP) {
|
||||
case 32:
|
||||
this.bit32();
|
||||
break;
|
||||
case 16:
|
||||
this.bit16();
|
||||
break;
|
||||
case 8:
|
||||
this.bit8();
|
||||
break;
|
||||
case 4:
|
||||
this.bit4();
|
||||
break;
|
||||
case 1:
|
||||
this.bit1();
|
||||
break;
|
||||
default:
|
||||
this.bit24();
|
||||
}
|
||||
}
|
||||
writeHeader() {
|
||||
this.data.write(this.flag, this.pos, 2);
|
||||
this.pos += 2;
|
||||
this.writeUInt32LE(this.fileSize);
|
||||
// Writing 2 UInt16LE resulted in a weird bug
|
||||
this.writeUInt32LE((this.reserved1 << 16) | this.reserved2);
|
||||
this.writeUInt32LE(this.offset);
|
||||
this.writeUInt32LE(this.headerSize);
|
||||
this.writeUInt32LE(this.width);
|
||||
this.writeUInt32LE(this.height);
|
||||
this.data.writeUInt16LE(this.planes, this.pos);
|
||||
this.pos += 2;
|
||||
this.data.writeUInt16LE(this.bitPP, this.pos);
|
||||
this.pos += 2;
|
||||
this.writeUInt32LE(this.compress);
|
||||
this.writeUInt32LE(this.rawSize);
|
||||
this.writeUInt32LE(this.hr);
|
||||
this.writeUInt32LE(this.vr);
|
||||
this.writeUInt32LE(this.colors);
|
||||
this.writeUInt32LE(this.importantColors);
|
||||
}
|
||||
bit1() {
|
||||
if (this.palette.length && this.colors === 2) {
|
||||
this.initColors(1);
|
||||
}
|
||||
else {
|
||||
this.writeUInt32LE(0x00ffffff); // Black
|
||||
this.writeUInt32LE(0x00000000); // White
|
||||
}
|
||||
this.pos += 1; // ?
|
||||
let lineArr = [];
|
||||
this.writeImage((p, index, x) => {
|
||||
let i = index;
|
||||
i++;
|
||||
const b = this.buffer[i++];
|
||||
const g = this.buffer[i++];
|
||||
const r = this.buffer[i++];
|
||||
const brightness = r * 0.2126 + g * 0.7152 + b * 0.0722;
|
||||
lineArr.push(brightness > 127 ? 0 : 1);
|
||||
if ((x + 1) % 8 === 0) {
|
||||
this.data[p - 1] = createInteger(lineArr);
|
||||
lineArr = [];
|
||||
}
|
||||
else if (x === this.width - 1 && lineArr.length > 0) {
|
||||
this.data[p - 1] = createInteger(lineArr) << 4;
|
||||
lineArr = [];
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit4() {
|
||||
const colors = this.initColors(4);
|
||||
let integerPair = [];
|
||||
this.writeImage((p, index, x) => {
|
||||
let i = index;
|
||||
const colorInt = createColor({
|
||||
quad: this.buffer[i++],
|
||||
blue: this.buffer[i++],
|
||||
green: this.buffer[i++],
|
||||
red: this.buffer[i++],
|
||||
});
|
||||
const colorExists = colors.findIndex((c) => c === colorInt);
|
||||
if (colorExists !== -1) {
|
||||
integerPair.push(colorExists);
|
||||
}
|
||||
else {
|
||||
integerPair.push(0);
|
||||
}
|
||||
if ((x + 1) % 2 === 0) {
|
||||
this.data[p] = (integerPair[0] << 4) | integerPair[1];
|
||||
integerPair = [];
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit8() {
|
||||
const colors = this.initColors(8);
|
||||
this.writeImage((p, index) => {
|
||||
let i = index;
|
||||
const colorInt = createColor({
|
||||
quad: this.buffer[i++],
|
||||
blue: this.buffer[i++],
|
||||
green: this.buffer[i++],
|
||||
red: this.buffer[i++],
|
||||
});
|
||||
const colorExists = colors.findIndex((c) => c === colorInt);
|
||||
if (colorExists !== -1) {
|
||||
this.data[p] = colorExists;
|
||||
}
|
||||
else {
|
||||
this.data[p] = 0;
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit16() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index + 1;
|
||||
const b = this.buffer[i++] / 8; // b
|
||||
const g = this.buffer[i++] / 8; // g
|
||||
const r = this.buffer[i++] / 8; // r
|
||||
const color = (r << 10) | (g << 5) | b;
|
||||
this.data[p] = color & 0x00ff;
|
||||
this.data[p + 1] = (color & 0xff00) >> 8;
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit24() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index + 1;
|
||||
this.data[p] = this.buffer[i++]; //b
|
||||
this.data[p + 1] = this.buffer[i++]; //g
|
||||
this.data[p + 2] = this.buffer[i++]; //r
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit32() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index;
|
||||
this.data[p + 3] = this.buffer[i++]; // a
|
||||
this.data[p] = this.buffer[i++]; // b
|
||||
this.data[p + 1] = this.buffer[i++]; // g
|
||||
this.data[p + 2] = this.buffer[i++]; // r
|
||||
return i;
|
||||
});
|
||||
}
|
||||
writeImage(writePixel) {
|
||||
const rowBytes = this.extraBytes + this.width * this.bytesInColor;
|
||||
let i = 0;
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
const p = Math.floor(this.pos + (this.height - 1 - y) * rowBytes + x * this.bytesInColor);
|
||||
i = writePixel.call(this, p, i, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
initColors(bit) {
|
||||
const colors = [];
|
||||
if (this.palette.length) {
|
||||
for (let i = 0; i < this.colors; i++) {
|
||||
const rootColor = createColor(this.palette[i]);
|
||||
this.writeUInt32LE(rootColor);
|
||||
colors.push(rootColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error(`To encode ${bit}-bit BMPs a pallette is needed. Please choose up to ${this.colors} colors. Colors must be 32-bit integers.`);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
writeUInt32LE(value) {
|
||||
this.data.writeUInt32LE(value, this.pos);
|
||||
this.pos += 4;
|
||||
}
|
||||
}
|
||||
exports.default = BmpEncoder;
|
||||
//# sourceMappingURL=encoder.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"encoder.js","sourceRoot":"","sources":["../../src/encoder.ts"],"names":[],"mappings":"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 truncated
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
declare enum HeaderTypes {
|
||||
BITMAP_INFO_HEADER = 40,
|
||||
BITMAP_V2_INFO_HEADER = 52,
|
||||
BITMAP_V3_INFO_HEADER = 56,
|
||||
BITMAP_V4_HEADER = 108,
|
||||
BITMAP_V5_HEADER = 124
|
||||
}
|
||||
export default HeaderTypes;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var HeaderTypes;
|
||||
(function (HeaderTypes) {
|
||||
HeaderTypes[HeaderTypes["BITMAP_INFO_HEADER"] = 40] = "BITMAP_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V2_INFO_HEADER"] = 52] = "BITMAP_V2_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V3_INFO_HEADER"] = 56] = "BITMAP_V3_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V4_HEADER"] = 108] = "BITMAP_V4_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V5_HEADER"] = 124] = "BITMAP_V5_HEADER";
|
||||
})(HeaderTypes || (HeaderTypes = {}));
|
||||
exports.default = HeaderTypes;
|
||||
//# sourceMappingURL=header-types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"header-types.js","sourceRoot":"","sources":["../../src/header-types.ts"],"names":[],"mappings":";;AAAA,IAAK,WAMJ;AAND,WAAK,WAAW;IACd,0EAAuB,CAAA;IACvB,gFAA0B,CAAA;IAC1B,gFAA0B,CAAA;IAC1B,uEAAsB,CAAA;IACtB,uEAAsB,CAAA;AACxB,CAAC,EANI,WAAW,KAAX,WAAW,QAMf;AAED,kBAAe,WAAW,CAAC"}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/// <reference types="node" />
|
||||
import BmpDecoder from './decoder.js';
|
||||
import BmpEncoder from './encoder.js';
|
||||
import { BmpDecoderOptions, BmpImage } from './types.js';
|
||||
export declare function decode(bmpData: Buffer, options?: BmpDecoderOptions): BmpDecoder;
|
||||
export declare function encode(imgData: BmpImage): BmpEncoder;
|
||||
export * from './types.js';
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.encode = exports.decode = void 0;
|
||||
const decoder_js_1 = __importDefault(require("./decoder.js"));
|
||||
const encoder_js_1 = __importDefault(require("./encoder.js"));
|
||||
function decode(bmpData, options) {
|
||||
return new decoder_js_1.default(bmpData, options);
|
||||
}
|
||||
exports.decode = decode;
|
||||
function encode(imgData) {
|
||||
return new encoder_js_1.default(imgData);
|
||||
}
|
||||
exports.encode = encode;
|
||||
__exportStar(require("./types.js"), exports);
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,8DAAsC;AACtC,8DAAsC;AAGtC,SAAgB,MAAM,CAAC,OAAe,EAAE,OAA2B;IACjE,OAAO,IAAI,oBAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AAFD,wBAEC;AACD,SAAgB,MAAM,CAAC,OAAiB;IACtC,OAAO,IAAI,oBAAU,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAFD,wBAEC;AAED,6CAA2B"}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export default function maskColor(maskRed: number, maskGreen: number, maskBlue: number, maskAlpha: number): {
|
||||
shiftRed: (x: number) => number;
|
||||
shiftGreen: (x: number) => number;
|
||||
shiftBlue: (x: number) => number;
|
||||
shiftAlpha: (x: number) => number;
|
||||
};
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
"use strict";
|
||||
// We have these:
|
||||
//
|
||||
// const sample = 0101 0101 0101 0101
|
||||
// const mask = 0111 1100 0000 0000
|
||||
// 256 === 0000 0001 0000 0000
|
||||
//
|
||||
// We want to take the sample and turn it into an 8-bit value.
|
||||
//
|
||||
// 1. We extract the last bit of the mask:
|
||||
//
|
||||
// 0000 0100 0000 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const a = ~mask = 1000 0011 1111 1111
|
||||
// const b = a + 1 = 1000 0100 0000 0000
|
||||
// const c = b & mask = 0000 0100 0000 0000
|
||||
//
|
||||
// 2. We shift it to the right and extract the bit before the first:
|
||||
//
|
||||
// 0000 0000 0010 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const d = mask / c = 0000 0000 0001 1111
|
||||
// const e = mask + 1 = 0000 0000 0010 0000
|
||||
//
|
||||
// 3. We apply the mask and the two values above to a sample:
|
||||
//
|
||||
// const f = sample & mask = 0101 0100 0000 0000
|
||||
// const g = f / c = 0000 0000 0001 0101
|
||||
// const h = 256 / e = 0000 0000 0000 0100
|
||||
// const i = g * h = 0000 0000 1010 1000
|
||||
// ^^^^ ^
|
||||
//
|
||||
// Voila, we have extracted a sample and "stretched" it to 8 bits. For samples
|
||||
// which are already 8-bit, h === 1 and g === i.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
function maskColor(maskRed, maskGreen, maskBlue, maskAlpha) {
|
||||
const maskRedR = (~maskRed + 1) & maskRed;
|
||||
const maskGreenR = (~maskGreen + 1) & maskGreen;
|
||||
const maskBlueR = (~maskBlue + 1) & maskBlue;
|
||||
const maskAlphaR = (~maskAlpha + 1) & maskAlpha;
|
||||
const shiftedMaskRedL = maskRed / maskRedR + 1;
|
||||
const shiftedMaskGreenL = maskGreen / maskGreenR + 1;
|
||||
const shiftedMaskBlueL = maskBlue / maskBlueR + 1;
|
||||
const shiftedMaskAlphaL = maskAlpha / maskAlphaR + 1;
|
||||
return {
|
||||
shiftRed: (x) => (((x & maskRed) / maskRedR) * 0x100) / shiftedMaskRedL,
|
||||
shiftGreen: (x) => (((x & maskGreen) / maskGreenR) * 0x100) / shiftedMaskGreenL,
|
||||
shiftBlue: (x) => (((x & maskBlue) / maskBlueR) * 0x100) / shiftedMaskBlueL,
|
||||
shiftAlpha: maskAlpha !== 0
|
||||
? (x) => (((x & maskAlpha) / maskAlphaR) * 0x100) / shiftedMaskAlphaL
|
||||
: () => 255,
|
||||
};
|
||||
}
|
||||
exports.default = maskColor;
|
||||
//# sourceMappingURL=mask-color.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mask-color.js","sourceRoot":"","sources":["../../src/mask-color.ts"],"names":[],"mappings":";AAAA,iBAAiB;AACjB,EAAE;AACF,qCAAqC;AACrC,qCAAqC;AACrC,qCAAqC;AACrC,EAAE;AACF,8DAA8D;AAC9D,EAAE;AACF,0CAA0C;AAC1C,EAAE;AACF,sBAAsB;AACtB,UAAU;AACV,EAAE;AACF,WAAW;AACX,EAAE;AACF,2CAA2C;AAC3C,2CAA2C;AAC3C,2CAA2C;AAC3C,EAAE;AACF,oEAAoE;AACpE,EAAE;AACF,sBAAsB;AACtB,gBAAgB;AAChB,EAAE;AACF,WAAW;AACX,EAAE;AACF,2CAA2C;AAC3C,2CAA2C;AAC3C,EAAE;AACF,6DAA6D;AAC7D,EAAE;AACF,gDAAgD;AAChD,gDAAgD;AAChD,gDAAgD;AAChD,gDAAgD;AAChD,6CAA6C;AAC7C,EAAE;AACF,8EAA8E;AAC9E,gDAAgD;;AAEhD,SAAwB,SAAS,CAC/B,OAAe,EACf,SAAiB,EACjB,QAAgB,EAChB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;IAC1C,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAChD,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC7C,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAEhD,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC;IAErD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CACtB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,eAAe;QACxD,UAAU,EAAE,CAAC,CAAS,EAAE,EAAE,CACxB,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,GAAG,iBAAiB;QAC9D,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CACvB,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,gBAAgB;QAC3D,UAAU,EACR,SAAS,KAAK,CAAC;YACb,CAAC,CAAC,CAAC,CAAS,EAAE,EAAE,CACZ,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,GAAG,iBAAiB;YAChE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG;KAChB,CAAC;AACJ,CAAC;AA7BD,4BA6BC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "commonjs"
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/// <reference types="node" />
|
||||
export declare enum BmpCompression {
|
||||
NONE = 0,
|
||||
BI_RLE8 = 1,
|
||||
BI_RLE4 = 2,
|
||||
BI_BIT_FIELDS = 3,
|
||||
BI_ALPHA_BIT_FIELDS = 6
|
||||
}
|
||||
export interface BmpColor {
|
||||
red: number;
|
||||
green: number;
|
||||
blue: number;
|
||||
quad: number;
|
||||
}
|
||||
export interface BmpDecoderOptions {
|
||||
toRGBA?: boolean;
|
||||
}
|
||||
export interface BmpImage {
|
||||
width: number;
|
||||
height: number;
|
||||
data: Buffer;
|
||||
flag?: string;
|
||||
fileSize?: number;
|
||||
/**
|
||||
* Used to store extra data or information in the image file structure that isn't typically used or necessary for interpreting the basic image data. These reserved fields are often set to 0 when not used. They are each two bytes in size. If the programmer or software uses these for specific purposes, it should be documented accordingly.
|
||||
*/
|
||||
reserved1?: number;
|
||||
/**
|
||||
* Used to store extra data or information in the image file structure that isn't typically used or necessary for interpreting the basic image data. These reserved fields are often set to 0 when not used. They are each two bytes in size. If the programmer or software uses these for specific purposes, it should be documented accordingly.
|
||||
*/
|
||||
reserved2?: number;
|
||||
offset?: number;
|
||||
headerSize?: number;
|
||||
planes?: number;
|
||||
bitPP?: number;
|
||||
compression?: BmpCompression;
|
||||
rawSize?: number;
|
||||
/**
|
||||
* The hr value is used to store information about the intended pixel density of the image when printed or displayed. It doesn't directly influence how the image is displayed on the screen, as screens don't usually have the ability to adjust their pixel density
|
||||
*/
|
||||
hr?: number;
|
||||
/**
|
||||
* Signifies the vertical resolution of the image in pixels per meter. This value is meant to store information about the targeted pixel density of the image when it is displayed or printed.
|
||||
*/
|
||||
vr?: number;
|
||||
/**
|
||||
* represents the number of color indexes in the color table actually used by the bitmap. This value is stored as a 4-byte field.
|
||||
* For a 24-bit bitmap, the colors field will be 0, as each pixel is defined by explicit Red, Green, and Blue values, making a color table unnecessary.
|
||||
* However, for less than 24-bit bitmaps (like 1-bit, 4-bit, 8-bit), the value of the field specifies how many colors are used. For example, an 8-bit bitmap can display up to 256 different colors. If all possible colors are utilized, this field will be 256.
|
||||
* When the colors field is 0 in these situations, it means that the maximum number of colors for the given bits-per-pixel (bitPP) value are used. For instance, if an 8-bit bitmap has colors set to 0, it means it uses 256 colors.
|
||||
* In cases where the bitmap contains a color palette but doesn't use all the potential colors, the colors field would contain the actual number of colors used in the palette.
|
||||
*/
|
||||
colors?: number;
|
||||
/**
|
||||
* specifies the number of color indexes in the color table that are considered important for displaying the bitmap. This value is stored as a 4-byte field.
|
||||
* If this value is 0, then all colors are considered important. This is often the case for most bitmaps.
|
||||
* This field has significance for devices with limited color display capabilities. If the device cannot display the full range of colors in the bitmap, it will refer to the importantColors field to decide which colors to prioritize. However, in modern systems with sophisticated color capabilities, this field is often disregarded.
|
||||
*/
|
||||
importantColors?: number;
|
||||
/**
|
||||
* A palette, in the context of the Bitmap (BMP) image file format, is a table that defines the colors that are used in the image. This feature is typically used in images that have less than 24 bits per pixel (bitPP).
|
||||
* The palette follows the BITMAPINFOHEADER or BITMAPV4HEADER (or similar) structure and precedes the actual pixel data in the file. Each entry in the palette corresponds to a single color, using either 3 bytes (R, G, B) or 4 bytes (R, G, B, 0) in the RGB color space.
|
||||
* For 1-bit images, the palette has 2 colors, for 4-bit images, the palette has 16 colors, and for an 8-bit image, the palette can contain up to 256 colors. The actual number of colors used in the palette is identified by the colors (biClrUsed) field in the header.
|
||||
* For 24-bit and 32-bit BMP, where each pixel is described by distinct R, G, and B (and potentially alpha) values, a palette isn't used or needed.
|
||||
*/
|
||||
palette?: BmpColor[];
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.BmpCompression = void 0;
|
||||
var BmpCompression;
|
||||
(function (BmpCompression) {
|
||||
BmpCompression[BmpCompression["NONE"] = 0] = "NONE";
|
||||
BmpCompression[BmpCompression["BI_RLE8"] = 1] = "BI_RLE8";
|
||||
BmpCompression[BmpCompression["BI_RLE4"] = 2] = "BI_RLE4";
|
||||
BmpCompression[BmpCompression["BI_BIT_FIELDS"] = 3] = "BI_BIT_FIELDS";
|
||||
BmpCompression[BmpCompression["BI_ALPHA_BIT_FIELDS"] = 6] = "BI_ALPHA_BIT_FIELDS";
|
||||
})(BmpCompression || (exports.BmpCompression = BmpCompression = {}));
|
||||
//# sourceMappingURL=types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":";;;AAAA,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,mDAAQ,CAAA;IACR,yDAAW,CAAA;IACX,yDAAW,CAAA;IACX,qEAAiB,CAAA;IACjB,iFAAuB,CAAA;AACzB,CAAC,EANW,cAAc,8BAAd,cAAc,QAMzB"}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
import { BmpCompression, BmpColor, BmpDecoderOptions, BmpImage } from './types.js';
|
||||
export default class BmpDecoder implements BmpImage {
|
||||
flag: string;
|
||||
fileSize: number;
|
||||
reserved1: number;
|
||||
reserved2: number;
|
||||
offset: number;
|
||||
headerSize: number;
|
||||
width: number;
|
||||
height: number;
|
||||
planes: number;
|
||||
bitPP: number;
|
||||
compression?: BmpCompression;
|
||||
rawSize: number;
|
||||
hr: number;
|
||||
vr: number;
|
||||
colors: number;
|
||||
importantColors: number;
|
||||
palette: BmpColor[];
|
||||
data: Buffer;
|
||||
private maskRed;
|
||||
private maskGreen;
|
||||
private maskBlue;
|
||||
private maskAlpha;
|
||||
private readonly toRGBA;
|
||||
private pos;
|
||||
private bottomUp;
|
||||
private readonly buffer;
|
||||
private readonly locRed;
|
||||
private readonly locGreen;
|
||||
private readonly locBlue;
|
||||
private readonly locAlpha;
|
||||
private shiftRed;
|
||||
private shiftGreen;
|
||||
private shiftBlue;
|
||||
private shiftAlpha;
|
||||
constructor(buffer: Buffer, { toRGBA }?: BmpDecoderOptions);
|
||||
private parseHeader;
|
||||
private parseRGBA;
|
||||
private bit1;
|
||||
private bit4;
|
||||
private bit8;
|
||||
private bit16;
|
||||
private bit24;
|
||||
private bit32;
|
||||
private scanImage;
|
||||
private readUInt32LE;
|
||||
private setPixelData;
|
||||
}
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
import HeaderTypes from './header-types.js';
|
||||
import maskColor from './mask-color.js';
|
||||
import { BmpCompression } from './types.js';
|
||||
export default class BmpDecoder {
|
||||
// Header
|
||||
flag;
|
||||
fileSize;
|
||||
reserved1;
|
||||
reserved2;
|
||||
offset;
|
||||
headerSize;
|
||||
width;
|
||||
height;
|
||||
planes;
|
||||
bitPP;
|
||||
compression;
|
||||
rawSize;
|
||||
hr;
|
||||
vr;
|
||||
colors;
|
||||
importantColors;
|
||||
palette;
|
||||
data;
|
||||
maskRed;
|
||||
maskGreen;
|
||||
maskBlue;
|
||||
maskAlpha;
|
||||
toRGBA;
|
||||
pos;
|
||||
bottomUp;
|
||||
buffer;
|
||||
locRed;
|
||||
locGreen;
|
||||
locBlue;
|
||||
locAlpha;
|
||||
shiftRed;
|
||||
shiftGreen;
|
||||
shiftBlue;
|
||||
shiftAlpha;
|
||||
constructor(buffer, { toRGBA } = { toRGBA: false }) {
|
||||
this.buffer = buffer;
|
||||
this.toRGBA = !!toRGBA;
|
||||
this.pos = 0;
|
||||
this.bottomUp = true;
|
||||
this.flag = this.buffer.toString('utf-8', 0, (this.pos += 2));
|
||||
if (this.flag !== 'BM') {
|
||||
throw new Error('Invalid BMP File');
|
||||
}
|
||||
this.locRed = this.toRGBA ? 0 : 3;
|
||||
this.locGreen = this.toRGBA ? 1 : 2;
|
||||
this.locBlue = this.toRGBA ? 2 : 1;
|
||||
this.locAlpha = this.toRGBA ? 3 : 0;
|
||||
this.parseHeader();
|
||||
this.parseRGBA();
|
||||
}
|
||||
parseHeader() {
|
||||
this.fileSize = this.readUInt32LE();
|
||||
this.reserved1 = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.reserved2 = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.offset = this.readUInt32LE();
|
||||
// End of BITMAP_FILE_HEADER
|
||||
this.headerSize = this.readUInt32LE();
|
||||
if (!(this.headerSize in HeaderTypes)) {
|
||||
throw new Error(`Unsupported BMP header size ${this.headerSize}`);
|
||||
}
|
||||
this.width = this.readUInt32LE();
|
||||
this.height = this.readUInt32LE();
|
||||
// negative value are possible here => implies bottom down
|
||||
this.height =
|
||||
this.height > 0x7fffffff ? this.height - 0x100000000 : this.height;
|
||||
this.planes = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.bitPP = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.compression = this.readUInt32LE();
|
||||
this.rawSize = this.readUInt32LE();
|
||||
this.hr = this.readUInt32LE();
|
||||
this.vr = this.readUInt32LE();
|
||||
this.colors = this.readUInt32LE();
|
||||
this.importantColors = this.readUInt32LE();
|
||||
// De facto defaults
|
||||
if (this.bitPP === 32) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x00ff0000;
|
||||
this.maskGreen = 0x0000ff00;
|
||||
this.maskBlue = 0x000000ff;
|
||||
}
|
||||
else if (this.bitPP === 16) {
|
||||
this.maskAlpha = 0;
|
||||
this.maskRed = 0x7c00;
|
||||
this.maskGreen = 0x03e0;
|
||||
this.maskBlue = 0x001f;
|
||||
}
|
||||
// End of BITMAP_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_INFO_HEADER ||
|
||||
this.compression === BmpCompression.BI_BIT_FIELDS ||
|
||||
this.compression === BmpCompression.BI_ALPHA_BIT_FIELDS) {
|
||||
this.maskRed = this.readUInt32LE();
|
||||
this.maskGreen = this.readUInt32LE();
|
||||
this.maskBlue = this.readUInt32LE();
|
||||
}
|
||||
// End of BITMAP_V2_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V2_INFO_HEADER ||
|
||||
this.compression === BmpCompression.BI_ALPHA_BIT_FIELDS) {
|
||||
this.maskAlpha = this.readUInt32LE();
|
||||
}
|
||||
// End of BITMAP_V3_INFO_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V3_INFO_HEADER) {
|
||||
this.pos +=
|
||||
HeaderTypes.BITMAP_V4_HEADER - HeaderTypes.BITMAP_V3_INFO_HEADER;
|
||||
}
|
||||
// End of BITMAP_V4_HEADER
|
||||
if (this.headerSize > HeaderTypes.BITMAP_V4_HEADER) {
|
||||
this.pos += HeaderTypes.BITMAP_V5_HEADER - HeaderTypes.BITMAP_V4_HEADER;
|
||||
}
|
||||
// End of BITMAP_V5_HEADER
|
||||
if (this.bitPP <= 8 || this.colors > 0) {
|
||||
const len = this.colors === 0 ? 1 << this.bitPP : this.colors;
|
||||
this.palette = new Array(len);
|
||||
for (let i = 0; i < len; i++) {
|
||||
const blue = this.buffer.readUInt8(this.pos++);
|
||||
const green = this.buffer.readUInt8(this.pos++);
|
||||
const red = this.buffer.readUInt8(this.pos++);
|
||||
const quad = this.buffer.readUInt8(this.pos++);
|
||||
this.palette[i] = {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
quad,
|
||||
};
|
||||
}
|
||||
}
|
||||
// End of color table
|
||||
// Can the height ever be negative?
|
||||
if (this.height < 0) {
|
||||
this.height *= -1;
|
||||
this.bottomUp = false;
|
||||
}
|
||||
const coloShift = maskColor(this.maskRed, this.maskGreen, this.maskBlue, this.maskAlpha);
|
||||
this.shiftRed = coloShift.shiftRed;
|
||||
this.shiftGreen = coloShift.shiftGreen;
|
||||
this.shiftBlue = coloShift.shiftBlue;
|
||||
this.shiftAlpha = coloShift.shiftAlpha;
|
||||
}
|
||||
parseRGBA() {
|
||||
this.data = Buffer.alloc(this.width * this.height * 4);
|
||||
switch (this.bitPP) {
|
||||
case 1:
|
||||
this.bit1();
|
||||
break;
|
||||
case 4:
|
||||
this.bit4();
|
||||
break;
|
||||
case 8:
|
||||
this.bit8();
|
||||
break;
|
||||
case 16:
|
||||
this.bit16();
|
||||
break;
|
||||
case 24:
|
||||
this.bit24();
|
||||
break;
|
||||
default:
|
||||
this.bit32();
|
||||
}
|
||||
}
|
||||
bit1() {
|
||||
const xLen = Math.ceil(this.width / 8);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
let lastLine;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
if (line !== lastLine) {
|
||||
lastLine = line;
|
||||
}
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 8 * 4;
|
||||
for (let i = 0; i < 8; i++) {
|
||||
if (x * 8 + i < this.width) {
|
||||
const rgb = this.palette[(b >> (7 - i)) & 0x1];
|
||||
this.data[location + i * this.locAlpha] = 0;
|
||||
this.data[location + i * 4 + this.locBlue] = rgb.blue;
|
||||
this.data[location + i * 4 + this.locGreen] = rgb.green;
|
||||
this.data[location + i * 4 + this.locRed] = rgb.red;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
bit4() {
|
||||
if (this.compression === BmpCompression.BI_RLE4) {
|
||||
this.data.fill(0);
|
||||
let lowNibble = false; //for all count of pixel
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.buffer.readUInt8(this.pos++);
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
lowNibble = false;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
// image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
// offset x, y
|
||||
const x = this.buffer.readUInt8(this.pos++);
|
||||
const y = this.buffer.readUInt8(this.pos++);
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
let c = this.buffer.readUInt8(this.pos++);
|
||||
for (let i = 0; i < b; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? c & 0x0f : (c & 0xf0) >> 4);
|
||||
if (i & 1 && i + 1 < b) {
|
||||
c = this.buffer.readUInt8(this.pos++);
|
||||
}
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
if ((((b + 1) >> 1) & 1) === 1) {
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, lowNibble ? b & 0x0f : (b & 0xf0) >> 4);
|
||||
lowNibble = !lowNibble;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const xLen = Math.ceil(this.width / 2);
|
||||
const mode = xLen % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, xLen, (x, line) => {
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 2 * 4;
|
||||
const first4 = b >> 4;
|
||||
let rgb = this.palette[first4];
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = rgb.blue;
|
||||
this.data[location + 2] = rgb.green;
|
||||
this.data[location + 3] = rgb.red;
|
||||
if (x * 2 + 1 >= this.width) {
|
||||
// throw new Error('Something');
|
||||
return false;
|
||||
}
|
||||
const last4 = b & 0x0f;
|
||||
rgb = this.palette[last4];
|
||||
this.data[location + 4] = 0;
|
||||
this.data[location + 4 + 1] = rgb.blue;
|
||||
this.data[location + 4 + 2] = rgb.green;
|
||||
this.data[location + 4 + 3] = rgb.red;
|
||||
});
|
||||
}
|
||||
}
|
||||
bit8() {
|
||||
if (this.compression === BmpCompression.BI_RLE8) {
|
||||
this.data.fill(0);
|
||||
let lines = this.bottomUp ? this.height - 1 : 0;
|
||||
let location = 0;
|
||||
while (location < this.data.length) {
|
||||
const a = this.buffer.readUInt8(this.pos++);
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
//absolute mode
|
||||
if (a === 0) {
|
||||
if (b === 0) {
|
||||
//line end
|
||||
lines += this.bottomUp ? -1 : 1;
|
||||
location = lines * this.width * 4;
|
||||
continue;
|
||||
}
|
||||
if (b === 1) {
|
||||
//image end
|
||||
break;
|
||||
}
|
||||
if (b === 2) {
|
||||
//offset x,y
|
||||
const x = this.buffer.readUInt8(this.pos++);
|
||||
const y = this.buffer.readUInt8(this.pos++);
|
||||
lines += this.bottomUp ? -y : y;
|
||||
location += y * this.width * 4 + x * 4;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < b; i++) {
|
||||
const c = this.buffer.readUInt8(this.pos++);
|
||||
location = this.setPixelData(location, c);
|
||||
}
|
||||
// @ts-ignore
|
||||
const shouldIncrement = b & (1 === 1);
|
||||
if (shouldIncrement) {
|
||||
this.pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//encoded mode
|
||||
for (let i = 0; i < a; i++) {
|
||||
location = this.setPixelData(location, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const mode = this.width % 4;
|
||||
const padding = mode !== 0 ? 4 - mode : 0;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const b = this.buffer.readUInt8(this.pos++);
|
||||
const location = line * this.width * 4 + x * 4;
|
||||
if (b < this.palette.length) {
|
||||
const rgb = this.palette[b];
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = rgb.blue;
|
||||
this.data[location + 2] = rgb.green;
|
||||
this.data[location + 3] = rgb.red;
|
||||
}
|
||||
else {
|
||||
this.data[location] = 0;
|
||||
this.data[location + 1] = 0xff;
|
||||
this.data[location + 2] = 0xff;
|
||||
this.data[location + 3] = 0xff;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
bit16() {
|
||||
const padding = (this.width % 2) * 2;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.buffer.readUInt16LE(this.pos);
|
||||
this.pos += 2;
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = this.shiftAlpha(px);
|
||||
});
|
||||
}
|
||||
bit24() {
|
||||
const padding = this.width % 4;
|
||||
this.scanImage(padding, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const blue = this.buffer.readUInt8(this.pos++);
|
||||
const green = this.buffer.readUInt8(this.pos++);
|
||||
const red = this.buffer.readUInt8(this.pos++);
|
||||
this.data[loc + this.locRed] = red;
|
||||
this.data[loc + this.locGreen] = green;
|
||||
this.data[loc + this.locBlue] = blue;
|
||||
this.data[loc + this.locAlpha] = 0;
|
||||
});
|
||||
}
|
||||
bit32() {
|
||||
this.scanImage(0, this.width, (x, line) => {
|
||||
const loc = line * this.width * 4 + x * 4;
|
||||
const px = this.readUInt32LE();
|
||||
this.data[loc + this.locRed] = this.shiftRed(px);
|
||||
this.data[loc + this.locGreen] = this.shiftGreen(px);
|
||||
this.data[loc + this.locBlue] = this.shiftBlue(px);
|
||||
this.data[loc + this.locAlpha] = this.shiftAlpha(px);
|
||||
});
|
||||
}
|
||||
scanImage(padding = 0, width = this.width, processPixel) {
|
||||
for (let y = this.height - 1; y >= 0; y--) {
|
||||
const line = this.bottomUp ? y : this.height - 1 - y;
|
||||
for (let x = 0; x < width; x++) {
|
||||
const result = processPixel.call(this, x, line);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.pos += padding;
|
||||
}
|
||||
}
|
||||
readUInt32LE() {
|
||||
const value = this.buffer.readUInt32LE(this.pos);
|
||||
this.pos += 4;
|
||||
return value;
|
||||
}
|
||||
setPixelData(location, rgbIndex) {
|
||||
const { blue, green, red } = this.palette[rgbIndex];
|
||||
this.data[location + this.locAlpha] = 0;
|
||||
this.data[location + 1 + this.locBlue] = blue;
|
||||
this.data[location + 2 + this.locGreen] = green;
|
||||
this.data[location + 3 + this.locRed] = red;
|
||||
return location + 4;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=decoder.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"decoder.js","sourceRoot":"","sources":["../../src/decoder.ts"],"names":[],"mappings":"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 truncated
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
import { BmpColor, BmpImage } from './types.js';
|
||||
export default class BmpEncoder implements BmpImage {
|
||||
readonly fileSize: number;
|
||||
readonly reserved1: number;
|
||||
readonly reserved2: number;
|
||||
readonly offset: number;
|
||||
readonly width: number;
|
||||
readonly flag: string;
|
||||
readonly height: number;
|
||||
readonly planes: number;
|
||||
readonly bitPP: number;
|
||||
readonly compress: number;
|
||||
readonly hr: number;
|
||||
readonly vr: number;
|
||||
readonly colors: number;
|
||||
readonly importantColors: number;
|
||||
readonly rawSize: number;
|
||||
readonly headerSize: number;
|
||||
readonly data: Buffer;
|
||||
readonly palette: BmpColor[];
|
||||
private readonly extraBytes;
|
||||
private readonly buffer;
|
||||
private readonly bytesInColor;
|
||||
private pos;
|
||||
constructor(imgData: BmpImage);
|
||||
encode(): void;
|
||||
private writeHeader;
|
||||
private bit1;
|
||||
private bit4;
|
||||
private bit8;
|
||||
private bit16;
|
||||
private bit24;
|
||||
private bit32;
|
||||
private writeImage;
|
||||
private initColors;
|
||||
private writeUInt32LE;
|
||||
}
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
import HeaderTypes from './header-types.js';
|
||||
function createInteger(numbers) {
|
||||
return numbers.reduce((final, n) => (final << 1) | n, 0);
|
||||
}
|
||||
function createColor(color) {
|
||||
return ((color.quad << 24) | (color.red << 16) | (color.green << 8) | color.blue);
|
||||
}
|
||||
export default class BmpEncoder {
|
||||
fileSize;
|
||||
reserved1;
|
||||
reserved2;
|
||||
offset;
|
||||
width;
|
||||
flag;
|
||||
height;
|
||||
planes;
|
||||
bitPP;
|
||||
compress;
|
||||
hr;
|
||||
vr;
|
||||
colors;
|
||||
importantColors;
|
||||
rawSize;
|
||||
headerSize;
|
||||
data;
|
||||
palette;
|
||||
extraBytes;
|
||||
buffer;
|
||||
bytesInColor;
|
||||
pos;
|
||||
constructor(imgData) {
|
||||
this.buffer = imgData.data;
|
||||
this.width = imgData.width;
|
||||
this.height = imgData.height;
|
||||
this.headerSize = HeaderTypes.BITMAP_INFO_HEADER;
|
||||
// Header
|
||||
this.flag = 'BM';
|
||||
this.bitPP = imgData.bitPP || 24;
|
||||
this.offset = 54;
|
||||
this.reserved1 = imgData.reserved1 || 0;
|
||||
this.reserved2 = imgData.reserved2 || 0;
|
||||
this.planes = 1;
|
||||
this.compress = 0;
|
||||
this.hr = imgData.hr || 0;
|
||||
this.vr = imgData.vr || 0;
|
||||
this.importantColors = imgData.importantColors || 0;
|
||||
this.colors = Math.min(2 ** (this.bitPP - 1 || 1), imgData.colors || Infinity);
|
||||
this.palette = imgData.palette || [];
|
||||
if (this.colors && this.bitPP < 16) {
|
||||
this.offset += this.colors * 4;
|
||||
}
|
||||
else {
|
||||
this.colors = 0;
|
||||
}
|
||||
switch (this.bitPP) {
|
||||
case 32:
|
||||
this.bytesInColor = 4;
|
||||
break;
|
||||
case 16:
|
||||
this.bytesInColor = 2;
|
||||
break;
|
||||
case 8:
|
||||
this.bytesInColor = 1;
|
||||
break;
|
||||
case 4:
|
||||
this.bytesInColor = 1 / 2;
|
||||
break;
|
||||
case 1:
|
||||
this.bytesInColor = 1 / 8;
|
||||
break;
|
||||
default:
|
||||
this.bytesInColor = 3;
|
||||
this.bitPP = 24;
|
||||
}
|
||||
const rowWidth = (this.width * this.bitPP) / 32;
|
||||
const rowBytes = Math.ceil(rowWidth);
|
||||
this.extraBytes = (rowBytes - rowWidth) * 4;
|
||||
// Why 2?
|
||||
this.rawSize = this.height * rowBytes * 4 + 2;
|
||||
this.fileSize = this.rawSize + this.offset;
|
||||
this.data = Buffer.alloc(this.fileSize, 0x1);
|
||||
this.pos = 0;
|
||||
this.encode();
|
||||
}
|
||||
encode() {
|
||||
this.pos = 0;
|
||||
this.writeHeader();
|
||||
switch (this.bitPP) {
|
||||
case 32:
|
||||
this.bit32();
|
||||
break;
|
||||
case 16:
|
||||
this.bit16();
|
||||
break;
|
||||
case 8:
|
||||
this.bit8();
|
||||
break;
|
||||
case 4:
|
||||
this.bit4();
|
||||
break;
|
||||
case 1:
|
||||
this.bit1();
|
||||
break;
|
||||
default:
|
||||
this.bit24();
|
||||
}
|
||||
}
|
||||
writeHeader() {
|
||||
this.data.write(this.flag, this.pos, 2);
|
||||
this.pos += 2;
|
||||
this.writeUInt32LE(this.fileSize);
|
||||
// Writing 2 UInt16LE resulted in a weird bug
|
||||
this.writeUInt32LE((this.reserved1 << 16) | this.reserved2);
|
||||
this.writeUInt32LE(this.offset);
|
||||
this.writeUInt32LE(this.headerSize);
|
||||
this.writeUInt32LE(this.width);
|
||||
this.writeUInt32LE(this.height);
|
||||
this.data.writeUInt16LE(this.planes, this.pos);
|
||||
this.pos += 2;
|
||||
this.data.writeUInt16LE(this.bitPP, this.pos);
|
||||
this.pos += 2;
|
||||
this.writeUInt32LE(this.compress);
|
||||
this.writeUInt32LE(this.rawSize);
|
||||
this.writeUInt32LE(this.hr);
|
||||
this.writeUInt32LE(this.vr);
|
||||
this.writeUInt32LE(this.colors);
|
||||
this.writeUInt32LE(this.importantColors);
|
||||
}
|
||||
bit1() {
|
||||
if (this.palette.length && this.colors === 2) {
|
||||
this.initColors(1);
|
||||
}
|
||||
else {
|
||||
this.writeUInt32LE(0x00ffffff); // Black
|
||||
this.writeUInt32LE(0x00000000); // White
|
||||
}
|
||||
this.pos += 1; // ?
|
||||
let lineArr = [];
|
||||
this.writeImage((p, index, x) => {
|
||||
let i = index;
|
||||
i++;
|
||||
const b = this.buffer[i++];
|
||||
const g = this.buffer[i++];
|
||||
const r = this.buffer[i++];
|
||||
const brightness = r * 0.2126 + g * 0.7152 + b * 0.0722;
|
||||
lineArr.push(brightness > 127 ? 0 : 1);
|
||||
if ((x + 1) % 8 === 0) {
|
||||
this.data[p - 1] = createInteger(lineArr);
|
||||
lineArr = [];
|
||||
}
|
||||
else if (x === this.width - 1 && lineArr.length > 0) {
|
||||
this.data[p - 1] = createInteger(lineArr) << 4;
|
||||
lineArr = [];
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit4() {
|
||||
const colors = this.initColors(4);
|
||||
let integerPair = [];
|
||||
this.writeImage((p, index, x) => {
|
||||
let i = index;
|
||||
const colorInt = createColor({
|
||||
quad: this.buffer[i++],
|
||||
blue: this.buffer[i++],
|
||||
green: this.buffer[i++],
|
||||
red: this.buffer[i++],
|
||||
});
|
||||
const colorExists = colors.findIndex((c) => c === colorInt);
|
||||
if (colorExists !== -1) {
|
||||
integerPair.push(colorExists);
|
||||
}
|
||||
else {
|
||||
integerPair.push(0);
|
||||
}
|
||||
if ((x + 1) % 2 === 0) {
|
||||
this.data[p] = (integerPair[0] << 4) | integerPair[1];
|
||||
integerPair = [];
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit8() {
|
||||
const colors = this.initColors(8);
|
||||
this.writeImage((p, index) => {
|
||||
let i = index;
|
||||
const colorInt = createColor({
|
||||
quad: this.buffer[i++],
|
||||
blue: this.buffer[i++],
|
||||
green: this.buffer[i++],
|
||||
red: this.buffer[i++],
|
||||
});
|
||||
const colorExists = colors.findIndex((c) => c === colorInt);
|
||||
if (colorExists !== -1) {
|
||||
this.data[p] = colorExists;
|
||||
}
|
||||
else {
|
||||
this.data[p] = 0;
|
||||
}
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit16() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index + 1;
|
||||
const b = this.buffer[i++] / 8; // b
|
||||
const g = this.buffer[i++] / 8; // g
|
||||
const r = this.buffer[i++] / 8; // r
|
||||
const color = (r << 10) | (g << 5) | b;
|
||||
this.data[p] = color & 0x00ff;
|
||||
this.data[p + 1] = (color & 0xff00) >> 8;
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit24() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index + 1;
|
||||
this.data[p] = this.buffer[i++]; //b
|
||||
this.data[p + 1] = this.buffer[i++]; //g
|
||||
this.data[p + 2] = this.buffer[i++]; //r
|
||||
return i;
|
||||
});
|
||||
}
|
||||
bit32() {
|
||||
this.writeImage((p, index) => {
|
||||
let i = index;
|
||||
this.data[p + 3] = this.buffer[i++]; // a
|
||||
this.data[p] = this.buffer[i++]; // b
|
||||
this.data[p + 1] = this.buffer[i++]; // g
|
||||
this.data[p + 2] = this.buffer[i++]; // r
|
||||
return i;
|
||||
});
|
||||
}
|
||||
writeImage(writePixel) {
|
||||
const rowBytes = this.extraBytes + this.width * this.bytesInColor;
|
||||
let i = 0;
|
||||
for (let y = 0; y < this.height; y++) {
|
||||
for (let x = 0; x < this.width; x++) {
|
||||
const p = Math.floor(this.pos + (this.height - 1 - y) * rowBytes + x * this.bytesInColor);
|
||||
i = writePixel.call(this, p, i, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
initColors(bit) {
|
||||
const colors = [];
|
||||
if (this.palette.length) {
|
||||
for (let i = 0; i < this.colors; i++) {
|
||||
const rootColor = createColor(this.palette[i]);
|
||||
this.writeUInt32LE(rootColor);
|
||||
colors.push(rootColor);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error(`To encode ${bit}-bit BMPs a pallette is needed. Please choose up to ${this.colors} colors. Colors must be 32-bit integers.`);
|
||||
}
|
||||
return colors;
|
||||
}
|
||||
writeUInt32LE(value) {
|
||||
this.data.writeUInt32LE(value, this.pos);
|
||||
this.pos += 4;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=encoder.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"encoder.js","sourceRoot":"","sources":["../../src/encoder.ts"],"names":[],"mappings":"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 truncated
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
declare enum HeaderTypes {
|
||||
BITMAP_INFO_HEADER = 40,
|
||||
BITMAP_V2_INFO_HEADER = 52,
|
||||
BITMAP_V3_INFO_HEADER = 56,
|
||||
BITMAP_V4_HEADER = 108,
|
||||
BITMAP_V5_HEADER = 124
|
||||
}
|
||||
export default HeaderTypes;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
var HeaderTypes;
|
||||
(function (HeaderTypes) {
|
||||
HeaderTypes[HeaderTypes["BITMAP_INFO_HEADER"] = 40] = "BITMAP_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V2_INFO_HEADER"] = 52] = "BITMAP_V2_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V3_INFO_HEADER"] = 56] = "BITMAP_V3_INFO_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V4_HEADER"] = 108] = "BITMAP_V4_HEADER";
|
||||
HeaderTypes[HeaderTypes["BITMAP_V5_HEADER"] = 124] = "BITMAP_V5_HEADER";
|
||||
})(HeaderTypes || (HeaderTypes = {}));
|
||||
export default HeaderTypes;
|
||||
//# sourceMappingURL=header-types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"header-types.js","sourceRoot":"","sources":["../../src/header-types.ts"],"names":[],"mappings":"AAAA,IAAK,WAMJ;AAND,WAAK,WAAW;IACd,0EAAuB,CAAA;IACvB,gFAA0B,CAAA;IAC1B,gFAA0B,CAAA;IAC1B,uEAAsB,CAAA;IACtB,uEAAsB,CAAA;AACxB,CAAC,EANI,WAAW,KAAX,WAAW,QAMf;AAED,eAAe,WAAW,CAAC"}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
import BmpDecoder from './decoder.js';
|
||||
import BmpEncoder from './encoder.js';
|
||||
import { BmpDecoderOptions, BmpImage } from './types.js';
|
||||
export declare function decode(bmpData: Buffer, options?: BmpDecoderOptions): BmpDecoder;
|
||||
export declare function encode(imgData: BmpImage): BmpEncoder;
|
||||
export * from './types.js';
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
import BmpDecoder from './decoder.js';
|
||||
import BmpEncoder from './encoder.js';
|
||||
export function decode(bmpData, options) {
|
||||
return new BmpDecoder(bmpData, options);
|
||||
}
|
||||
export function encode(imgData) {
|
||||
return new BmpEncoder(imgData);
|
||||
}
|
||||
export * from './types.js';
|
||||
//# sourceMappingURL=index.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,cAAc,CAAC;AACtC,OAAO,UAAU,MAAM,cAAc,CAAC;AAGtC,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,OAA2B;IACjE,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AAC1C,CAAC;AACD,MAAM,UAAU,MAAM,CAAC,OAAiB;IACtC,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,cAAc,YAAY,CAAC"}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
export default function maskColor(maskRed: number, maskGreen: number, maskBlue: number, maskAlpha: number): {
|
||||
shiftRed: (x: number) => number;
|
||||
shiftGreen: (x: number) => number;
|
||||
shiftBlue: (x: number) => number;
|
||||
shiftAlpha: (x: number) => number;
|
||||
};
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
// We have these:
|
||||
//
|
||||
// const sample = 0101 0101 0101 0101
|
||||
// const mask = 0111 1100 0000 0000
|
||||
// 256 === 0000 0001 0000 0000
|
||||
//
|
||||
// We want to take the sample and turn it into an 8-bit value.
|
||||
//
|
||||
// 1. We extract the last bit of the mask:
|
||||
//
|
||||
// 0000 0100 0000 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const a = ~mask = 1000 0011 1111 1111
|
||||
// const b = a + 1 = 1000 0100 0000 0000
|
||||
// const c = b & mask = 0000 0100 0000 0000
|
||||
//
|
||||
// 2. We shift it to the right and extract the bit before the first:
|
||||
//
|
||||
// 0000 0000 0010 0000
|
||||
// ^
|
||||
//
|
||||
// Like so:
|
||||
//
|
||||
// const d = mask / c = 0000 0000 0001 1111
|
||||
// const e = mask + 1 = 0000 0000 0010 0000
|
||||
//
|
||||
// 3. We apply the mask and the two values above to a sample:
|
||||
//
|
||||
// const f = sample & mask = 0101 0100 0000 0000
|
||||
// const g = f / c = 0000 0000 0001 0101
|
||||
// const h = 256 / e = 0000 0000 0000 0100
|
||||
// const i = g * h = 0000 0000 1010 1000
|
||||
// ^^^^ ^
|
||||
//
|
||||
// Voila, we have extracted a sample and "stretched" it to 8 bits. For samples
|
||||
// which are already 8-bit, h === 1 and g === i.
|
||||
export default function maskColor(maskRed, maskGreen, maskBlue, maskAlpha) {
|
||||
const maskRedR = (~maskRed + 1) & maskRed;
|
||||
const maskGreenR = (~maskGreen + 1) & maskGreen;
|
||||
const maskBlueR = (~maskBlue + 1) & maskBlue;
|
||||
const maskAlphaR = (~maskAlpha + 1) & maskAlpha;
|
||||
const shiftedMaskRedL = maskRed / maskRedR + 1;
|
||||
const shiftedMaskGreenL = maskGreen / maskGreenR + 1;
|
||||
const shiftedMaskBlueL = maskBlue / maskBlueR + 1;
|
||||
const shiftedMaskAlphaL = maskAlpha / maskAlphaR + 1;
|
||||
return {
|
||||
shiftRed: (x) => (((x & maskRed) / maskRedR) * 0x100) / shiftedMaskRedL,
|
||||
shiftGreen: (x) => (((x & maskGreen) / maskGreenR) * 0x100) / shiftedMaskGreenL,
|
||||
shiftBlue: (x) => (((x & maskBlue) / maskBlueR) * 0x100) / shiftedMaskBlueL,
|
||||
shiftAlpha: maskAlpha !== 0
|
||||
? (x) => (((x & maskAlpha) / maskAlphaR) * 0x100) / shiftedMaskAlphaL
|
||||
: () => 255,
|
||||
};
|
||||
}
|
||||
//# sourceMappingURL=mask-color.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"mask-color.js","sourceRoot":"","sources":["../../src/mask-color.ts"],"names":[],"mappings":"AAAA,iBAAiB;AACjB,EAAE;AACF,qCAAqC;AACrC,qCAAqC;AACrC,qCAAqC;AACrC,EAAE;AACF,8DAA8D;AAC9D,EAAE;AACF,0CAA0C;AAC1C,EAAE;AACF,sBAAsB;AACtB,UAAU;AACV,EAAE;AACF,WAAW;AACX,EAAE;AACF,2CAA2C;AAC3C,2CAA2C;AAC3C,2CAA2C;AAC3C,EAAE;AACF,oEAAoE;AACpE,EAAE;AACF,sBAAsB;AACtB,gBAAgB;AAChB,EAAE;AACF,WAAW;AACX,EAAE;AACF,2CAA2C;AAC3C,2CAA2C;AAC3C,EAAE;AACF,6DAA6D;AAC7D,EAAE;AACF,gDAAgD;AAChD,gDAAgD;AAChD,gDAAgD;AAChD,gDAAgD;AAChD,6CAA6C;AAC7C,EAAE;AACF,8EAA8E;AAC9E,gDAAgD;AAEhD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,OAAe,EACf,SAAiB,EACjB,QAAgB,EAChB,SAAiB;IAEjB,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC;IAC1C,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAChD,MAAM,SAAS,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IAC7C,MAAM,UAAU,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;IAEhD,MAAM,eAAe,GAAG,OAAO,GAAG,QAAQ,GAAG,CAAC,CAAC;IAC/C,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC;IACrD,MAAM,gBAAgB,GAAG,QAAQ,GAAG,SAAS,GAAG,CAAC,CAAC;IAClD,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC;IAErD,OAAO;QACL,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CACtB,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,QAAQ,CAAC,GAAG,KAAK,CAAC,GAAG,eAAe;QACxD,UAAU,EAAE,CAAC,CAAS,EAAE,EAAE,CACxB,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,GAAG,iBAAiB;QAC9D,SAAS,EAAE,CAAC,CAAS,EAAE,EAAE,CACvB,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,GAAG,gBAAgB;QAC3D,UAAU,EACR,SAAS,KAAK,CAAC;YACb,CAAC,CAAC,CAAC,CAAS,EAAE,EAAE,CACZ,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,UAAU,CAAC,GAAG,KAAK,CAAC,GAAG,iBAAiB;YAChE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG;KAChB,CAAC;AACJ,CAAC"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/// <reference types="node" resolution-mode="require"/>
|
||||
export declare enum BmpCompression {
|
||||
NONE = 0,
|
||||
BI_RLE8 = 1,
|
||||
BI_RLE4 = 2,
|
||||
BI_BIT_FIELDS = 3,
|
||||
BI_ALPHA_BIT_FIELDS = 6
|
||||
}
|
||||
export interface BmpColor {
|
||||
red: number;
|
||||
green: number;
|
||||
blue: number;
|
||||
quad: number;
|
||||
}
|
||||
export interface BmpDecoderOptions {
|
||||
toRGBA?: boolean;
|
||||
}
|
||||
export interface BmpImage {
|
||||
width: number;
|
||||
height: number;
|
||||
data: Buffer;
|
||||
flag?: string;
|
||||
fileSize?: number;
|
||||
/**
|
||||
* Used to store extra data or information in the image file structure that isn't typically used or necessary for interpreting the basic image data. These reserved fields are often set to 0 when not used. They are each two bytes in size. If the programmer or software uses these for specific purposes, it should be documented accordingly.
|
||||
*/
|
||||
reserved1?: number;
|
||||
/**
|
||||
* Used to store extra data or information in the image file structure that isn't typically used or necessary for interpreting the basic image data. These reserved fields are often set to 0 when not used. They are each two bytes in size. If the programmer or software uses these for specific purposes, it should be documented accordingly.
|
||||
*/
|
||||
reserved2?: number;
|
||||
offset?: number;
|
||||
headerSize?: number;
|
||||
planes?: number;
|
||||
bitPP?: number;
|
||||
compression?: BmpCompression;
|
||||
rawSize?: number;
|
||||
/**
|
||||
* The hr value is used to store information about the intended pixel density of the image when printed or displayed. It doesn't directly influence how the image is displayed on the screen, as screens don't usually have the ability to adjust their pixel density
|
||||
*/
|
||||
hr?: number;
|
||||
/**
|
||||
* Signifies the vertical resolution of the image in pixels per meter. This value is meant to store information about the targeted pixel density of the image when it is displayed or printed.
|
||||
*/
|
||||
vr?: number;
|
||||
/**
|
||||
* represents the number of color indexes in the color table actually used by the bitmap. This value is stored as a 4-byte field.
|
||||
* For a 24-bit bitmap, the colors field will be 0, as each pixel is defined by explicit Red, Green, and Blue values, making a color table unnecessary.
|
||||
* However, for less than 24-bit bitmaps (like 1-bit, 4-bit, 8-bit), the value of the field specifies how many colors are used. For example, an 8-bit bitmap can display up to 256 different colors. If all possible colors are utilized, this field will be 256.
|
||||
* When the colors field is 0 in these situations, it means that the maximum number of colors for the given bits-per-pixel (bitPP) value are used. For instance, if an 8-bit bitmap has colors set to 0, it means it uses 256 colors.
|
||||
* In cases where the bitmap contains a color palette but doesn't use all the potential colors, the colors field would contain the actual number of colors used in the palette.
|
||||
*/
|
||||
colors?: number;
|
||||
/**
|
||||
* specifies the number of color indexes in the color table that are considered important for displaying the bitmap. This value is stored as a 4-byte field.
|
||||
* If this value is 0, then all colors are considered important. This is often the case for most bitmaps.
|
||||
* This field has significance for devices with limited color display capabilities. If the device cannot display the full range of colors in the bitmap, it will refer to the importantColors field to decide which colors to prioritize. However, in modern systems with sophisticated color capabilities, this field is often disregarded.
|
||||
*/
|
||||
importantColors?: number;
|
||||
/**
|
||||
* A palette, in the context of the Bitmap (BMP) image file format, is a table that defines the colors that are used in the image. This feature is typically used in images that have less than 24 bits per pixel (bitPP).
|
||||
* The palette follows the BITMAPINFOHEADER or BITMAPV4HEADER (or similar) structure and precedes the actual pixel data in the file. Each entry in the palette corresponds to a single color, using either 3 bytes (R, G, B) or 4 bytes (R, G, B, 0) in the RGB color space.
|
||||
* For 1-bit images, the palette has 2 colors, for 4-bit images, the palette has 16 colors, and for an 8-bit image, the palette can contain up to 256 colors. The actual number of colors used in the palette is identified by the colors (biClrUsed) field in the header.
|
||||
* For 24-bit and 32-bit BMP, where each pixel is described by distinct R, G, and B (and potentially alpha) values, a palette isn't used or needed.
|
||||
*/
|
||||
palette?: BmpColor[];
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
export var BmpCompression;
|
||||
(function (BmpCompression) {
|
||||
BmpCompression[BmpCompression["NONE"] = 0] = "NONE";
|
||||
BmpCompression[BmpCompression["BI_RLE8"] = 1] = "BI_RLE8";
|
||||
BmpCompression[BmpCompression["BI_RLE4"] = 2] = "BI_RLE4";
|
||||
BmpCompression[BmpCompression["BI_BIT_FIELDS"] = 3] = "BI_BIT_FIELDS";
|
||||
BmpCompression[BmpCompression["BI_ALPHA_BIT_FIELDS"] = 6] = "BI_ALPHA_BIT_FIELDS";
|
||||
})(BmpCompression || (BmpCompression = {}));
|
||||
//# sourceMappingURL=types.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,mDAAQ,CAAA;IACR,yDAAW,CAAA;IACX,yDAAW,CAAA;IACX,qEAAiB,CAAA;IACjB,iFAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB"}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "bmp-ts",
|
||||
"version": "1.0.9",
|
||||
"description": "A pure typescript BMP encoder and decoder",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hipstersmoothie/bmp-ts"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"types"
|
||||
],
|
||||
"author": {
|
||||
"name": "Andrew lisowski",
|
||||
"email": "lisowski54@gmail.com"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tshy",
|
||||
"test": "vitest",
|
||||
"release": "auto shipit"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^10.11.7",
|
||||
"auto": "^11.1.2",
|
||||
"prettier": "^3.2.5",
|
||||
"tshy": "^1.12.0",
|
||||
"typescript": "^5.4.3",
|
||||
"vitest": "^1.4.0"
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"keywords": [
|
||||
"bmp",
|
||||
"1bit",
|
||||
"4bit",
|
||||
"8bit",
|
||||
"16bit",
|
||||
"24bit",
|
||||
"32bit",
|
||||
"encoder",
|
||||
"decoder",
|
||||
"image",
|
||||
"javascript",
|
||||
"js"
|
||||
],
|
||||
"tshy": {
|
||||
"exclude": [
|
||||
"**/__test__/**"
|
||||
],
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": "./src/index.ts"
|
||||
}
|
||||
},
|
||||
"exports": {
|
||||
"./package.json": "./package.json",
|
||||
".": {
|
||||
"import": {
|
||||
"types": "./dist/esm/index.d.ts",
|
||||
"default": "./dist/esm/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"default": "./dist/commonjs/index.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
"main": "./dist/commonjs/index.js",
|
||||
"types": "./dist/commonjs/index.d.ts",
|
||||
"type": "module"
|
||||
}
|
||||
Reference in new issue
Block a user