UNPKG

6.74 kBJavaScriptView Raw
1/**
2 * @licstart The following is the entire license notice for the
3 * JavaScript code in this page
4 *
5 * Copyright 2022 Mozilla Foundation
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * @licend The above is the entire license notice for the
20 * JavaScript code in this page
21 */
22"use strict";
23
24Object.defineProperty(exports, "__esModule", {
25 value: true
26});
27exports.PredictorStream = void 0;
28
29var _decode_stream = require("./decode_stream.js");
30
31var _primitives = require("./primitives.js");
32
33var _util = require("../shared/util.js");
34
35class 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
268exports.PredictorStream = PredictorStream;
\No newline at end of file