Browse Source

Fix GIF encoding, minor css adjustment for minimap

pull/46/head 0.93
coomdev 2 years ago
parent
commit
dc89f80fb0
  1. 2
      src/ScrollHighlighter.svelte
  2. 79
      src/gif.ts
  3. 62
      src/main.ts

2
src/ScrollHighlighter.svelte

@ -91,6 +91,8 @@ onDestroy(() => {
<style scoped> <style scoped>
.hint { .hint {
background-color: rgb(222 222 222 / 80%); background-color: rgb(222 222 222 / 80%);
z-index: -1;
pointer-events: none;
} }
.scroll-container { .scroll-container {

79
src/gif.ts

@ -1,10 +1,29 @@
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import type { ImageProcessor } from "./main"; import type { EmbeddedFile, ImageProcessor } from "./main";
import { BufferWriteStream } from "./png"; import { BufferWriteStream } from "./png";
const netscape = Buffer.from("!\xFF\x0BNETSCAPE2.0", 'ascii'); const netscape = Buffer.from("!\xFF\x0BNETSCAPE2.0", 'ascii');
const magic = Buffer.from("!\xFF\x0B" + "COOMTECH0.1", 'ascii'); const magic = Buffer.from("!\xFF\x0B" + "COOMTECH0.1", 'ascii');
const read_section = (gif: Buffer, pos: number) => {
const begin = pos;
pos += 3 + gif[pos + 2];
let buf = Buffer.alloc(0);
while (pos < gif.byteLength) {
const v = gif[pos++];
buf = Buffer.concat([buf, gif.slice(pos, pos + v)]);
if (v == 0)
break;
pos += v;
}
const appname = gif.slice(begin + 3, begin + 11).toString('ascii');
return {
appname,
data: buf,
end: pos
};
};
const extractBuff = (gif: Buffer) => { const extractBuff = (gif: Buffer) => {
const field = gif.readUInt8(10); const field = gif.readUInt8(10);
const gcte = !!(field & (1 << 7)); const gcte = !!(field & (1 << 7));
@ -13,41 +32,28 @@ const extractBuff = (gif: Buffer) => {
end += 3 * (1 << ((field & 7) + 1)); end += 3 * (1 << ((field & 7) + 1));
} }
// skip beeg blocks // skip beeg blocks
while (gif.readUInt8(end) == '!'.charCodeAt(0)) { while (gif[end] == '!'.charCodeAt(0)) {
if (magic.compare(gif, end, end + magic.byteLength) != 0) { let sec = read_section(gif, end); // this section contains the size to more easily preallocate a buffer size, but you don't need to care care
end += 3 + gif.readUInt8(end + 2); if (sec.appname == "COOMTECH") {
// eslint-disable-next-line no-constant-condition const ret = Buffer.alloc(sec.data.readInt32LE(0));
while (true) { // skip sub blocks let ptr = 0;
const v = gif.readUInt8(end++); do {
if (!v) sec = read_section(gif, sec.end);
break; sec.data.copy(ret, ptr);
end += v; ptr += sec.data.byteLength;
} end = sec.end;
} else { } while (sec.appname == "COOMTECH" && gif[end] == '!'.charCodeAt(0));
let count = end + magic.byteLength; return { data: ret, filename: 'embedded' } as EmbeddedFile;
let t = 0;
let v = 0;
while ((v = gif.readUInt8(count)) != 0) {
t += v;
count += v + 1;
}
const buff = Buffer.alloc(t);
count = end + magic.byteLength;
t = 0;
while ((v = gif.readUInt8(count)) != 0) {
gif.copy(buff, t, count + 1, count + 1 + v);
t += v;
count += v + 1;
}
return {filename: 'embedded', data: buff};
} }
end = sec.end;
} }
throw "Shouldn't happen";
// metadata ended, nothing... // metadata ended, nothing...
}; };
const extract = extractBuff; const extract = extractBuff;
const write_embedding = async (writer: WritableStreamDefaultWriter<Buffer>, inj: Buffer) => { const write_data = async (writer: WritableStreamDefaultWriter<Buffer>, inj: Buffer) => {
await writer.write(magic); await writer.write(magic);
const byte = Buffer.from([0]); const byte = Buffer.from([0]);
let size = inj.byteLength; let size = inj.byteLength;
@ -65,11 +71,26 @@ const write_embedding = async (writer: WritableStreamDefaultWriter<Buffer>, inj:
await writer.write(byte); await writer.write(byte);
}; };
const write_embedding = async (writer: WritableStreamDefaultWriter<Buffer>, inj: Buffer) => {
const b = Buffer.alloc(4);
b.writeInt32LE(inj.byteLength, 0);
await write_data(writer, b);
let size = inj.byteLength;
let offset = 0;
while (size != 0) {
const ws = size >= (3 << 13) ? (3 << 13) : size;
await write_data(writer, inj.slice(offset, offset + ws));
offset += ws;
size -= ws;
}
};
const inject = async (container: File, inj: File) => { const inject = async (container: File, inj: File) => {
const [writestream, extract] = BufferWriteStream(); const [writestream, extract] = BufferWriteStream();
const writer = writestream.getWriter(); const writer = writestream.getWriter();
const contbuff = Buffer.from(await container.arrayBuffer()); const contbuff = Buffer.from(await container.arrayBuffer());
debugger;
const field = contbuff.readUInt8(10); const field = contbuff.readUInt8(10);
const gcte = !!(field & (1 << 0x7)); const gcte = !!(field & (1 << 0x7));

62
src/main.ts

@ -14,6 +14,8 @@ import ScrollHighlighter from "./ScrollHighlighter.svelte";
import SettingsButton from './SettingsButton.svelte'; import SettingsButton from './SettingsButton.svelte';
import Embedding from './Embedding.svelte'; import Embedding from './Embedding.svelte';
import EyeButton from './EyeButton.svelte'; import EyeButton from './EyeButton.svelte';
import { fileTypeFromBuffer } from "file-type";
import { buf } from "crc-32";
export interface ImageProcessor { export interface ImageProcessor {
skip?: true; skip?: true;
@ -327,30 +329,36 @@ customStyles.appendChild(document.createTextNode(globalCss));
document.documentElement.insertBefore(customStyles, null); document.documentElement.insertBefore(customStyles, null);
// if ((window as any)['pagemode']) { //if ((window as any)['pagemode']) {
// onload = () => { // onload = () => {
// const resbuf = async (s: EmbeddedFile['data']) => Buffer.isBuffer(s) ? s : await s(); // console.log("loaded");
// const container = document.getElementById("container") as HTMLInputElement; // const resbuf = async (s: EmbeddedFile['data']) => Buffer.isBuffer(s) ? s : await s();
// const injection = document.getElementById("injection") as HTMLInputElement; // const container = document.getElementById("container") as HTMLInputElement;
// container.onchange = injection.onchange = async () => { // const injection = document.getElementById("injection") as HTMLInputElement;
// console.log('eval changed'); // container.onchange = injection.onchange = async () => {
// if (container.files?.length && injection.files?.length) { // console.log('eval changed');
// const dlr = document.getElementById("dlr") as HTMLAnchorElement; // if (container.files?.length && injection.files?.length) {
// const dle = document.getElementById("dle") as HTMLAnchorElement; // const dlr = document.getElementById("dlr") as HTMLAnchorElement;
// const res = await gif.inject!(container.files[0], injection.files[0]); // const dle = document.getElementById("dle") as HTMLAnchorElement;
// console.log('inj done'); // console.log(buf(new Uint8Array(await container.files[0].arrayBuffer())));
// const result = document.getElementById("result") as HTMLImageElement; // console.log(buf(new Uint8Array(await injection.files[0].arrayBuffer())));
// const extracted = document.getElementById("extracted") as HTMLImageElement; // const res = await gif.inject!(container.files[0], injection.files[0]);
// const res2 = new Blob([res], {type: (await fileTypeFromBuffer(res))?.mime}); // console.log('inj done', buf(res));
// result.src = URL.createObjectURL(res2); // const result = document.getElementById("result") as HTMLImageElement;
// dlr.href = result.src; // const extracted = document.getElementById("extracted") as HTMLImageElement;
// console.log('url created'); // const res2 = new Blob([res], { type: (await fileTypeFromBuffer(res))?.mime });
// const embedded = await gif.extract(res); // result.src = URL.createObjectURL(res2);
// if (!embedded) // dlr.href = result.src;
// debugger; // console.log('url created');
// extracted.src = URL.createObjectURL(new Blob([await resbuf(embedded?.data!)])); // const embedded = await gif.extract(res);
// dle.href = extracted.src; // console.log(buf(new Uint8Array(await resbuf(embedded.data))));
// } // if (!embedded) {
// }; // debugger;
// }; // return;
// } // }
// extracted.src = URL.createObjectURL(new Blob([await resbuf(embedded.data!)]));
// dle.href = extracted.src;
// }
// };
// };
//}
Loading…
Cancel
Save