Created
June 15, 2022 21:08
-
-
Save zazaulola/44aa030102dcc55a270852b034a854ba to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** @format */ | |
/** | |
* Функция отчищает JPEG-картинку от метаданных | |
* | |
* @param {ArrayBuffer} buf буфер с изображением | |
* @returns {Blob|null} | |
*/ | |
function clearJpegMetadata(buf) { | |
if (!(buf instanceof ArrayBuffer)) { | |
console.error('buf = ', buf); | |
throw new TypeError('Wrong ArrayBuffer specified'); | |
} | |
const dv = new DataView(buf); | |
const length = dv.byteLength; | |
const SOI = dv.getUint16(0, false); | |
const EOI = dv.getUint16(length - 2, false); | |
if (SOI != 0xffd8 || EOI != 0xffd9) { | |
console.error('SOI = ', SOI); | |
console.error('EOI = ', EOI); | |
throw new ReferenceError('Not valid JPEG image'); | |
} | |
const p = []; | |
let r = 0; | |
for (const { type, ofs, len } of readJpegSegments(buf)) { | |
if (type == 0xe1) { | |
p.push([r, ofs - 2]); | |
r = ofs + len; | |
} else if (type == 0xda) { | |
p.push([r]); | |
break; | |
} | |
} | |
return p.length | |
? new Blob( | |
p.map(a => buf.slice(...a)), | |
{ type: 'image/jpeg' } | |
) | |
: null; | |
} | |
/** @format */ | |
/** | |
* Функция читает из буфера JPEG-картинки ориентацию и размеры в пикселях | |
* | |
* @param {ArrayBuffer} buf буфер с изображением | |
* @returns {{orientation:Number,width:Number,height:Number}} | |
*/ | |
function readJpegRect(buf) { | |
if (!(buf instanceof ArrayBuffer)) { | |
console.error('buf = ', buf); | |
throw new TypeError('Wrong ArrayBuffer specified'); | |
} | |
const dv = new DataView(buf); | |
const length = dv.byteLength; | |
const SOI = dv.getUint16(0, false); | |
const EOI = dv.getUint16(length - 2, false); | |
if (SOI != 0xffd8 || EOI != 0xffd9) { | |
console.error('SOI = ', SOI); | |
console.error('EOI = ', EOI); | |
throw new ReferenceError('Not valid JPEG image'); | |
} | |
let width=0,height=0,orientation=0; | |
for (let { type, ofs } of readJpegSegments(buf)) { | |
if (type == 0xe1) { | |
if (dv.getUint32(ofs, false) != 0x45786966 || dv.getUint16(ofs + 4, false) != 0) { | |
throw new Error('Wrong Exif format'); | |
} | |
ofs += 6; | |
const isLE = dv.getUint16(ofs, false) == 0x4949; | |
ofs += dv.getUint32(ofs + 4, isLE); | |
const tagCount = dv.getUint16(ofs, isLE); | |
ofs += 2; | |
for (let i = 0; i < tagCount; i++){ | |
if (dv.getUint16(ofs + i * 12, isLE) == 0x0112) { | |
orientation = dv.getUint16(ofs + i * 12 + 8, isLE); | |
} | |
} | |
} else if (0xc0 <= type && type <= 0xcf) { | |
ofs += 1; | |
height = Math.max(height, dv.getUint16(ofs, false)); | |
ofs += 2; | |
width = Math.max(width, dv.getUint16(ofs, false)); | |
} | |
} | |
if (!orientation) { | |
orientation = 1; | |
} | |
return { orientation, width, height }; | |
} | |
/** | |
* Читает сегменты из JPEG буфера | |
* @param {ArrayBuffer} buf | |
* @yields {type: Number, ofs: Number, len: Number} | |
*/ | |
function* readJpegSegments(buf) { | |
if (!(buf instanceof ArrayBuffer)) { | |
console.error('buf = ', buf); | |
throw new TypeError('Wrong ArrayBuffer specified'); | |
} | |
const dv = new DataView(buf); | |
const length = dv.byteLength; | |
const SOI = dv.getUint16(0, false); | |
const EOI = dv.getUint16(length - 2, false); | |
if (SOI != 0xffd8 || EOI != 0xffd9) { | |
console.error('SOI = ', SOI); | |
console.error('EOI = ', EOI); | |
throw new ReferenceError('Not valid JPEG image'); | |
} | |
let idx = 2; | |
while (idx < size - 2) { | |
if (0xff != dv.getUint8(idx++)) { | |
throw new RangeError('Not valid JPEG image'); | |
} | |
const type = dv.getUint8(idx++); | |
const ofs = idx; | |
const len = dv.getUint16(idx, false); | |
idx += len; | |
yield { type, ofs, len }; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment