1.delete crc32.js delete png-metadata.js

Signed-off-by: zhoulisheng <635547767@qq.com>
This commit is contained in:
zhoulisheng 2022-07-15 01:02:57 -07:00
parent bdc7156b27
commit ca22bad4c4
5 changed files with 2 additions and 581 deletions

View File

@ -6,15 +6,13 @@
<filteritem type="filename" name="hvigorfile.js" desc="hvigor构建脚本DevEco Studio自动生成不手动修改"/>
<filteritem type="filename" name="*.json5" desc="hvigor配置文件DevEco Studio自动生成不手动修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/UPNG.js" desc="使用开源库UPNG,使用其默认版权头,无需修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/crc32.js" desc="使用开源库crc-32,使用其默认版权头,无需修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/png-metadata.js" desc="使用开源https://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_PNG_files,使用其默认版权头,无需修改"/>
</filefilter>
<filefilter name="defaultPolicyFilter" desc="Filters for compatibilitylicense header policies">
<filteritem type="filename" name="hvigorfile.js" desc="hvigor构建脚本DevEco Studio自动生成不手动修改"/>
<filteritem type="filename" name="*.json5" desc="hvigor配置文件DevEco Studio自动生成不手动修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/UPNG.js" desc="使用开源库UPNG,使用其默认版权头,无需修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/crc32.js" desc="使用开源库crc-32,使用其默认版权头,无需修改"/>
<filteritem type="filepath" name="imageknife/src/main/ets/components/imageknife/pngj/png-metadata.js" desc="使用开源https://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_PNG_files,使用其默认版权头,无需修改"/>
</filefilter>
<filefilter name="defaultPolicyFilter" desc="Filters for copyright header policies">
</filefilter>

View File

@ -14,16 +14,6 @@
*/
import router from '@system.router';
import { Pngj } from '@ohos/imageknife'
import {
RESOLUTION_UNITS,
insertMetadata,
readMetadata,
writeMetadata,
textEncode,
textDecode,
extractChunks,
encodeChunks
} from '@ohos/imageknife'
import resourceManager from '@ohos.resourceManager';
import { FileUtils } from '@ohos/imageknife'
import featureability from '@ohos.ability.featureAbility'
@ -165,38 +155,6 @@ struct PngjTestCasePage {
}.width('100%')
.height(60).backgroundColor(Color.Pink)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button('测试readMetadata')
.onClick(() => {
globalThis.ImageKnife.getImageKnifeContext()
.resourceManagergetMedia($r('app.media.pngSample').id)
.then(data => {
let arrayBuffer = this.typedArrayToBuffer(data);
let metadata = readMetadata(arrayBuffer);
console.log("readMetadata metadata=" + JSON.stringify(metadata))
this.hint5 = JSON.stringify(metadata);
})
.catch(err => {
console.log('测试readMetadata err=' + err)
})
}).margin({ top: 5, left: 10 })
Button('测试writeMetadata')
.onClick(() => {
globalThis.ImageKnife.getImageKnifeContext()
.resourceManagergetMedia($r('app.media.pngSample').id)
.then(data => {
let arrayBuffer = this.typedArrayToBuffer(data);
// let pngBuffer = writeMetadata(arrayBuffer);
// console.log("writeMetadata metadata="+JSON.stringify(metadata))
// this.hint5 = JSON.stringify(metadata);
})
.catch(err => {
console.log('测试writeMetadata err=' + err)
})
}).margin({ top: 5, left: 10 })
}.width('100%')
.height(60).backgroundColor(Color.Pink)
Text(this.hint1)
.width('100%')
.height(120)

View File

@ -83,9 +83,6 @@ export * from './src/main/ets/components/imageknife/pngj/Pngj'
export {handler} from './src/main/ets/components/imageknife/pngj/PngWork'
export * from './src/main/ets/components/imageknife/pngj/UPNG'
export {
RESOLUTION_UNITS, insertMetadata, readMetadata, writeMetadata, textEncode, textDecode, extractChunks, encodeChunks
} from './src/main/ets/components/imageknife/pngj/png-metadata'
/**

View File

@ -1,109 +0,0 @@
/* crc32.js (C) 2014-present SheetJS -- http://sheetjs.com */
/* vim: set ts=2: */
/*exported CRC32 */
export var Crc32;
(function(factory){
/*jshint ignore:start */
/*eslint-disable */
factory(Crc32 = {});
/*eslint-enable */
/*jshint ignore:end */
}(function (CRC32) {
CRC32.version = '1.2.0';
/* see perf/crc32table.js */
/*global Int32Array */
function signed_crc_table() {
var c = 0, table = new Array(256);
for (var n = 0; n != 256; ++n) {
c = n;
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
c = ((c & 1) ? (-306674912 ^ (c >>> 1)) : (c >>> 1));
table[n] = c;
}
return typeof Int32Array !== 'undefined' ? new Int32Array(table) : table;
}
var T = signed_crc_table();
function crc32_bstr(bstr, seed) {
var C = seed ^ -1, L = bstr.length - 1;
for (var i = 0; i < L; ) {
C = (C >>> 8) ^ T[(C ^ bstr.charCodeAt(i++))&0xFF];
C = (C >>> 8) ^ T[(C ^ bstr.charCodeAt(i++))&0xFF];
}
if (i === L) C = (C >>> 8) ^ T[(C ^ bstr.charCodeAt(i))&0xFF];
return C ^ -1;
}
function crc32_buf(buf, seed) {
if (buf.length > 10000) return crc32_buf_8(buf, seed);
var C = seed ^ -1, L = buf.length - 3;
for (var i = 0; i < L; ) {
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
}
while (i < L + 3) C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
return C ^ -1;
}
function crc32_buf_8(buf, seed) {
var C = seed ^ -1, L = buf.length - 7;
for (var i = 0; i < L; ) {
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
}
while (i < L + 7) C = (C >>> 8) ^ T[(C ^ buf[i++])&0xFF];
return C ^ -1;
}
function crc32_str(str, seed) {
var C = seed ^ -1;
for (var i = 0, L = str.length, c, d; i < L; ) {
c = str.charCodeAt(i++);
if (c < 0x80) {
C = (C >>> 8) ^ T[(C ^ c)&0xFF];
} else if (c < 0x800) {
C = (C >>> 8) ^ T[(C ^ (192 | ((c >> 6) & 31)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | (c & 63)))&0xFF];
} else if (c >= 0xD800 && c < 0xE000) {
c = (c & 1023) + 64;
d = str.charCodeAt(i++) & 1023;
C = (C >>> 8) ^ T[(C ^ (240 | ((c >> 8) & 7)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 2) & 63)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | ((d >> 6) & 15) | ((c & 3) << 4)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | (d & 63)))&0xFF];
} else {
C = (C >>> 8) ^ T[(C ^ (224 | ((c >> 12) & 15)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | ((c >> 6) & 63)))&0xFF];
C = (C >>> 8) ^ T[(C ^ (128 | (c & 63)))&0xFF];
}
}
return C ^ -1;
}
CRC32.table = T;
// $FlowIgnore
CRC32.bstr = crc32_bstr;
// $FlowIgnore
CRC32.buf = crc32_buf;
// $FlowIgnore
CRC32.str = crc32_str;
}));

View File

@ -1,423 +0,0 @@
/**
* library to read and write PNG Metadata
*
* References:
* w3 PNG Chunks specification: https://www.w3.org/TR/PNG-Chunks.html
* The Metadata in PNG files: https://dev.exiv2.org/projects/exiv2/wiki/The_Metadata_in_PNG_files
*/
import { Crc32 } from './crc32'
// Used for fast-ish conversion between uint8s and uint32s/int32s.
// Also required in order to remain agnostic for both Node Buffers and
// Uint8Arrays.
let uint8 = new Uint8Array(4)
let int32 = new Int32Array(uint8.buffer)
let uint32 = new Uint32Array(uint8.buffer)
export const RESOLUTION_UNITS = { UNDEFINED: 0, METERS: 1, INCHES: 2 };
/**
* https://github.com/aheckmann/sliced
* An Array.prototype.slice.call(arguments) alternative
* @param {Object} args something with a length
* @param {Number} slice
* @param {Number} sliceEnd
* @api public
*/
function sliced(args, slice, sliceEnd) {
var ret = [];
var len = args.length;
if (0 === len) return ret;
var start = slice < 0
? Math.max(0, slice + len)
: slice || 0;
if (sliceEnd !== undefined) {
len = sliceEnd < 0
? sliceEnd + len
: sliceEnd
}
while (len-- > start) {
ret[len - start] = args[len];
}
return ret;
}
/**
* https://github.com/hughsk/png-chunk-text
* Returns a chunk object containing the metadata for a given key and value:
* @param keyword
* @param content
* @param chunkName
* @returns {{data: Uint8Array, name: 'tEXt'}}
*/
export function textEncode(keyword, content, chunkName = 'tEXt') {
keyword = String(keyword)
content = String(content)
if (content.length && (!/^[\x00-\xFF]+$/.test(keyword) || !/^[\x00-\xFF]+$/.test(content))) {
throw new Error('Only Latin-1 characters are permitted in PNG tEXt chunks. You might want to consider base64 encoding and/or zEXt compression')
}
if (keyword.length >= 80) {
throw new Error('Keyword "' + keyword + '" is longer than the 79-character limit imposed by the PNG specification')
}
let totalSize = keyword.length + content.length + 1
let output = new Uint8Array(totalSize)
let idx = 0
let code
for (let i = 0; i < keyword.length; i++) {
if (!(code = keyword.charCodeAt(i))) {
throw new Error('0x00 character is not permitted in tEXt keywords')
}
output[idx++] = code
}
output[idx++] = 0
for (let j = 0; j < content.length; j++) {
if (!(code = content.charCodeAt(j))) {
throw new Error('0x00 character is not permitted in tEXt content')
}
output[idx++] = code
}
return {
name: chunkName,
data: output
}
}
/**
* https://github.com/hughsk/png-chunk-text
* Reads a Uint8Array or Node.js Buffer instance containing a tEXt PNG chunk's data and returns its keyword/text:
* @param data
* @returns {{text: string, keyword: string}}
*/
export function textDecode(data) {
if (data.data && data.name) {
data = data.data
}
let naming = true
let text = ''
let name = ''
for (let i = 0; i < data.length; i++) {
let code = data[i]
if (naming) {
if (code) {
name += String.fromCharCode(code)
} else {
naming = false
}
} else {
if (code) {
text += String.fromCharCode(code)
} else {
throw new Error('Invalid NULL character found. 0x00 character is not permitted in tEXt content')
}
}
}
return {
keyword: name,
text: text
}
}
/**
* https://github.com/hughsk/png-chunks-extract
* Extract the data chunks from a PNG file.
* Useful for reading the metadata of a PNG image, or as the base of a more complete PNG parser.
* Takes the raw image file data as a Uint8Array or Node.js Buffer, and returns an array of chunks. Each chunk has a name and data buffer:
* @param data {Uint8Array}
* @returns {[{name: String, data: Uint8Array}]}
*/
export function extractChunks(data) {
if (data[0] !== 0x89) throw new Error('Invalid .png file header')
if (data[1] !== 0x50) throw new Error('Invalid .png file header')
if (data[2] !== 0x4E) throw new Error('Invalid .png file header')
if (data[3] !== 0x47) throw new Error('Invalid .png file header')
if (data[4] !== 0x0D) throw new Error('Invalid .png file header: possibly caused by DOS-Unix line ending conversion?')
if (data[5] !== 0x0A) throw new Error('Invalid .png file header: possibly caused by DOS-Unix line ending conversion?')
if (data[6] !== 0x1A) throw new Error('Invalid .png file header')
if (data[7] !== 0x0A) throw new Error('Invalid .png file header: possibly caused by DOS-Unix line ending conversion?')
let ended = false
let chunks = []
let idx = 8
while (idx < data.length) {
// Read the length of the current chunk,
// which is stored as a Uint32.
uint8[3] = data[idx++]
uint8[2] = data[idx++]
uint8[1] = data[idx++]
uint8[0] = data[idx++]
// Chunk includes name/type for CRC check (see below).
let length = uint32[0] + 4
let chunk = new Uint8Array(length)
chunk[0] = data[idx++]
chunk[1] = data[idx++]
chunk[2] = data[idx++]
chunk[3] = data[idx++]
// Get the name in ASCII for identification.
let name = (
String.fromCharCode(chunk[0]) +
String.fromCharCode(chunk[1]) +
String.fromCharCode(chunk[2]) +
String.fromCharCode(chunk[3])
)
// The IHDR header MUST come first.
if (!chunks.length && name !== 'IHDR') {
throw new Error('IHDR header missing')
}
// The IEND header marks the end of the file,
// so on discovering it break out of the loop.
if (name === 'IEND') {
ended = true
chunks.push({
name: name,
data: new Uint8Array(0)
})
break
}
// Read the contents of the chunk out of the main buffer.
for (let i = 4; i < length; i++) {
chunk[i] = data[idx++]
}
// Read out the CRC value for comparison.
// It's stored as an Int32.
uint8[3] = data[idx++]
uint8[2] = data[idx++]
uint8[1] = data[idx++]
uint8[0] = data[idx++]
let crcActual = int32[0]
let crcExpect = Crc32.buf(chunk)
if (crcExpect !== crcActual) {
throw new Error(
'CRC values for ' + name + ' header do not match, PNG file is likely corrupted'
)
}
// The chunk data is now copied to remove the 4 preceding
// bytes used for the chunk name/type.
let chunkData = new Uint8Array(chunk.buffer.slice(4))
chunks.push({
name: name,
data: chunkData
})
}
if (!ended) {
throw new Error('.png file ended prematurely: no IEND header was found')
}
return chunks
}
/**
* https://github.com/hughsk/png-chunks-encode
* Return a fresh PNG buffer given a set of PNG chunks. Useful in combination with png-chunks-encode to easily modify or add to the data of a PNG file.
* Takes an array of chunks, each with a name and data:
* @param chunks {[{name: String, data: Uint8Array}]}
* @returns {Uint8Array}
*/
export function encodeChunks(chunks) {
let totalSize = 8
let idx = totalSize
let i
for (i = 0; i < chunks.length; i++) {
totalSize += chunks[i].data.length
totalSize += 12
}
let output = new Uint8Array(totalSize)
output[0] = 0x89
output[1] = 0x50
output[2] = 0x4E
output[3] = 0x47
output[4] = 0x0D
output[5] = 0x0A
output[6] = 0x1A
output[7] = 0x0A
for (i = 0; i < chunks.length; i++) {
let chunk = chunks[i]
let name = chunk.name
let data = chunk.data
let size = data.length
let nameChars = [
name.charCodeAt(0),
name.charCodeAt(1),
name.charCodeAt(2),
name.charCodeAt(3)
]
uint32[0] = size
output[idx++] = uint8[3]
output[idx++] = uint8[2]
output[idx++] = uint8[1]
output[idx++] = uint8[0]
output[idx++] = nameChars[0]
output[idx++] = nameChars[1]
output[idx++] = nameChars[2]
output[idx++] = nameChars[3]
for (let j = 0; j < size; ) {
output[idx++] = data[j++]
}
let crcCheck = nameChars.concat(sliced(data, undefined, undefined));
int32[0] = Crc32.buf(crcCheck)
output[idx++] = uint8[3]
output[idx++] = uint8[2]
output[idx++] = uint8[1]
output[idx++] = uint8[0]
}
return output
}
/**
* read 4 bytes number from UInt8Array.
* @param uint8array
* @param offset
* @returns {number}
*/
function readUint32(uint8array, offset) {
let byte1, byte2, byte3, byte4;
byte1 = uint8array[offset++];
byte2 = uint8array[offset++];
byte3 = uint8array[offset++];
byte4 = uint8array[offset];
return 0 | (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4;
}
/**
* write 4 bytes number to UInt8Array.
* @param uint8array
* @param num
* @param offset
*/
function writeUInt32(uint8array, num, offset) {
uint8array[offset] = (num & 0xff000000) >> 24;
uint8array[offset + 1] = (num & 0x00ff0000) >> 16;
uint8array[offset + 2] = (num & 0x0000ff00) >> 8;
uint8array[offset + 3] = (num & 0x000000ff);
}
/**
* Get object with PNG metadata. only tEXt and pHYs chunks are parsed
* @param buffer {Buffer}
* @returns {{tEXt: {keyword: value}, pHYs: {x: number, y: number, units: RESOLUTION_UNITS}, [string]: true}}
*/
export function readMetadata(buffer) {
let result = {};
const chunks = extractChunks(buffer);
chunks.forEach(chunk => {
switch (chunk.name) {
case 'tEXt':
if (!result['tEXt']) {
result['tEXt'] = {};
}
let textChunk = textDecode(chunk.data);
result['tEXt'][textChunk.keyword] = textChunk.text;
break
case 'pHYs':
result['pHYs'] = {
// Pixels per unit, X axis: 4 bytes (unsigned integer)
"x": readUint32(chunk.data, 0),
// Pixels per unit, Y axis: 4 bytes (unsigned integer)
"y": readUint32(chunk.data, 4),
"unit": chunk.data[8],
}
break
case 'gAMA':
case 'cHRM':
case 'sRGB':
case 'IHDR':
case 'iCCP':
default:
result[chunk.name] = true;
}
})
return result;
}
/**
* create new Buffer with metadata. only tEXt and pHYs chunks are supported.
* @param buffer {Buffer}
* @param metadata {{tEXt: {keyword: value}, pHYs: {x: number, y: number, units: RESOLUTION_UNITS}}}
* @returns {Buffer}
*/
export function writeMetadata(buffer, metadata) {
const chunks = extractChunks(buffer);
insertMetadata(chunks, metadata);
ArrayBuffer
let out = encodeChunks(chunks).buffer;
return out;
}
export function insertMetadata(chunks, metadata) {
if (metadata.clear) {
for (let i = chunks.length - 1; i--; ) {
switch (chunks[i].name) {
case 'IHDR':
case 'IDAT':
case 'IEND':
break;
default:
chunks.splice(i, 1);
}
}
}
if (metadata.tEXt) {
for (var keyword in metadata.tEXt) {
chunks.splice(-1, 0, textEncode(keyword, metadata.tEXt[keyword]))
}
}
if (metadata.pHYs) {
const data = new Uint8Array(9);
writeUInt32(data, metadata.pHYs.x, 0)
writeUInt32(data, metadata.pHYs.y, 4)
data[8] = metadata.pHYs.units; // inches
let pHYs = chunks.find(chunk => chunk.name === "pHYs");
if (pHYs) {
pHYs.data = data;
}
else {
chunks.splice(1, 0, { name: "pHYs", data: data })
}
}
}