您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
jpeg -> array
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/38665/255145/bv7_jpeg2array_b.js
// ==UserScript== // @name bv7_jpeg2array_b // @namespace bv7 // @version 0.6 // @description jpeg -> array // @author bv7 // @include file:///D:/projects/JSProjects/bv7bbc/bv7_bbc_dark/bv_dev_canvas*.html // @run-at document-idle // @grant GM_xmlhttpRequest // ==/UserScript== class BaseImage { constructor() { this._src = null; this.onload = (() => ''); } load() { GM_xmlhttpRequest({ method : 'GET', url : this._src, overrideMimeType: 'text/plain; charset=x-user-defined', onload : (v) => { let data = new Uint8Array(v.responseText.length); data.forEach((val, i) => data[i] = v.responseText.charCodeAt(i)); this.parse(data); //this.decode(); this.onload(); } }); } get src() {return this._src;} set src(v) { if (this._src !== v) { this._src = v; this.load(); } } drawCanvas(canvas, dx, dy, dWidth, dHeight, sx, sy, sWidth, sHeight) { let context = canvas.getContext('2d'); let imageData = context.getImageData(0, 0, canvas.width, canvas.height); this.copyToImageData(imageData); //for (let x = dx; x < imageData; x++) for (let y = dy; y < dy + dHeight; y++) context. //context.putImageData(imageData, dx, dy, sx, sy, sWidth, sHeight); context.putImageData(imageData, 0, 0); } } class JpegImage extends BaseImage { parse(data) { this.jfif = null; this.adobe = null; const dctZigZag = new Int32Array([ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 ]); const dctCos1 = 4017; // cos( pi/16) const dctSin1 = 799; // sin( pi/16) const dctCos3 = 3406; // cos(3*pi/16) const dctSin3 = 2276; // sin(3*pi/16) const dctCos6 = 1567; // cos(6*pi/16) const dctSin6 = 3784; // sin(6*pi/16) const dctSqrt2 = 5793; // sqrt(2) const dctSqrt1d2 = 2896; // sqrt(2) / 2 let frame; let resetInterval; let quantizationTables = []; let frames = []; let huffmanTablesAC = []; let huffmanTablesDC = []; let offset = 0; let readUint8 = () => data[offset++]; let readUint16 = () => ((readUint8() << 8) | readUint8()); let readDataBlock = () => { let length = readUint16() - 2; let value = data.slice(offset, offset + length - 2); offset += length; return value; }; let buildHuffmanTable = (codeLengths, values) => { let length = codeLengths.length; while (length > 0 && !codeLengths[length - 1]) length--; let p = {children: [], index: 0}; let code = [p]; for (let i = 0, k = 0, q; i < length; i++) { for (let j = 0; j < codeLengths[i]; j++, k++) { p = code.pop(); p.children[p.index] = values[k]; while (p.index > 0) p = code.pop(); p.index++; code.push(p); while (code.length <= i) { code.push(q = {children: [], index: 0}); p.children[p.index] = q.children; p = q; } } if (i + 1 < length) { // p here points to last code code.push(q = {children: [], index: 0}); p.children[p.index] = q.children; p = q; } } return code[0].children; }; let buildComponentData = (component) => { let lines = []; let samplesPerLine = component.blocksPerLine << 3; let R = new Int32Array(64); let r = new Uint8Array(64); // A port of poppler's IDCT method which in turn is taken from: // Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, // "Practical Fast 1-D DCT Algorithms with 11 Multiplications", // IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, // 988-991. let quantizeAndInverse = (zz, dataOut, dataIn) => { let t, v, u; // dequant dataIn.forEach((v, i) => dataIn[i] = zz[i] * component.quantizationTable[i]); for (let i = 0; i < 8; ++i) { let row = 8 * i; v = dataIn.slice(row, 8 + row); // check for all-zero AC coefficients if (v.every((val, i) => (!i || !val))) dataIn.fill((dctSqrt2 * v[0] + 512) >> 10, row, 8 + row); else { // stage 4 u = [ (dctSqrt2 * v[0] + 128) >> 8, (dctSqrt2 * v[4] + 128) >> 8, v[2], v[6], (dctSqrt1d2 * (v[1] - v[7]) + 128) >> 8, v[3] << 4, v[5] << 4, (dctSqrt1d2 * (v[1] + v[7]) + 128) >> 8 ]; // stage 3 v = [ (u[0] + u[1] + 1) >> 1, (u[0] - u[1] + 1) >> 1, (u[2] * dctCos6 - u[3] * dctSin6 + 128) >> 8, (u[2] * dctSin6 + u[3] * dctCos6 + 128) >> 8, (u[4] + u[6] + 1) >> 1, (u[7] - u[5] + 1) >> 1, (u[4] - u[6] + 1) >> 1, (u[7] + u[5] + 1) >> 1 ]; // stage 2 u = [ (v[0] + v[3] + 1) >> 1, (v[1] + v[2] + 1) >> 1, (v[1] - v[2] + 1) >> 1, (v[0] - v[3] + 1) >> 1, (v[4] * dctCos3 - v[7] * dctSin3 + 2048) >> 12, (v[5] * dctCos1 - v[6] * dctSin1 + 2048) >> 12, (v[5] * dctSin1 + v[6] * dctCos1 + 2048) >> 12, (v[4] * dctSin3 + v[7] * dctCos3 + 2048) >> 12 ]; // stage 1 for(let j = 0; j < 4; j++) { dataIn[0 + j + row] = u[j] + u[7 - j]; dataIn[7 - j + row] = u[j] - u[7 - j]; } } } // inverse DCT on columns for (let col = 0; col < 8; ++col) { for (let i = 0; i < 8; i++) v[i] = dataIn[i * 8 + col]; // check for all-zero AC coefficients if (v.every((val, i) => (!i || !val))) { t = (dctSqrt2 * v[0] + 8192) >> 14; v.forEach((val, i) => dataIn[i * 8 + col] = t); } else { // stage 4 u = [ (dctSqrt2 * v[0] + 2048) >> 12, (dctSqrt2 * v[4] + 2048) >> 12, v[2], v[6], (dctSqrt1d2 * (v[1] - v[7]) + 2048) >> 12, v[3], v[5], (dctSqrt1d2 * (v[1] + v[7]) + 2048) >> 12 ]; // stage 3 v = [ (u[0] + u[1] + 1) >> 1, (u[0] - u[1] + 1) >> 1, (u[2] * dctCos6 - u[3] * dctSin6 + 2048) >> 12, (u[2] * dctSin6 + u[3] * dctCos6 + 2048) >> 12, (u[4] + u[6] + 1) >> 1, (u[7] - u[5] + 1) >> 1, (u[4] - u[6] + 1) >> 1, (u[7] + u[5] + 1) >> 1 ]; // stage 2 u = [ (v[0] + v[3] + 1) >> 1, (v[1] + v[2] + 1) >> 1, (v[1] - v[2] + 1) >> 1, (v[0] - v[3] + 1) >> 1, (v[4] * dctCos3 - v[7] * dctSin3 + 2048) >> 12, (v[5] * dctCos1 - v[6] * dctSin1 + 2048) >> 12, (v[5] * dctSin1 + v[6] * dctCos1 + 2048) >> 12, (v[4] * dctSin3 + v[7] * dctCos3 + 2048) >> 12 ]; // stage 1 for (let i = 0; i < 4; i++) { dataIn[(0 + i) * 8 + col] = u[i] + u[7 - i]; dataIn[(7 - i) * 8 + col] = u[i] - u[7 - i]; } } } // convert to 8-bit integers dataIn.forEach((val, i) => { let sample = 128 + ((val + 8) >> 4); dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample; }); }; for (let blockRow = 0; blockRow < component.blocksPerColumn; blockRow++) { let scanLine = blockRow << 3; for (let i = 0; i < 8; i++) lines.push(new Uint8Array(samplesPerLine)); for (let blockCol = 0; blockCol < component.blocksPerLine; blockCol++) { quantizeAndInverse(component.blocks[blockRow][blockCol], r, R); let sample = blockCol << 3; for (let j = 0, offset = 0; j < 8; j++) { let line = lines[scanLine + j]; for (let i = 0; i < 8; i++, offset++) line[sample + i] = r[offset]; } } } return lines; } let prepareComponents = (frame) => { frame.maxH = 0; frame.maxV = 0; frame.componentsOrder.forEach((v) => { let component = frame.components[v]; if (frame.maxH < component.h) frame.maxH = component.h; if (frame.maxV < component.v) frame.maxV = component.v; }); frame.mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH); frame.mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV); frame.componentsOrder.forEach((v) => { let component = frame.components[v]; component.blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH); component.blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV); component.blocks = []; let blocksPerLineForMcu = frame.mcusPerLine * component.h; let blocksPerColumnForMcu = frame.mcusPerColumn * component.v; for (let i = 0; i < blocksPerColumnForMcu; i++) { let row = []; for (let j = 0; j < blocksPerLineForMcu; j++) row.push(new Int32Array(64)); component.blocks.push(row); } }); }; let decodeScan = (components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) => { let bitsData = 0; let bitsCount = 0; let readBit = () => { if (bitsCount > 0) bitsCount--; else { bitsData = readUint8(); if (bitsData == 0xFF) { let nextByte = readUint8(); if (nextByte) throw new Error('Unexpected marker: ' + ((bitsData << 8) | nextByte).toString(16)); // unstuff 0 } bitsCount = 7; } return (bitsData >> bitsCount) & 1; }; let decodeHuffman = (tree) => { let node = tree; let bit; while ((bit = readBit()) !== null) if (typeof (node = node[bit]) === 'number') return node; else if (typeof node !== 'object') throw new Error('Invalid huffman sequence'); return null; }; let receive = (length) => { let n = 0; for (; length > 0; length--) { let bit = readBit(); if (bit === null) return; n = (n << 1) | bit; } return n; }; let receiveAndExtend = (length) => { let n = receive(length); return (n >= 1 << (length - 1)) ? n : (n + (-1 << length) + 1); }; let decodeBaseline = (component, zz) => { let t = decodeHuffman(component.huffmanTableDC); let diff = t === 0 ? 0 : receiveAndExtend(t); zz[0] = (component.pred += diff); let k = 1; while (k < 64) { let rs = decodeHuffman(component.huffmanTableAC); let s = rs & 15; let r = rs >> 4; if (s === 0) { if (r < 15) break; else { k += 16; continue; } } else { k += r; zz[dctZigZag[k]] = receiveAndExtend(s); k++; } } } let decodeDCFirst = (component, zz) => { let t = decodeHuffman(component.huffmanTableDC); let diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); zz[0] = (component.pred += diff); } let decodeDCSuccessive = (component, zz) => zz[0] |= readBit() << successive; let eobrun = 0; let decodeACFirst = (component, zz) => { if (eobrun > 0) eobrun--; else { let k = spectralStart; while (k <= spectralEnd) { let rs = decodeHuffman(component.huffmanTableAC); let s = rs & 15; let r = rs >> 4; if (s === 0) { if (r < 15) { eobrun = receive(r) + (1 << r) - 1; break; } else k += 16; } else { k += r; zz[dctZigZag[k]] = receiveAndExtend(s) * (1 << successive); k++; } } } }; let successiveACState = 0; let successiveACNextValue = 0; let decodeACSuccessive = (component, zz) => { let k = spectralStart; let r = 0; while(k <= spectralEnd) { let z = dctZigZag[k]; let direction = zz[z] < 0 ? -1 : 1; switch (successiveACState) { case 0: // initial state let rs = decodeHuffman(component.huffmanTableAC); let s = rs & 15; r = rs >> 4; if (s === 0) { if (r < 15) { eobrun = receive(r) + (1 << r); successiveACState = 4; } else { r = 16; successiveACState = 1; } } else if (s !== 1) throw new Error('Invalid ACn encoding'); else { successiveACNextValue = receiveAndExtend(s); successiveACState = r ? 2 : 3; } continue; case 1: // skipping r zero items case 2: if (zz[z]) zz[z] += (readBit() << successive) * direction; else { r--; if (r === 0) successiveACState = successiveACState == 2 ? 3 : 0; } break; case 3: // set value for a zero item if (zz[z]) zz[z] += (readBit() << successive) * direction; else { zz[z] = successiveACNextValue << successive; successiveACState = 0; } break; case 4: // eob if (zz[z]) zz[z] += (readBit() << successive) * direction; break; } k++; } if (successiveACState === 4) { eobrun--; if (eobrun === 0) successiveACState = 0; } }; let decodeMcu = (component, decode, mcu, row, col) => decode( component, component.blocks[((mcu / frame.mcusPerLine) | 0) * component.v + row][(mcu % frame.mcusPerLine) * component.h + col] ); let decodeBlock = (component, decode, mcu) => decode( component, component.blocks[(mcu / component.blocksPerLine) | 0][mcu % component.blocksPerLine] ); let decodeFn = frame.progressive ? ( spectralStart === 0 ? ( successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive ) : ( successivePrev === 0 ? decodeACFirst : decodeACSuccessive ) ) : decodeBaseline; let mcu = 0; let mcuExpected = (components.length == 1) ? ( components[0].blocksPerLine * components[0].blocksPerColumn ) : ( frame.mcusPerLine * frame.mcusPerColumn ); if (!resetInterval) resetInterval = mcuExpected; while (mcu < mcuExpected) { // reset interval stuff components.forEach((v) => v.pred = 0); eobrun = 0; if (components.length == 1) { let component = components[0]; for (let n = 0; n < resetInterval; n++, mcu++) decodeBlock(component, decodeFn, mcu); } else for (let n = 0; n < resetInterval; n++) { for (let i = 0; i < components.length; i++) { let component = components[i]; for (let j = 0; j < component.v; j++) for (let k = 0; k < component.h; k++) decodeMcu(component, decodeFn, mcu, j, k); } mcu++; // If we've reached our expected MCU's, stop decoding if (mcu === mcuExpected) break; } // find marker bitsCount = 0; let marker = readUint16(); if (marker < 0xFFD0 || marker > 0xFFD7) { // !RSTx offset -= 2; if (marker < 0xFF00) throw new Error('Marker was not found'); break; } } }; let fileMarker = readUint16(); if (fileMarker != 0xFFD8) // SOI (Start of Image) throw new Error('SOI not found'); while ((fileMarker = readUint16()) != 0xFFD9) { // EOI (End of image) let length; switch(fileMarker) { case 0xFF00: break; case 0xFFE0: // APP0 (Application Specific) case 0xFFE1: // APP1 case 0xFFE2: // APP2 case 0xFFE3: // APP3 case 0xFFE4: // APP4 case 0xFFE5: // APP5 case 0xFFE6: // APP6 case 0xFFE7: // APP7 case 0xFFE8: // APP8 case 0xFFE9: // APP9 case 0xFFEA: // APP10 case 0xFFEB: // APP11 case 0xFFEC: // APP12 case 0xFFED: // APP13 case 0xFFEE: // APP14 case 0xFFEF: // APP15 case 0xFFFE: // COM (Comment) let appData = readDataBlock(); switch(fileMarker){ case 0xFFE0: if ( appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0 ) this.jfif = { // 'JFIF\x00' version : { major: appData[5], minor: appData[6] }, densityUnits: appData[7], xDensity : (appData[8 ] << 8) | appData[9 ], yDensity : (appData[10] << 8) | appData[11], thumbWidth : appData[12], thumbHeight : appData[13], thumbData : appData.slice(14, 14 + 3 * appData[12] * appData[13] + 1) }; break; // TODO APP1 - Exif case 0xFFEE: if ( appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && appData[3] === 0x62 && appData[4] === 0x65 && appData[5] === 0 ) this.adobe = { // 'Adobe\x00' version : appData[6], flags0 : (appData[7] << 8) | appData[8], flags1 : (appData[9] << 8) | appData[10], transformCode: appData[11] }; break; } break; case 0xFFDB: // DQT (Define Quantization Tables) let quantizationTablesLength = readUint16(); let quantizationTablesEnd = quantizationTablesLength + offset - 2; while (offset < quantizationTablesEnd) { let quantizationTableSpec = readUint8(); let tableData = new Int32Array(64); switch(quantizationTableSpec >> 4){ case 0: // 8 bit values tableData.forEach((v, i) => tableData[dctZigZag[i]] = readUint8()); break; case 1: //16 bit tableData.forEach((v, i) => tableData[dctZigZag[i]] = readUint16()); break; default: throw new Error('DQT: invalid table spec: ' + (quantizationTableSpec >> 4)); } quantizationTables[quantizationTableSpec & 15] = tableData; } break; case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT) case 0xFFC1: // SOF1 (Start of Frame, Extended DCT) case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT) readUint16(); // skip data length frame = { extended : fileMarker === 0xFFC1, progressive : fileMarker === 0xFFC2, precision : readUint8(), scanLines : readUint16(), samplesPerLine : readUint16(), components : {}, componentsOrder: new Uint8Array(readUint8()) }; frame.componentsOrder.forEach((v, i) => { let componentId = readUint8(); let b = readUint8(); frame.components[frame.componentsOrder[i] = componentId] = { h : b >> 4, v : b & 15, quantizationIdx: readUint8() }; }); prepareComponents(frame); frames.push(frame); break; case 0xFFC4: // DHT (Define Huffman Tables) let huffmanLength = readUint16() - 2; while (huffmanLength > 0) { let huffmanTableSpec = readUint8(); let codeLengths = new Uint8Array(16); let codeLengthSum = 0; codeLengths.forEach((v, i) => codeLengthSum += (codeLengths[i] = readUint8())); let huffmanValues = new Uint8Array(codeLengthSum); huffmanValues.forEach((v, i) => huffmanValues[i] = readUint8()); huffmanLength -= 1 + codeLengths.length + huffmanValues.length; ((huffmanTableSpec >> 4) === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues); } break; case 0xFFDD: // DRI (Define Restart Interval) readUint16(); // skip data length resetInterval = readUint16(); break; case 0xFFDA: // SOS (Start of Scan) readUint16(); // scanLength let components = []; for (let selectorsCount = readUint8(); selectorsCount > 0; selectorsCount--) { let component = frame.components[readUint8()]; let tableSpec = readUint8(); component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4]; component.huffmanTableAC = huffmanTablesAC[tableSpec & 15]; components.push(component); } let spectralStart = readUint8(); let spectralEnd = readUint8(); let successiveApproximation = readUint8(); decodeScan( components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15 ); break; case 0xFFFF: // Fill bytes if (data[offset] !== 0xFF) offset--; // Avoid skipping a valid marker. break; default: // could be incorrect encoding -- last 0xFF byte of the previous // block was eaten by the encoder if (data[offset - 3] == data[offset - 2] && data[offset - 2] >= 0xC0 && d1 <= 0xFE) { offset -= 3; break; } else throw new Error('Unknown JPEG marker ' + fileMarker.toString(16)); } } if (frames.length != 1) throw new Error("Only single frame JPEGs supported"); // set each frame's components quantization table frames.forEach((v) => { for (var j in v.components) { v.components[j].quantizationTable = quantizationTables[v.components[j].quantizationIdx]; delete v.components[j].quantizationIdx; } }); this.width = frame.samplesPerLine; this.height = frame.scanLines; this.components = []; frame.componentsOrder.forEach((v) => { let component = frame.components[v]; this.components.push({ lines : buildComponentData(component), scaleX: component.h / frame.maxH, scaleY: component.v / frame.maxV }); }); } clampTo8bit(a) { return a < 0 ? 0 : a > 255 ? 255 : a; } getData(width, height) { let scaleX = this.width / width ; let scaleY = this.height / height; let data = new Uint8Array(width * height * this.components.length); let offset = 0; if (this.components.length > 0 && this.components.length < 5) { let components4 = this.components.length == 4; // PDF might compress two component data in custom colorspace if (components4 && !this.adobe) throw new Error('Unsupported color mode (4 components)'); else { // The default transform for three components is true // The adobe transform marker overrides any previous setting let colorTransform = this.components.length > 2 && ( (this.adobe && this.adobe.transformCode) || (typeof this.colorTransform === 'undefined') || !!this.colorTransform ); let componentLines = []; let d = new Uint8Array(this.components.length); for (let y = 0; y < height; y++) { this.components.forEach((v, i) => (componentLines[i] = v.lines[0 | (y * v.scaleY * scaleY)])); for (let x = 0; x < width; x++) { componentLines.forEach((v, i) => (d[i] = v[0 | (x * this.components[i].scaleX * scaleX)])); // Y if (colorTransform) { data[offset++] = this.clampTo8bit(d[0] + 1.402 * (d[2] - 128)); data[offset++] = this.clampTo8bit(d[0] - 0.3441363 * (d[1] - 128) - 0.71413636 * (d[2] - 128)); data[offset++] = this.clampTo8bit(d[0] + 1.772 * (d[1] - 128)); if (components4) data[offset++] = 255 - d[0]; } else if (components4) d.forEach((v) => data[offset++] = 255 - v); else d.forEach((v) => data[offset++] = v); } } } } else throw new Error('Unsupported color mode'); return data; } copyToImageData(imageData) { let data = this.getData(imageData.width, imageData.height); let i = 0; let j = 0; switch (this.components.length) { case 1: for (let y = 0; y < imageData.height; y++) for (let x = 0; x < imageData.width; x++) { imageData.data[j++] = imageData.data[j++] = imageData.data[j++] = data[i++]; // Y imageData.data[j++] = 255; } break; case 3: for (let y = 0; y < imageData.height; y++) for (let x = 0; x < imageData.width; x++) { imageData.data[j++] = data[i++]; // R imageData.data[j++] = data[i++]; // G imageData.data[j++] = data[i++]; // B imageData.data[j++] = 255; } break; case 4: for (let y = 0; y < imageData.height; y++) for (let x = 0; x < imageData.width; x++) { let C = data[i++]; let M = data[i++]; let Y = data[i++]; let K = data[i++]; imageData.data[j++] = 255 - this.clampTo8bit(C * (1 - K / 255) + K); // R imageData.data[j++] = 255 - this.clampTo8bit(M * (1 - K / 255) + K); // G imageData.data[j++] = 255 - this.clampTo8bit(Y * (1 - K / 255) + K); // B imageData.data[j++] = 255; } break; default: throw new Error('Unsupported color mode'); } } } /* let jpeg = new JpegImage(); jpeg.onload = function() { this.drawCanvas(document.getElementById('canvas'), 10, 10, 20, 20, 50, 50); console.log('jpeg =', this); }; jpeg.src = document.getElementById('img1').src; */
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址