1 | "use strict";
|
2 |
|
3 | let constants = require("./constants");
|
4 | let CrcStream = require("./crc");
|
5 | let bitPacker = require("./bitpacker");
|
6 | let filter = require("./filter-pack");
|
7 | let zlib = require("zlib");
|
8 |
|
9 | let 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 |
|
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 |
|
64 | Packer.prototype.getDeflateOptions = function () {
|
65 | return {
|
66 | chunkSize: this._options.deflateChunkSize,
|
67 | level: this._options.deflateLevel,
|
68 | strategy: this._options.deflateStrategy,
|
69 | };
|
70 | };
|
71 |
|
72 | Packer.prototype.createDeflate = function () {
|
73 | return this._options.deflateFactory(this.getDeflateOptions());
|
74 | };
|
75 |
|
76 | Packer.prototype.filterData = function (data, width, height) {
|
77 |
|
78 | let packedData = bitPacker(data, width, height, this._options);
|
79 |
|
80 |
|
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 |
|
86 | Packer.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 |
|
104 | Packer.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 |
|
110 | Packer.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;
|
115 | buf[9] = this._options.colorType;
|
116 | buf[10] = 0;
|
117 | buf[11] = 0;
|
118 | buf[12] = 0;
|
119 |
|
120 | return this._packChunk(constants.TYPE_IHDR, buf);
|
121 | };
|
122 |
|
123 | Packer.prototype.packIDAT = function (data) {
|
124 | return this._packChunk(constants.TYPE_IDAT, data);
|
125 | };
|
126 |
|
127 | Packer.prototype.packIEND = function () {
|
128 | return this._packChunk(constants.TYPE_IEND, null);
|
129 | };
|