ketr.photos/frontend/js/load-image-iptc.js
James Ketrenos 017560fa1a Added MVIMG support!
Signed-off-by: James Ketrenos <james_gitlab@ketrenos.com>
2019-11-28 02:56:45 -08:00

154 lines
5.0 KiB
JavaScript

/*
* JavaScript Load Image IPTC Parser
* https://github.com/blueimp/JavaScript-Load-Image
*
* Copyright 2013, Sebastian Tschan
* Copyright 2018, Dave Bevan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
/* global define, module, require, Buffer */
;(function(factory) {
'use strict'
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['./load-image', './load-image-meta'], factory)
} else if (typeof module === 'object' && module.exports) {
factory(require('./load-image'), require('./load-image-meta'))
} else {
// Browser globals:
factory(window.loadImage)
}
})(function(loadImage) {
'use strict'
loadImage.IptcMap = function() {
return this
}
loadImage.IptcMap.prototype.map = {
ObjectName: 0x5
}
loadImage.IptcMap.prototype.get = function(id) {
return this[id] || this[this.map[id]]
}
loadImage.parseIptcTags = function(
dataView,
startOffset,
sectionLength,
data
) {
/**
* Retrieves string for the given Buffer and range
*
* @param {Buffer} buffer IPTC buffer
* @param {number} start Range start
* @param {number} length Range length
* @returns {string} String value
*/
function getStringFromDB(buffer, start, length) {
var outstr = ''
for (var n = start; n < start + length; n++) {
outstr += String.fromCharCode(buffer.getUint8(n))
}
return outstr
}
var fieldValue, dataSize, segmentType
var segmentStartPos = startOffset
while (segmentStartPos < startOffset + sectionLength) {
// we currently handle the 2: class of iptc tag
if (
dataView.getUint8(segmentStartPos) === 0x1c &&
dataView.getUint8(segmentStartPos + 1) === 0x02
) {
segmentType = dataView.getUint8(segmentStartPos + 2)
// only store data for known tags
if (segmentType in data.iptc.tags) {
dataSize = dataView.getInt16(segmentStartPos + 3)
fieldValue = getStringFromDB(dataView, segmentStartPos + 5, dataSize)
// Check if we already stored a value with this name
if (Object.prototype.hasOwnProperty.call(data.iptc, segmentType)) {
// Value already stored with this name, create multivalue field
if (data.iptc[segmentType] instanceof Array) {
data.iptc[segmentType].push(fieldValue)
} else {
data.iptc[segmentType] = [data.iptc[segmentType], fieldValue]
}
} else {
data.iptc[segmentType] = fieldValue
}
}
}
segmentStartPos++
}
}
loadImage.parseIptcData = function(dataView, offset, length, data, options) {
if (options.disableIptc) {
return
}
var markerLength = offset + length
// Found '8BIM<EOT><EOT>' ?
var isFieldSegmentStart = function(dataView, offset) {
return (
dataView.getUint32(offset) === 0x3842494d &&
dataView.getUint16(offset + 4) === 0x0404
)
}
// Hunt forward, looking for the correct IPTC block signature:
// Reference: https://metacpan.org/pod/distribution/Image-MetaData-JPEG/lib/Image/MetaData/JPEG/Structures.pod#Structure-of-a-Photoshop-style-APP13-segment
// From https://github.com/exif-js/exif-js/blob/master/exif.js ~ line 474 on
while (offset + 8 < markerLength) {
if (isFieldSegmentStart(dataView, offset)) {
var nameHeaderLength = dataView.getUint8(offset + 7)
if (nameHeaderLength % 2 !== 0) nameHeaderLength += 1
// Check for pre photoshop 6 format
if (nameHeaderLength === 0) {
// Always 4
nameHeaderLength = 4
}
var startOffset = offset + 8 + nameHeaderLength
if (startOffset > markerLength) {
// eslint-disable-next-line no-console
console.log('Invalid IPTC data: Invalid segment offset.')
break
}
var sectionLength = dataView.getUint16(offset + 6 + nameHeaderLength)
if (offset + sectionLength > markerLength) {
// eslint-disable-next-line no-console
console.log('Invalid IPTC data: Invalid segment size.')
break
}
// Create the iptc object to store the tags:
data.iptc = new loadImage.IptcMap()
// Parse the tags
return loadImage.parseIptcTags(
dataView,
startOffset,
sectionLength,
data
)
}
// eslint-disable-next-line no-param-reassign
offset++
}
// eslint-disable-next-line no-console
console.log('No IPTC data at this offset - could be XMP')
}
// Registers this IPTC parser for the APP13 JPEG meta data segment:
loadImage.metaDataParsers.jpeg[0xffed].push(loadImage.parseIptcData)
// Adds the following properties to the parseMetaData callback data:
// * iptc: The iptc tags, parsed by the parseIptcData method
// Adds the following options to the parseMetaData method:
// * disableIptc: Disables IPTC parsing.
})