UNPKG

3.72 kBJavaScriptView Raw
1"use strict";
2
3let constants = require("./constants");
4let CrcStream = require("./crc");
5let bitPacker = require("./bitpacker");
6let filter = require("./filter-pack");
7let zlib = require("zlib");
8
9let Packer = (module.exports = function (options) {
10 this._options = options;
11
12 options.deflateChunkSize = options.deflateChunkSize || 32 * 1024;
13 options.deflateLevel =
14 options.deflateLevel != null ? options.deflateLevel : 9;
15 options.deflateStrategy =
16 options.deflateStrategy != null ? options.deflateStrategy : 3;
17 options.inputHasAlpha =
18 options.inputHasAlpha != null ? options.inputHasAlpha : true;
19 options.deflateFactory = options.deflateFactory || zlib.createDeflate;
20 options.bitDepth = options.bitDepth || 8;
21 // This is outputColorType
22 options.colorType =
23 typeof options.colorType === "number"
24 ? options.colorType
25 : constants.COLORTYPE_COLOR_ALPHA;
26 options.inputColorType =
27 typeof options.inputColorType === "number"
28 ? options.inputColorType
29 : constants.COLORTYPE_COLOR_ALPHA;
30
31 if (
32 [
33 constants.COLORTYPE_GRAYSCALE,
34 constants.COLORTYPE_COLOR,
35 constants.COLORTYPE_COLOR_ALPHA,
36 constants.COLORTYPE_ALPHA,
37 ].indexOf(options.colorType) === -1
38 ) {
39 throw new Error(
40 "option color type:" + options.colorType + " is not supported at present"
41 );
42 }
43 if (
44 [
45 constants.COLORTYPE_GRAYSCALE,
46 constants.COLORTYPE_COLOR,
47 constants.COLORTYPE_COLOR_ALPHA,
48 constants.COLORTYPE_ALPHA,
49 ].indexOf(options.inputColorType) === -1
50 ) {
51 throw new Error(
52 "option input color type:" +
53 options.inputColorType +
54 " is not supported at present"
55 );
56 }
57 if (options.bitDepth !== 8 && options.bitDepth !== 16) {
58 throw new Error(
59 "option bit depth:" + options.bitDepth + " is not supported at present"
60 );
61 }
62});
63
64Packer.prototype.getDeflateOptions = function () {
65 return {
66 chunkSize: this._options.deflateChunkSize,
67 level: this._options.deflateLevel,
68 strategy: this._options.deflateStrategy,
69 };
70};
71
72Packer.prototype.createDeflate = function () {
73 return this._options.deflateFactory(this.getDeflateOptions());
74};
75
76Packer.prototype.filterData = function (data, width, height) {
77 // convert to correct format for filtering (e.g. right bpp and bit depth)
78 let packedData = bitPacker(data, width, height, this._options);
79
80 // filter pixel data
81 let bpp = constants.COLORTYPE_TO_BPP_MAP[this._options.colorType];
82 let filteredData = filter(packedData, width, height, this._options, bpp);
83 return filteredData;
84};
85
86Packer.prototype._packChunk = function (type, data) {
87 let len = data ? data.length : 0;
88 let buf = Buffer.alloc(len + 12);
89
90 buf.writeUInt32BE(len, 0);
91 buf.writeUInt32BE(type, 4);
92
93 if (data) {
94 data.copy(buf, 8);
95 }
96
97 buf.writeInt32BE(
98 CrcStream.crc32(buf.slice(4, buf.length - 4)),
99 buf.length - 4
100 );
101 return buf;
102};
103
104Packer.prototype.packGAMA = function (gamma) {
105 let buf = Buffer.alloc(4);
106 buf.writeUInt32BE(Math.floor(gamma * constants.GAMMA_DIVISION), 0);
107 return this._packChunk(constants.TYPE_gAMA, buf);
108};
109
110Packer.prototype.packIHDR = function (width, height) {
111 let buf = Buffer.alloc(13);
112 buf.writeUInt32BE(width, 0);
113 buf.writeUInt32BE(height, 4);
114 buf[8] = this._options.bitDepth; // Bit depth
115 buf[9] = this._options.colorType; // colorType
116 buf[10] = 0; // compression
117 buf[11] = 0; // filter
118 buf[12] = 0; // interlace
119
120 return this._packChunk(constants.TYPE_IHDR, buf);
121};
122
123Packer.prototype.packIDAT = function (data) {
124 return this._packChunk(constants.TYPE_IDAT, data);
125};
126
127Packer.prototype.packIEND = function () {
128 return this._packChunk(constants.TYPE_IEND, null);
129};