1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | "use strict";
|
23 |
|
24 | Object.defineProperty(exports, "__esModule", {
|
25 | value: true
|
26 | });
|
27 | exports.PredictorStream = void 0;
|
28 |
|
29 | var _decode_stream = require("./decode_stream.js");
|
30 |
|
31 | var _primitives = require("./primitives.js");
|
32 |
|
33 | var _util = require("../shared/util.js");
|
34 |
|
35 | class PredictorStream extends _decode_stream.DecodeStream {
|
36 | constructor(str, maybeLength, params) {
|
37 | super(maybeLength);
|
38 |
|
39 | if (!(params instanceof _primitives.Dict)) {
|
40 | return str;
|
41 | }
|
42 |
|
43 | const predictor = this.predictor = params.get("Predictor") || 1;
|
44 |
|
45 | if (predictor <= 1) {
|
46 | return str;
|
47 | }
|
48 |
|
49 | if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
|
50 | throw new _util.FormatError(`Unsupported predictor: ${predictor}`);
|
51 | }
|
52 |
|
53 | if (predictor === 2) {
|
54 | this.readBlock = this.readBlockTiff;
|
55 | } else {
|
56 | this.readBlock = this.readBlockPng;
|
57 | }
|
58 |
|
59 | this.str = str;
|
60 | this.dict = str.dict;
|
61 | const colors = this.colors = params.get("Colors") || 1;
|
62 | const bits = this.bits = params.get("BPC", "BitsPerComponent") || 8;
|
63 | const columns = this.columns = params.get("Columns") || 1;
|
64 | this.pixBytes = colors * bits + 7 >> 3;
|
65 | this.rowBytes = columns * colors * bits + 7 >> 3;
|
66 | return this;
|
67 | }
|
68 |
|
69 | readBlockTiff() {
|
70 | const rowBytes = this.rowBytes;
|
71 | const bufferLength = this.bufferLength;
|
72 | const buffer = this.ensureBuffer(bufferLength + rowBytes);
|
73 | const bits = this.bits;
|
74 | const colors = this.colors;
|
75 | const rawBytes = this.str.getBytes(rowBytes);
|
76 | this.eof = !rawBytes.length;
|
77 |
|
78 | if (this.eof) {
|
79 | return;
|
80 | }
|
81 |
|
82 | let inbuf = 0,
|
83 | outbuf = 0;
|
84 | let inbits = 0,
|
85 | outbits = 0;
|
86 | let pos = bufferLength;
|
87 | let i;
|
88 |
|
89 | if (bits === 1 && colors === 1) {
|
90 | for (i = 0; i < rowBytes; ++i) {
|
91 | let c = rawBytes[i] ^ inbuf;
|
92 | c ^= c >> 1;
|
93 | c ^= c >> 2;
|
94 | c ^= c >> 4;
|
95 | inbuf = (c & 1) << 7;
|
96 | buffer[pos++] = c;
|
97 | }
|
98 | } else if (bits === 8) {
|
99 | for (i = 0; i < colors; ++i) {
|
100 | buffer[pos++] = rawBytes[i];
|
101 | }
|
102 |
|
103 | for (; i < rowBytes; ++i) {
|
104 | buffer[pos] = buffer[pos - colors] + rawBytes[i];
|
105 | pos++;
|
106 | }
|
107 | } else if (bits === 16) {
|
108 | const bytesPerPixel = colors * 2;
|
109 |
|
110 | for (i = 0; i < bytesPerPixel; ++i) {
|
111 | buffer[pos++] = rawBytes[i];
|
112 | }
|
113 |
|
114 | for (; i < rowBytes; i += 2) {
|
115 | const sum = ((rawBytes[i] & 0xff) << 8) + (rawBytes[i + 1] & 0xff) + ((buffer[pos - bytesPerPixel] & 0xff) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xff);
|
116 | buffer[pos++] = sum >> 8 & 0xff;
|
117 | buffer[pos++] = sum & 0xff;
|
118 | }
|
119 | } else {
|
120 | const compArray = new Uint8Array(colors + 1);
|
121 | const bitMask = (1 << bits) - 1;
|
122 | let j = 0,
|
123 | k = bufferLength;
|
124 | const columns = this.columns;
|
125 |
|
126 | for (i = 0; i < columns; ++i) {
|
127 | for (let kk = 0; kk < colors; ++kk) {
|
128 | if (inbits < bits) {
|
129 | inbuf = inbuf << 8 | rawBytes[j++] & 0xff;
|
130 | inbits += 8;
|
131 | }
|
132 |
|
133 | compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
|
134 | inbits -= bits;
|
135 | outbuf = outbuf << bits | compArray[kk];
|
136 | outbits += bits;
|
137 |
|
138 | if (outbits >= 8) {
|
139 | buffer[k++] = outbuf >> outbits - 8 & 0xff;
|
140 | outbits -= 8;
|
141 | }
|
142 | }
|
143 | }
|
144 |
|
145 | if (outbits > 0) {
|
146 | buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
|
147 | }
|
148 | }
|
149 |
|
150 | this.bufferLength += rowBytes;
|
151 | }
|
152 |
|
153 | readBlockPng() {
|
154 | const rowBytes = this.rowBytes;
|
155 | const pixBytes = this.pixBytes;
|
156 | const predictor = this.str.getByte();
|
157 | const rawBytes = this.str.getBytes(rowBytes);
|
158 | this.eof = !rawBytes.length;
|
159 |
|
160 | if (this.eof) {
|
161 | return;
|
162 | }
|
163 |
|
164 | const bufferLength = this.bufferLength;
|
165 | const buffer = this.ensureBuffer(bufferLength + rowBytes);
|
166 | let prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
|
167 |
|
168 | if (prevRow.length === 0) {
|
169 | prevRow = new Uint8Array(rowBytes);
|
170 | }
|
171 |
|
172 | let i,
|
173 | j = bufferLength,
|
174 | up,
|
175 | c;
|
176 |
|
177 | switch (predictor) {
|
178 | case 0:
|
179 | for (i = 0; i < rowBytes; ++i) {
|
180 | buffer[j++] = rawBytes[i];
|
181 | }
|
182 |
|
183 | break;
|
184 |
|
185 | case 1:
|
186 | for (i = 0; i < pixBytes; ++i) {
|
187 | buffer[j++] = rawBytes[i];
|
188 | }
|
189 |
|
190 | for (; i < rowBytes; ++i) {
|
191 | buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xff;
|
192 | j++;
|
193 | }
|
194 |
|
195 | break;
|
196 |
|
197 | case 2:
|
198 | for (i = 0; i < rowBytes; ++i) {
|
199 | buffer[j++] = prevRow[i] + rawBytes[i] & 0xff;
|
200 | }
|
201 |
|
202 | break;
|
203 |
|
204 | case 3:
|
205 | for (i = 0; i < pixBytes; ++i) {
|
206 | buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
|
207 | }
|
208 |
|
209 | for (; i < rowBytes; ++i) {
|
210 | buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xff;
|
211 | j++;
|
212 | }
|
213 |
|
214 | break;
|
215 |
|
216 | case 4:
|
217 | for (i = 0; i < pixBytes; ++i) {
|
218 | up = prevRow[i];
|
219 | c = rawBytes[i];
|
220 | buffer[j++] = up + c;
|
221 | }
|
222 |
|
223 | for (; i < rowBytes; ++i) {
|
224 | up = prevRow[i];
|
225 | const upLeft = prevRow[i - pixBytes];
|
226 | const left = buffer[j - pixBytes];
|
227 | const p = left + up - upLeft;
|
228 | let pa = p - left;
|
229 |
|
230 | if (pa < 0) {
|
231 | pa = -pa;
|
232 | }
|
233 |
|
234 | let pb = p - up;
|
235 |
|
236 | if (pb < 0) {
|
237 | pb = -pb;
|
238 | }
|
239 |
|
240 | let pc = p - upLeft;
|
241 |
|
242 | if (pc < 0) {
|
243 | pc = -pc;
|
244 | }
|
245 |
|
246 | c = rawBytes[i];
|
247 |
|
248 | if (pa <= pb && pa <= pc) {
|
249 | buffer[j++] = left + c;
|
250 | } else if (pb <= pc) {
|
251 | buffer[j++] = up + c;
|
252 | } else {
|
253 | buffer[j++] = upLeft + c;
|
254 | }
|
255 | }
|
256 |
|
257 | break;
|
258 |
|
259 | default:
|
260 | throw new _util.FormatError(`Unsupported predictor: ${predictor}`);
|
261 | }
|
262 |
|
263 | this.bufferLength += rowBytes;
|
264 | }
|
265 |
|
266 | }
|
267 |
|
268 | exports.PredictorStream = PredictorStream; |
\ | No newline at end of file |