Browse Source

optimize jpg embed extraction

pull/54/head
coomdev 2 years ago
parent
commit
ec5e075927
  1. 2
      README.md
  2. 444
      chrome/dist/main.js
  3. 2
      chrome/manifest.json
  4. 444
      dist/main.js
  5. 444
      firefox/dist/main.js
  6. 2
      firefox/manifest.json
  7. 2
      firefox_update.json
  8. 2
      main.meta.js
  9. 446
      main.user.js
  10. BIN
      pngextraembedder-0.288.xpi
  11. BIN
      pngextraembedder-0.289.xpi
  12. BIN
      pngextraembedder-0.290.xpi
  13. BIN
      pngextraembedder-0.291.xpi
  14. BIN
      pngextraembedder-0.292.xpi
  15. BIN
      pngextraembedder-0.294.xpi
  16. BIN
      pngextraembedder-0.295.xpi
  17. BIN
      pngextraembedder-0.299.xpi
  18. BIN
      pngextraembedder-0.302.xpi
  19. BIN
      pngextraembedder-0.305.xpi
  20. BIN
      pngextraembedder-0.306.xpi
  21. 471
      src/f5stego.ts
  22. 7
      src/main.ts

2
README.md

@ -25,7 +25,7 @@ Please report any issue you have with those (only for mainstream browsers)
Also, use this if you plan to use b4k's archive.
- [Install 4chanX (recommended)](https://www.4chan-x.net/builds/4chan-X.user.js)
- Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.305.xpi) or Chrome-based (Down for "maintainance"))
- Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.306.xpi) or Chrome-based (Down for "maintainance"))
For FF users, the extension is signed so you can just drag and drop it on your about:addons tab.

444
chrome/dist/main.js

File diff suppressed because one or more lines are too long

2
chrome/manifest.json

@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!",
"version": "0.305",
"version": "0.306",
"icons": {
"64": "1449696017588.png"
},

444
dist/main.js

File diff suppressed because one or more lines are too long

444
firefox/dist/main.js

File diff suppressed because one or more lines are too long

2
firefox/manifest.json

@ -7,7 +7,7 @@
},
"name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!",
"version": "0.305",
"version": "0.306",
"icons": {
"64": "1449696017588.png"
},

2
firefox_update.json

@ -1 +1 @@
{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.305","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.305.xpi"}]}}}
{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.306","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.306.xpi"}]}}}

2
main.meta.js

@ -1,7 +1,7 @@
// ==UserScript==
// @name PNGExtraEmbed
// @namespace https://coom.tech/
// @version 0.305
// @version 0.306
// @description uhh
// @author You
// @match https://boards.4channel.org/*

446
main.user.js

File diff suppressed because one or more lines are too long

BIN
pngextraembedder-0.288.xpi

Binary file not shown.

BIN
pngextraembedder-0.289.xpi

Binary file not shown.

BIN
pngextraembedder-0.290.xpi

Binary file not shown.

BIN
pngextraembedder-0.291.xpi

Binary file not shown.

BIN
pngextraembedder-0.292.xpi

Binary file not shown.

BIN
pngextraembedder-0.294.xpi

Binary file not shown.

BIN
pngextraembedder-0.295.xpi

Binary file not shown.

BIN
pngextraembedder-0.299.xpi

Binary file not shown.

BIN
pngextraembedder-0.302.xpi

Binary file not shown.

BIN
pngextraembedder-0.305.xpi

Binary file not shown.

BIN
pngextraembedder-0.300.xpi → pngextraembedder-0.306.xpi

Binary file not shown.

471
src/f5stego.ts

@ -1,3 +1,4 @@
/* eslint-disable no-constant-condition */
/* This software is licensed under the MIT License.
Copyright (c) 2016 desudesutalk
@ -46,7 +47,6 @@
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.
jpeg encoder license:
JPEG encoder ported to JavaScript, optimized by Andreas Ritter
@ -104,14 +104,67 @@
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import { BitstreamWriter, revbyte } from "./bitstream";
/* global define, module, exports */
/* jshint sub:true */
// Standard Huffman tables for coder initialization
// ===========================================================================================================
var bitcode = new Array(65535),
function* f5get(): Generator<void, Buffer, number> {
let extrBit = 0;
//var pm = this.#stegShuffle(coeff),
// gamma = pm.gamma,
// gammaI = 0;
let k = 0;
for (let i = 0; i < 4; ++i) {
const b = (yield);
k |= b << i;
}
k = (k & 15) + 1;
let toread = 8; // length is on 16 bits, unless bit 0 on the second byte is 1, in which case it's 23 bits
let len = 0;
while (toread--) {
len = len * 2 + (yield);
}
const b = yield;
toread += 8;
if (b)
toread += 7;
else
len *= 2;
while (toread--) {
len = len * 2 + (yield);
}
let rlen = revbyte(len, b ? 23 : 16);
len = rlen;
if (len >= 256) // don't know if length decoding is correct so let's be safe and trim
len = rlen = 256;
len *= 8; // bytes to bits
// k must be 1
const chunks: Uint8Array[] = [];
const bw = new BitstreamWriter({
write(chunk) {
chunks.push(chunk);
},
});
while (len) {
extrBit = yield;
bw.write(1, extrBit);
len--;
}
bw.end();
return Buffer.concat(chunks).slice(0, rlen);
}
const bitcode = new Array(65535),
category = new Array(65535),
std_dc_luminance_nrcodes = [0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0],
std_dc_luminance_values = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
@ -167,18 +220,18 @@ var bitcode = new Array(65535),
];
function _initCategoryNumber() {
var nrlower = 1;
var nrupper = 2;
for (var cat = 1; cat <= 15; cat++) {
let nrlower = 1;
let nrupper = 2;
for (let cat = 1; cat <= 15; cat++) {
//Positive numbers
for (var nr = nrlower; nr < nrupper; nr++) {
for (let nr = nrlower; nr < nrupper; nr++) {
category[32767 + nr] = cat;
bitcode[32767 + nr] = [];
bitcode[32767 + nr][1] = cat;
bitcode[32767 + nr][0] = nr;
}
//Negative numbers
for (var nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
for (let nrneg = -(nrupper - 1); nrneg <= -nrlower; nrneg++) {
category[32767 + nrneg] = cat;
bitcode[32767 + nrneg] = [];
bitcode[32767 + nrneg][1] = cat;
@ -192,11 +245,11 @@ function _initCategoryNumber() {
_initCategoryNumber();
function _computeHuffmanTbl(nrcodes: number[], std_table: number[]) {
var codevalue = 0;
var pos_in_table = 0;
var HT: number[][] = [];
for (var k = 1; k <= 16; k++) {
for (var j = 1; j <= nrcodes[k]; j++) {
let codevalue = 0;
let pos_in_table = 0;
const HT: number[][] = [];
for (let k = 1; k <= 16; k++) {
for (let j = 1; j <= nrcodes[k]; j++) {
HT[std_table[pos_in_table]] = [];
HT[std_table[pos_in_table]][0] = codevalue;
HT[std_table[pos_in_table]][1] = k;
@ -213,7 +266,6 @@ const YDC_HT = _computeHuffmanTbl(std_dc_luminance_nrcodes, std_dc_luminance_val
YAC_HT = _computeHuffmanTbl(std_ac_luminance_nrcodes, std_ac_luminance_values),
UVAC_HT = _computeHuffmanTbl(std_ac_chrominance_nrcodes, std_ac_chrominance_values);
type FrameComponentType = {
componentId: number,
h: number,
@ -257,88 +309,56 @@ export class f5stego {
constructor(key: ArrayLike<number>, private maxPixels: number = 4096 * 4096) {
}
embed(image: Uint8Array, data: ArrayLike<number>, k?: number) {
embed(image: Uint8Array, data: ArrayLike<number>, k: number) {
this.parse(image);
this.f5put(data, k);
return this.pack();
};
}
extract(image: Uint8Array) {
this.parse(image, true);
return this.f5get();
};
try {
this.gengen = f5get();
this.gengen.next(); // run shit
this.parse(image, true);
return this.f5get();
} catch (e) {
if (e instanceof Buffer)
return e;
throw e;
}
}
#_raw?: Uint8Array;
#jfif?: any;
#APPn?: any;
#qts?: any[];
#frame: FrameType | null = null;
#tail: Uint8Array | null = null;
#_analyze(coeff: Int16Array) {
var _one = 0,
_zero = 0,
_large, _ratio, usable, i, k, embedded, matched, changed;
for (i = 0; i < coeff.length; i++) {
if (i % 64 === 0) continue;
if (coeff[i] === 0) _zero++;
if (coeff[i] == 1 || coeff[i] == -1) _one++;
}
_large = coeff.length - _zero - _one - coeff.length / 64;
_ratio = _one / (_large + _one);
var res = {
'capacity': [0, ((_large + (0.49 * _one)) >> 3) - 1],
'coeff_total': coeff.length,
'coeff_large': _large,
'coeff_zero': _zero,
'coeff_one': _one,
'coeff_one_ratio': _one / (_large + _one)
};
for (i = 2; i < 17; i++) {
k = (1 << i) - 1;
usable = _large + _one;
embedded = 0;
while (usable > k) {
matched = (usable / k / (1 << i) / (1 << i)) | 0;
usable -= matched * k;
changed = (usable * (1 - _ratio) / k * 0.96) | 0;
usable -= changed * k;
embedded += changed + matched;
k++;
}
res.capacity[i] = ((i * embedded) >> 3) - 1;
}
return res;
}
#_f5write(coeff: Int16Array, data: ArrayLike<number>, k: number) {
var coeff_count = coeff.length;
const coeff_count = coeff.length;
var _changed = 0,
let _changed = 0,
_embedded = 0,
_examined = 0,
_thrown = 0,
shuffled_index = 0,
i, n, ii;
i, ii: number;
//let { gamma, pm } = this.#stegShuffle(coeff_count);
//let gammaI = 0;
var next_bit_to_embed = 0,
let next_bit_to_embed = 0,
byte_to_embed = data.length,
data_idx = 0,
available_bits_to_embed = 0;
n = (1 << k) - 1;
const n = (1 << k) - 1;
byte_to_embed = k - 1;
byte_to_embed ^= 0; // nop
@ -353,7 +373,7 @@ export class f5stego {
if (shuffled_index % 64 === 0 || coeff[shuffled_index] === 0) continue;
var cc = coeff[shuffled_index];
const cc = coeff[shuffled_index];
_examined++;
if (cc > 0 && (cc & 1) != next_bit_to_embed) {
@ -385,7 +405,7 @@ export class f5stego {
if (k != 1) {
//ii--;
var is_last_byte = false,
let is_last_byte = false,
k_bits_to_embed = 0;
while (!is_last_byte || (available_bits_to_embed !== 0 && is_last_byte)) {
@ -409,8 +429,8 @@ export class f5stego {
}
var code_word = [];
var ci = null;
const code_word: number[] = [];
let ci: number | null = null;
for (i = 0; i < n; i++) {
while (true) {
@ -427,8 +447,8 @@ export class f5stego {
_examined += n;
while (true) {
var vhash = 0,
extracted_bit;
let vhash = 0;
let extracted_bit;
for (i = 0; i < code_word.length; i++) {
if (coeff[code_word[i]] > 0) {
@ -484,32 +504,10 @@ export class f5stego {
};
}
analyze() {
if (!this.#frame)
throw "Parser not run";
var i, comp = this.#frame.components[0];
if (comp.componentId != 1) {
for (i = 0; i < this.#frame.components.length; i++) {
if (this.#frame.components[i].componentId == 1) {
comp = this.#frame.components[i];
break;
}
}
}
if (!('blocks' in comp)) {
throw "Blocks failed to be parsed";
}
return this.#_analyze(comp.blocks);
};
f5put(data: ArrayLike<number>, k?: number) {
f5put(data: ArrayLike<number>, k: number) {
if (!this.#frame)
throw "Parser not run";
var t, i, comp = this.#frame.components[0];
let t, i, comp = this.#frame.components[0];
// Looks funny, but who knows?
// From the other hand you need ~80MB jpeg to hide 8MB of data and this will be bigger than 4096x4096 pixels
@ -537,69 +535,20 @@ export class f5stego {
}
}
if (k) {
if (!('blocks' in comp)) {
throw "Blocks failed to be parsed";
}
return this.#_f5write(comp.blocks, t, k);
}
if (!('blocks' in comp)) {
throw "Blocks failed to be parsed";
}
let ret: {
k: number;
embedded: number;
examined: number;
changed: number;
thrown: number;
efficiency: string;
stats?: {
capacity: number[];
coeff_total: number;
coeff_large: number;
coeff_zero: number;
coeff_one: number;
coeff_one_ratio: number;
}
};
let prop = this.#_analyze(comp.blocks);
k = 0;
for (i = prop.capacity.length - 1; i >= 0; i--) {
if (prop.capacity[i] >= t.length) {
k = i;
break;
}
}
if (k === 0) throw 'capacity exceeded';
try {
ret = this.#_f5write(comp.blocks, t, k);
} catch (e) {
k--;
if (k === 0) throw 'capacity exceeded';
ret = this.#_f5write(comp.blocks, t, k);
}
ret['stats'] = prop;
return ret;
return this.#_f5write(comp.blocks, t, k);
}
f5get() {
if (!this.#frame)
throw "Parser not run";
var comp = this.#frame.components[0];
let comp = this.#frame.components[0];
if (comp.componentId != 1) {
for (var i = 0; i < this.#frame.components.length; i++) {
for (let i = 0; i < this.#frame.components.length; i++) {
if (this.#frame.components[i].componentId == 1) {
comp = this.#frame.components[i];
break;
@ -611,47 +560,45 @@ export class f5stego {
throw "Blocks failed to be parsed";
}
var coeff = new Int16Array(comp.blocks.length);
const coeff = new Int16Array(comp.blocks.length);
coeff.set(comp.blocks);
var pos = -1,
extrBit = 0,
cCount = coeff.length - 1;
let pos = -1,
extrBit = 0;
const cCount = coeff.length - 1;
//var pm = this.#stegShuffle(coeff),
// gamma = pm.gamma,
// gammaI = 0;
var n, k = 0;
let k = 0;
var out = new Uint8Array((coeff.length / 8) | 0),
extrByte = 0,
outPos = 0,
bitsAvail = 0,
code = 0,
hash = 0;
const out = new Uint8Array((coeff.length / 8) | 0);
let extrByte = 0;
let outPos = 0;
let bitsAvail = 0;
let code = 0;
let hash = 0;
while (bitsAvail < 4) {
pos++;
//console.log(pos)
if (coeff[pos] === 0) {
continue;
}
extrBit = coeff[pos] & 1;
if (coeff[pos] < 0) {
extrBit = 1 - extrBit;
}
k |= extrBit << bitsAvail;
bitsAvail++;
}
//k = (k ^ gamma[gammaI++] & 15) + 1;
k = (k & 15) + 1;
n = (1 << k) - 1;
const n = (1 << k) - 1;
bitsAvail = 0;
@ -718,7 +665,7 @@ export class f5stego {
extrByte = extrByte >> 8;
}
var s = 2,
let s = 2,
l = out[0];
if (out[1] & 128) {
@ -727,21 +674,21 @@ export class f5stego {
} else {
l += out[1] << 8;
}
return out.subarray(s, s + l);
}
gengen!: Generator<void, Buffer, number>;
parse(data: Uint8Array, tolerant = false) {
var offset = 0;
let offset = 0;
function _buildHuffmanTable(nrcodes: Uint8Array, values: Uint8Array) {
var codevalue = 0,
pos_in_table = 0,
HT = new Uint16Array(65536);
for (var k = 0; k < 16; k++) {
for (var j = 0; j < nrcodes[k]; j++) {
for (var i = codevalue << (15 - k), cntTo = ((codevalue + 1) << (15 - k)); i < cntTo; i++) {
let codevalue = 0;
let pos_in_table = 0;
const HT = new Uint16Array(65536);
for (let k = 0; k < 16; k++) {
for (let j = 0; j < nrcodes[k]; j++) {
for (let i = codevalue << (15 - k), cntTo = ((codevalue + 1) << (15 - k)); i < cntTo; i++) {
HT[i] = values[pos_in_table] + ((k + 1) << 8);
}
pos_in_table++;
@ -752,7 +699,7 @@ export class f5stego {
return HT;
}
function decodeScan(data: ArrayLike<number>,
const decodeScan = (data: ArrayLike<number>,
offset: number,
frame: FrameType,
components: DiscriminateUnion<FrameComponentType, 'huffmanTableDC', Uint16Array>[],
@ -760,28 +707,28 @@ export class f5stego {
spectralStart: number,
spectralEnd: number,
successivePrev: number,
successive: number) {
successive: number) => {
var startOffset = offset,
bitsData = 0,
const startOffset = offset;
let bitsData = 0,
bitsCount = 0,
eobrun = 0,
p1 = 1 << successive, /* 1 in the bit position being coded */
m1 = -1 << successive; /* -1 in the bit position being coded */
eobrun = 0;
const p1 = 1 << successive; /* 1 in the bit position being coded */
const m1 = -1 << successive; /* -1 in the bit position being coded */
function decodeBaseline(component: typeof components[0], pos: number) {
const decodeBaseline = (component: typeof components[0], pos: number) => {
while (bitsCount < 16) {
bitsData = (bitsData << 8) + (data[offset] | 0);
bitsCount += 8;
if (data[offset] == 0xFF) offset++;
offset++;
}
var t = component.huffmanTableDC[(bitsData >>> (bitsCount - 16)) & 0xFFFF];
let t = component.huffmanTableDC[(bitsData >>> (bitsCount - 16)) & 0xFFFF];
if (!t) throw "invalid huffman sequence";
bitsCount -= t >>> 8;
t &= 255;
var diff = 0;
let diff = 0;
if (t !== 0) {
while (bitsCount < t) {
bitsData = (bitsData << 8) + data[offset++];
@ -794,7 +741,7 @@ export class f5stego {
}
component.blocksDC[pos >> 6] = (component.pred += diff);
var k = 1,
let k = 1,
s, r;
while (k < 64) {
@ -823,22 +770,33 @@ export class f5stego {
if ((bitsData & 0xff) == 0xFF) offset++;
bitsCount += 8;
}
component.blocks[pos + k] = (bitsData >>> (bitsCount - s)) & ((1 << s) - 1);
if (component.componentId == 1) {
// EMIT BITS HERE
component.blocks[pos + k] = (bitsData >>> (bitsCount - s)) & ((1 << s) - 1);
if (component.blocks[pos + k] < 1 << (s - 1)) component.blocks[pos + k] += (-1 << s) + 1;
if (component.blocks[pos + k] != 0) {
const v = (component.blocks[pos + k] < 0) ? 1 - (component.blocks[pos + k] & 1) : (component.blocks[pos + k] & 1);
const it = this.gengen.next(v);
if (it.done) {
throw it.value;
}
}
}
bitsCount -= s;
if (component.blocks[pos + k] < 1 << (s - 1)) component.blocks[pos + k] += (-1 << s) + 1;
k++;
}
}
};
function decodeDCFirst(component: typeof components[0], pos: number) {
var diff = 0;
let diff = 0;
while (bitsCount < 16) {
bitsData = (bitsData << 8) + (data[offset] | 0);
bitsCount += 8;
if (data[offset] == 0xFF) offset++;
offset++;
}
var t = component.huffmanTableDC[(bitsData >>> (bitsCount - 16)) & 0xFFFF];
let t = component.huffmanTableDC[(bitsData >>> (bitsCount - 16)) & 0xFFFF];
if (!t) throw "invalid huffman sequence";
bitsCount -= t >>> 8;
t &= 255;
@ -874,8 +832,7 @@ export class f5stego {
return;
}
var k = spectralStart,
let k = spectralStart,
s, r;
while (k <= spectralEnd) {
@ -923,9 +880,8 @@ export class f5stego {
}
}
function decodeACSuccessive(component: typeof components[0], pos: number) {
var k = spectralStart,
let k = spectralStart,
r, s;
if (frame == null)
throw "Frame not defined";
@ -1003,7 +959,7 @@ export class f5stego {
}
}
var decodeFn;
let decodeFn;
if (frame.progressive) {
if (spectralStart === 0)
@ -1014,7 +970,7 @@ export class f5stego {
decodeFn = decodeBaseline;
}
var marker, mcuExpected, i, j, k, n, mcusPerLine, mcusPerRow, x, y;
let marker, mcuExpected, i, j, k, n, mcusPerLine, mcusPerRow, x, y;
if (components.length == 1) {
mcusPerLine = components[0].blocksPerLine;
@ -1101,17 +1057,17 @@ export class f5stego {
offset -= (bitsCount / 8) | 0;
if (data[offset - 1] == 0xFF) offset--;
return offset - startOffset;
}
};
function readUint16() {
var value = (data[offset] << 8) | data[offset + 1];
const value = (data[offset] << 8) | data[offset + 1];
offset += 2;
return value;
}
function readDataBlock() {
var length = readUint16();
var array = data.subarray(offset, offset + length - 2);
const length = readUint16();
const array = data.subarray(offset, offset + length - 2);
offset += array.length;
return array;
}
@ -1123,9 +1079,9 @@ export class f5stego {
this.#frame = null;
this.#tail = null;
var markerHi, markerLo, i, j, resetInterval, component;
let huffmanTablesAC: Uint16Array[] = [];
let huffmanTablesDC: Uint16Array[] = [];
let markerHi, markerLo, i, j, resetInterval, component;
const huffmanTablesAC: Uint16Array[] = [];
const huffmanTablesDC: Uint16Array[] = [];
while (1) {
if (offset >= data.length) {
@ -1173,18 +1129,18 @@ export class f5stego {
if (this.#frame.scanLines * this.#frame.samplesPerLine > this.maxPixels) throw "Image is too big.";
var componentsCount = data[offset++],
componentId;
var maxH = 0,
const componentsCount = data[offset++];
let componentId;
let maxH = 0,
maxV = 0;
for (i = 0; i < componentsCount; i++) {
componentId = data[offset];
var h = data[offset + 1] >> 4;
var v = data[offset + 1] & 15;
const h = data[offset + 1] >> 4;
const v = data[offset + 1] & 15;
if (maxH < h) maxH = h;
if (maxV < v) maxV = v;
var qId = data[offset + 2];
var l = this.#frame.components.push({
const qId = data[offset + 2];
const l = this.#frame.components.push({
componentId: componentId,
h,
v,
@ -1196,14 +1152,14 @@ export class f5stego {
this.#frame.maxH = maxH;
this.#frame.maxV = maxV;
var mcusPerLine = Math.ceil(this.#frame.samplesPerLine / 8 / maxH);
var mcusPerColumn = Math.ceil(this.#frame.scanLines / 8 / maxV);
const mcusPerLine = Math.ceil(this.#frame.samplesPerLine / 8 / maxH);
const mcusPerColumn = Math.ceil(this.#frame.scanLines / 8 / maxV);
for (i = 0; i < this.#frame.components.length; i++) {
component = this.#frame.components[i];
var blocksPerLine = Math.ceil(Math.ceil(this.#frame.samplesPerLine / 8) * component.h / maxH);
var blocksPerColumn = Math.ceil(Math.ceil(this.#frame.scanLines / 8) * component.v / maxV);
var blocksPerLineForMcu = mcusPerLine * component.h;
var blocksPerColumnForMcu = mcusPerColumn * component.v;
const blocksPerLine = Math.ceil(Math.ceil(this.#frame.samplesPerLine / 8) * component.h / maxH);
const blocksPerColumn = Math.ceil(Math.ceil(this.#frame.scanLines / 8) * component.v / maxV);
const blocksPerLineForMcu = mcusPerLine * component.h;
const blocksPerColumnForMcu = mcusPerColumn * component.v;
this.#frame.components[i] = {
...component,
@ -1220,14 +1176,14 @@ export class f5stego {
}
if (markerLo == 0xC4) { // DHT (Define Huffman Tables)
var huffmanLength = readUint16();
const huffmanLength = readUint16();
for (i = 2; i < huffmanLength;) {
var huffmanTableSpec = data[offset++];
var codeLengths = new Uint8Array(16);
var codeLengthSum = 0;
const huffmanTableSpec = data[offset++];
const codeLengths = new Uint8Array(16);
let codeLengthSum = 0;
for (j = 0; j < 16; j++, offset++)
codeLengthSum += (codeLengths[j] = data[offset]);
var huffmanValues = new Uint8Array(codeLengthSum);
const huffmanValues = new Uint8Array(codeLengthSum);
for (j = 0; j < codeLengthSum; j++, offset++)
huffmanValues[j] = data[offset];
i += 17 + codeLengthSum;
@ -1247,22 +1203,22 @@ export class f5stego {
if (this.#frame == null)
throw "SOS before SOF";
readUint16();
var selectorsCount = data[offset++];
var components = [];
const selectorsCount = data[offset++];
const components: FrameComponentType[] = [];
for (i = 0; i < selectorsCount; i++) {
var componentIndex = this.#frame.componentIds[data[offset++]];
const componentIndex = this.#frame.componentIds[data[offset++]];
component = this.#frame.components[componentIndex];
var tableSpec = data[offset++];
const tableSpec = data[offset++];
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
components.push(component);
}
var spectralStart = data[offset++];
var spectralEnd = data[offset++];
var successiveApproximation = data[offset++];
var processed = decodeScan(data, offset,
const spectralStart = data[offset++];
const spectralEnd = data[offset++];
const successiveApproximation = data[offset++];
const processed = decodeScan(data, offset,
this.#frame, components as any, resetInterval,
spectralStart, spectralEnd,
successiveApproximation >> 4, successiveApproximation & 15);
@ -1295,7 +1251,7 @@ export class f5stego {
if (offset < data.length) this.#tail = data.subarray(offset);
return this;
};
}
pack() {
let byteout: Uint8Array;
@ -1307,7 +1263,7 @@ export class f5stego {
// IO functions
function writeByte(value: number) {
var t;
let t;
byteout[outpos++] = value;
if (outpos > poslast) {
@ -1324,7 +1280,7 @@ export class f5stego {
}
function writeBlock(block: Uint8Array) {
var t;
let t;
if (outpos + block.length > poslast) {
t = new Uint8Array(byteout.length * 2 + block.length);
t.set(byteout);
@ -1359,7 +1315,7 @@ export class f5stego {
}
function writeDQT(self: f5stego) {
for (var i = 0; i < self.#qts!.length; i++) {
for (let i = 0; i < self.#qts!.length; i++) {
writeWord(0xFFDB); // marker
writeWord(self.#qts![i].length + 2); // length
writeBlock(self.#qts![i]);
@ -1367,7 +1323,7 @@ export class f5stego {
}
function writeAPPn(self: f5stego) {
for (var i = 0; i < self.#APPn.length; i++) {
for (let i = 0; i < self.#APPn.length; i++) {
writeWord(0xFF00 | self.#APPn[i].app);
writeWord(self.#APPn[i].data.length + 2);
writeBlock(self.#APPn[i].data);
@ -1384,8 +1340,8 @@ export class f5stego {
writeWord(self.#frame.samplesPerLine);
writeByte(self.#frame.components.length); // nrofcomponents
for (var i = 0; i < self.#frame.components.length; i++) {
var c = self.#frame.components[i];
for (let i = 0; i < self.#frame.components.length; i++) {
const c = self.#frame.components[i];
writeByte(c.componentId);
writeByte(c.h << 4 | c.v);
writeByte(c.quantizationTable);
@ -1399,20 +1355,20 @@ export class f5stego {
writeWord(0xFFC4); // marker
writeWord(31); // length
writeByte(0); // HTYDCinfo
for (var i = 0; i < 16; i++) {
for (let i = 0; i < 16; i++) {
writeByte(std_dc_luminance_nrcodes[i + 1]);
}
for (var j = 0; j <= 11; j++) {
for (let j = 0; j <= 11; j++) {
writeByte(std_dc_luminance_values[j]);
}
writeWord(0xFFC4); // marker
writeWord(181); // length
writeByte(0x10); // HTYACinfo
for (var k = 0; k < 16; k++) {
for (let k = 0; k < 16; k++) {
writeByte(std_ac_luminance_nrcodes[k + 1]);
}
for (var l = 0; l <= 161; l++) {
for (let l = 0; l <= 161; l++) {
writeByte(std_ac_luminance_values[l]);
}
@ -1420,20 +1376,20 @@ export class f5stego {
writeWord(0xFFC4); // marker
writeWord(31); // length
writeByte(1); // HTUDCinfo
for (var m = 0; m < 16; m++) {
for (let m = 0; m < 16; m++) {
writeByte(std_dc_chrominance_nrcodes[m + 1]);
}
for (var n = 0; n <= 11; n++) {
for (let n = 0; n <= 11; n++) {
writeByte(std_dc_chrominance_values[n]);
}
writeWord(0xFFC4); // marker
writeWord(181); // length
writeByte(0x11); // HTUACinfo
for (var o = 0; o < 16; o++) {
for (let o = 0; o < 16; o++) {
writeByte(std_ac_chrominance_nrcodes[o + 1]);
}
for (var p = 0; p <= 161; p++) {
for (let p = 0; p <= 161; p++) {
writeByte(std_ac_chrominance_values[p]);
}
}
@ -1447,8 +1403,8 @@ export class f5stego {
writeWord(6 + self.#frame.components.length * 2); // length
writeByte(self.#frame.components.length); // nrofcomponents
for (var i = 0; i < self.#frame.components.length; i++) {
var c = self.#frame.components[i];
for (let i = 0; i < self.#frame.components.length; i++) {
const c = self.#frame.components[i];
writeByte(c.componentId);
if (i === 0) {
writeByte(0);
@ -1463,14 +1419,14 @@ export class f5stego {
}
function processDU(comp: FrameComponentType, POS: number, DC: number, HTDC: number[][], HTAC: number[][]) {
var pos, posval, t;
let pos, posval, t;
if (bytepos === 0) bytenew = 0;
if (!('blocks' in comp))
throw "Blocks not parsed";
var Diff = comp.blocksDC[POS >> 6] - DC;
const Diff = comp.blocksDC[POS >> 6] - DC;
DC = comp.blocksDC[POS >> 6];
//Encode DC
if (Diff === 0) {
@ -1514,7 +1470,7 @@ export class f5stego {
}
}
//Encode ACs
var end0pos = 63; // was const... which is crazy
let end0pos = 63; // was const... which is crazy
for (;
(end0pos > 0) && (comp.blocks[POS + end0pos] === 0); end0pos--) { }
//end0pos = first element in reverse order !=0
@ -1535,16 +1491,16 @@ export class f5stego {
}
return DC;
}
var i = 1;
var lng;
let i = 1;
let lng;
while (i <= end0pos) {
var startpos = i;
const startpos = i;
for (;
(comp.blocks[POS + i] === 0) && (i <= end0pos); ++i) { }
var nrzeroes = i - startpos;
let nrzeroes = i - startpos;
if (nrzeroes >= 16) {
lng = nrzeroes >> 4;
for (var nrmarker = 1; nrmarker <= lng; ++nrmarker) {
for (let nrmarker = 1; nrmarker <= lng; ++nrmarker) {
posval = HTAC[0xF0][1];
bytenew <<= posval;
bytenew += HTAC[0xF0][0];
@ -1644,9 +1600,9 @@ export class f5stego {
if (!this.#frame)
throw "Frame not ready";
var c, mcuRow, mcuCol, blockRow, blockCol, mcu, i, v, h;
let c, mcuRow, mcuCol, blockRow, blockCol, mcu, i, v, h;
var DCdiff = [];
const DCdiff: number[] = [];
for (i = 0; i < this.#frame.components.length; i++) {
DCdiff.push(0);
}
@ -1690,6 +1646,5 @@ export class f5stego {
if (this.#tail) writeBlock(this.#tail);
return byteout.slice(0, outpos);
};
}
}

7
src/main.ts

@ -651,13 +651,6 @@ const earlystartup = async () => {
return false;
}
}
if (['arch.b4k.co', 'desuarchive.org'].includes(location.host) && execution_mode == "chrome_api") {
if (!Platform.getValue("warning_seen3", false)) {
alert("Due to b4k and desuarchive policies being mean, PEE cannot display content properly here. A \"PEE companion\" extension will be released as including that functionnallity in PEE lengthens ChromeWebStore review delays, please understando.");
Platform.setValue("warning_seen3", true);
return false;
}
}
return true;
};

Loading…
Cancel
Save