[feat] better image saving
This commit is contained in:
@@ -2,6 +2,79 @@ import { Buffer } from 'buffer';
|
||||
import crc32 from 'crc/crc32';
|
||||
import type { LocalWriter } from './storage/globalApi';
|
||||
|
||||
class StreamChunkWriter{
|
||||
constructor(private data:Uint8Array, private writer:LocalWriter){
|
||||
|
||||
}
|
||||
async pushData(data:Uint8Array){
|
||||
await this.writer.write(data)
|
||||
}
|
||||
async init(){
|
||||
let pos = 8
|
||||
let newData:Uint8Array[] = []
|
||||
|
||||
|
||||
const data = this.data
|
||||
await this.pushData(data.slice(0,8))
|
||||
|
||||
while(pos < data.length){
|
||||
const len = data[pos] * 0x1000000 + data[pos+1] * 0x10000 + data[pos+2] * 0x100 + data[pos+3]
|
||||
const type = data.slice(pos+4,pos+8)
|
||||
const typeString = new TextDecoder().decode(type)
|
||||
if(typeString === 'IEND'){
|
||||
break
|
||||
}
|
||||
if(typeString === 'tEXt'){
|
||||
pos += 12 + len
|
||||
}
|
||||
else{
|
||||
await this.pushData(data.slice(pos,pos+12+len))
|
||||
pos += 12 + len
|
||||
}
|
||||
}
|
||||
}
|
||||
async write(key:string, val:string){
|
||||
|
||||
const keyData = new TextEncoder().encode(key)
|
||||
const value = Buffer.from(val)
|
||||
const lenNum = value.byteLength + keyData.byteLength + 1
|
||||
//idk, but uint32array is not working
|
||||
const length = new Uint8Array([
|
||||
lenNum / 0x1000000 % 0x100,
|
||||
lenNum / 0x10000 % 0x100,
|
||||
lenNum / 0x100 % 0x100,
|
||||
lenNum % 0x100
|
||||
])
|
||||
const type = new TextEncoder().encode('tEXt')
|
||||
await this.pushData(length)
|
||||
await this.pushData(type)
|
||||
await this.pushData(keyData)
|
||||
await this.pushData(new Uint8Array([0]))
|
||||
await this.pushData(value)
|
||||
const crc = crc32(Buffer.concat([type,keyData,new Uint8Array([0]),value]))
|
||||
await this.pushData(new Uint8Array([
|
||||
crc / 0x1000000 % 0x100,
|
||||
crc / 0x10000 % 0x100,
|
||||
crc / 0x100 % 0x100,
|
||||
crc % 0x100
|
||||
]))
|
||||
}
|
||||
async end() {
|
||||
const length = new Uint8Array((new Uint32Array([0])).buffer)
|
||||
const type = new TextEncoder().encode('IEND')
|
||||
await this.pushData(length)
|
||||
await this.pushData(type)
|
||||
const crc = crc32(type)
|
||||
await this.pushData(new Uint8Array([
|
||||
crc / 0x1000000 % 0x100,
|
||||
crc / 0x10000 % 0x100,
|
||||
crc / 0x100 % 0x100,
|
||||
crc % 0x100
|
||||
]))
|
||||
this.writer.close()
|
||||
}
|
||||
}
|
||||
|
||||
export const PngChunk = {
|
||||
read: (data:Uint8Array, chunkName:string[], arg:{checkCrc?:boolean} = {}) => {
|
||||
let pos = 8
|
||||
@@ -25,7 +98,7 @@ export const PngChunk = {
|
||||
const chunkData = data.slice(pos+8,pos+8+len)
|
||||
let key=''
|
||||
let value=''
|
||||
for(let i=0;i<10;i++){
|
||||
for(let i=0;i<70;i++){
|
||||
if(chunkData[i] === 0){
|
||||
key = new TextDecoder().decode(chunkData.slice(0,i))
|
||||
value = new TextDecoder().decode(chunkData.slice(i))
|
||||
@@ -40,6 +113,41 @@ export const PngChunk = {
|
||||
}
|
||||
return chunks
|
||||
},
|
||||
|
||||
readGenerator: function*(data:Uint8Array, arg:{checkCrc?:boolean} = {}):Generator<{key:string,value:string},null>{
|
||||
let pos = 8
|
||||
while(pos < data.length){
|
||||
const len = data[pos] * 0x1000000 + data[pos+1] * 0x10000 + data[pos+2] * 0x100 + data[pos+3]
|
||||
const type = data.slice(pos+4,pos+8)
|
||||
const typeString = new TextDecoder().decode(type)
|
||||
console.log(typeString, len)
|
||||
if(arg.checkCrc){
|
||||
const crc = data[pos+8+len] * 0x1000000 + data[pos+9+len] * 0x10000 + data[pos+10+len] * 0x100 + data[pos+11+len]
|
||||
const crcCheck = crc32(data.slice(pos+4,pos+8+len))
|
||||
if(crc !== crcCheck){
|
||||
throw new Error('crc check failed')
|
||||
}
|
||||
}
|
||||
if(typeString === 'IEND'){
|
||||
break
|
||||
}
|
||||
if(typeString === 'tEXt'){
|
||||
const chunkData = data.slice(pos+8,pos+8+len)
|
||||
let key=''
|
||||
let value=''
|
||||
for(let i=0;i<70;i++){
|
||||
if(chunkData[i] === 0){
|
||||
key = new TextDecoder().decode(chunkData.slice(0,i))
|
||||
value = new TextDecoder().decode(chunkData.slice(i))
|
||||
break
|
||||
}
|
||||
}
|
||||
yield {key,value}
|
||||
}
|
||||
pos += 12 + len
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
trim: (data:Uint8Array) => {
|
||||
let pos = 8
|
||||
@@ -141,4 +249,5 @@ export const PngChunk = {
|
||||
return Buffer.concat(newData)
|
||||
}
|
||||
},
|
||||
streamWriter: StreamChunkWriter
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user