| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- const fs = require('fs');
- const tmp = require('tmp');
- const imLib = require('imagemagick');
- const ThreadPool = require('../threadPool.js');
- const MetaStruct = require('./metaStruct.js').MetaStruct;
- class ImagemagickWrapper {
- #threadPool = new ThreadPool(5);
- readMeta(path) {
- return this.#threadPool.pushTask(() => new Promise((ok, ko) => {
- imLib.identify(['-format', '%[EXIF:*]Compression=%[compression]\nWidth=%w\nHeight=%h\n', path], (err, stdout) => {
- if (err)
- return ko(err);
- ok(stdout);
- });
- }));
- }
- convert(args) {
- return this.#threadPool.pushTask(() => new Promise((ok, ko) => {
- imLib.convert(args, (err, stdout) => {
- if (err)
- return ko(err);
- ok(stdout);
- });
- }));
- }
- }
- const im = new ImagemagickWrapper();
- function readMeta(path) {
- return new Promise(async (ok, ko) => {
- try {
- let stdout = await im.readMeta(path);
- var meta = {};
- for (const line of stdout.split(/\n/))
- {
- var eq_p = line.indexOf('=');
- if (eq_p === -1)
- continue;
- var key = line.substr(0, eq_p).replace('/','-'),
- value = line.substr(eq_p+1).trim();
- var p = key.indexOf(':');
- if (p !== -1)
- key = key.substr(p+1);
- key = key.charAt(0).toLowerCase() + key.slice(1);
- meta[key] = value;
- }
- ok(meta);
- } catch (err) {
- console.error("readMeta from Imagemagick: ", err);
- ko(err);
- }
- });
- }
- function exifDate(value) {
- if (!value)
- return undefined;
- value = value.split(/ /);
- return new Date(value[0].replace(/:/g, '-')+' '+value[1]+' +0000');
- }
- function exifSlash(value) {
- if (!value)
- return undefined;
- if (!(/[0-9]+\/[0-9]+/).test(value))
- return value;
- return eval(value);
- }
- function readTags(data) {
- let result = [];
- if (data['winXP-Keywords']) {
- result = result.concat(Array.from(data["winXP-Keywords"]).filter((a, b) => !(b%2)).slice(0, -1).join("").split(";"));
- }
- return result;
- }
- module.exports.parse = async (fileObj, data) => {
- if (!fileObj.mimeType.startsWith('image/') || data["exifParsed"])
- return {};
- let result = new MetaStruct();
- try {
- let imdata = await readMeta(fileObj.path);
- if (!imdata)
- return {};
- result.artist = imdata.artist || undefined;
- result.setExposureProgram(Number.parseInt(imdata.exposureProgram));
- result.exposureTime = exifSlash(imdata.exposureTime);
- result.exposureTimeStr = imdata.exposureTime || undefined;
- result.dateTime = exifDate(imdata.dateTimeDigitized || imdata.dateTimeOriginal);
- result.fNumber = exifSlash(imdata.fNumber);
- result.focal = exifSlash(imdata.focalLength);
- result.lensModel = imdata.lensModel || undefined;
- result.camera = ((imdata.model || "") + (imdata.model && imdata.make ? " " : "") + (imdata.make || "")) || "";
- result.software = imdata.software || undefined;
- result.iso = Number.parseInt(imdata.photographicSensitivity) || undefined;
- result.width = imdata.width || undefined;
- result.height = imdata.height || undefined;
- result.compression = imdata.compression || undefined;
- result.orientation = imdata.orientation || undefined;
- try {
- result.setGPSInfo(imdata.gPSLatitude.split(',').map(eval), data.gPSLatitudeRef,
- imdata.gPSLongitude.split(',').map(eval), data.gPSLongitudeRef);
- }
- catch (err) {}
- result.tags = readTags(imdata);
- }
- catch (err) {
- result.imException = err;
- }
- for (let i of Object.keys(result))
- if (result[i] === undefined || result[i].length === 0)
- delete result[i];
- return { value: result };
- }
- module.exports.createThumbnail = async (fileObj, width, height, quality) => {
- if (!fileObj?.meta?.width || !fileObj?.meta?.height)
- return null;
- if (!width && !height)
- width = height = 420;
- let ratio = Math.min((width / fileObj.meta.width) || 1, (height / fileObj.meta.height) || 1, 1);
- const output = tmp.fileSync({ discardDescriptor: true });
- try {
- await im.convert([
- fileObj.path,
- '-strip',
- '-interlace', 'Plane',
- '-resize', (Math.floor(fileObj.meta.width * ratio)),
- '-quality', '' + (Math.floor(Math.max(0, Math.min(100, (quality *10))))) + '%',
- '-sampling-factor', '4:2:0',
- `JPG:${output.name}`,
- ]);
- }
- catch (err) {
- console.error("Imagemagick createThumbnail error: ", err);
- throw err;
- }
- return output;
- };
|