Updated thumbnail creation to create a scaled version
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
baf152d57c
commit
e9fd50a054
@ -151,7 +151,7 @@ Polymer({
|
|||||||
download: function(event) {
|
download: function(event) {
|
||||||
console.log("Download tapped");
|
console.log("Download tapped");
|
||||||
var anchor = document.createElement('a');
|
var anchor = document.createElement('a');
|
||||||
anchor.href = this.src;
|
anchor.href = this.base + this.item.path + "/" + this.item.filename;
|
||||||
anchor.setAttribute("download", this.src.replace(/.*\/([^/]+)$/, "$1"));
|
anchor.setAttribute("download", this.src.replace(/.*\/([^/]+)$/, "$1"));
|
||||||
anchor.style.display = "none";
|
anchor.style.display = "none";
|
||||||
document.body.appendChild(anchor);
|
document.body.appendChild(anchor);
|
||||||
@ -233,6 +233,12 @@ Polymer({
|
|||||||
},
|
},
|
||||||
|
|
||||||
attached: function() {
|
attached: function() {
|
||||||
|
var base = document.querySelector("base");
|
||||||
|
if (base) {
|
||||||
|
this.base = new URL(base.href).pathname.replace(/\/$/, ""); /* Remove trailing slash if there */
|
||||||
|
} else {
|
||||||
|
this.base = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -876,7 +876,8 @@
|
|||||||
this.lightBoxElement.selected = false;
|
this.lightBoxElement.selected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$.lightbox.src = this.base + el.item.path + "/" + el.item.filename;
|
this.$.lightbox.item = el.item;
|
||||||
|
this.$.lightbox.src = this.base + el.item.path + "/thumbs/scaled/" + el.item.filename;
|
||||||
this.lightBoxElement = el;
|
this.lightBoxElement = el;
|
||||||
this.lightBoxElement.selected = true;
|
this.lightBoxElement.selected = true;
|
||||||
this.disableScrolling = true;
|
this.disableScrolling = true;
|
||||||
|
@ -71,112 +71,83 @@ function scanDir(parent, path) {
|
|||||||
}
|
}
|
||||||
}).then(function(parent) {
|
}).then(function(parent) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
console.log("Scanning " + replacements.path);
|
console.log("Scanning ..." + replacements.path);
|
||||||
|
|
||||||
fs.readdir(path, function(err, files) {
|
fs.readdir(path, function(err, files) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.warn(" Could not readdir " + path);
|
console.warn("Could not readdir " + path);
|
||||||
return resolve(null);
|
return resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
scanning++;
|
return resolve(files);
|
||||||
|
});
|
||||||
|
}).then(function(files) {
|
||||||
|
scanning++;
|
||||||
|
|
||||||
let hasThumbs = false;
|
/* Remove 'thumbs' and 'raw' directories from being processed */
|
||||||
for (let i = 0; i < files.length; i++) {
|
files = files.filter(function(file) {
|
||||||
if (files[i] == "thumbs") {
|
for (var i = 0; i < files.length; i++) {
|
||||||
hasThumbs = true;
|
/* If this file has an original NEF/ORF on the system, don't add the JPG to the DB */
|
||||||
break;
|
if (rawExtension.exec(files[i]) && file == files[i].replace(rawExtension, ".jpg")) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let tmp;
|
|
||||||
if (!hasThumbs) {
|
|
||||||
tmp = mkdirPromise(path + "/thumbs");
|
|
||||||
} else {
|
|
||||||
tmp = Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove 'thumbs' and 'raw' directories from being processed */
|
|
||||||
files = files.filter(function(file) {
|
|
||||||
for (var i = 0; i < files.length; i++) {
|
|
||||||
/* If this file has an original NEF/ORF on the system, don't add the JPG to the DB */
|
|
||||||
if (rawExtension.exec(files[i]) && file == files[i].replace(rawExtension, ".jpg")) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is a different CASE (eg. JPG vs jpg) don't add it, and remove the 'lower case'
|
|
||||||
* version from disk. */
|
|
||||||
if (file != files[i] && file.toUpperCase() == files[i]) {
|
|
||||||
removeNewerFile(path, file, files[i]);
|
|
||||||
console.log("Duplicate file in " + path + ": ", file, files[i]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return file != "raw" && file != "thumbs" && file != ".git" && file != "corrupt";
|
|
||||||
});
|
|
||||||
|
|
||||||
return tmp.then(function() {
|
|
||||||
return Promise.map(files, function(file) {
|
|
||||||
let filepath = path + "/" + file;
|
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
|
||||||
fs.stat(filepath, function(err, stats) {
|
|
||||||
if (err) {
|
|
||||||
console.warn("Could not stat " + filepath);
|
|
||||||
return resolve(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.isDirectory()) {
|
|
||||||
return scanDir(parent, filepath, stats).then(function(entry) {
|
|
||||||
return resolve(true);
|
|
||||||
}).catch(function(error) {
|
|
||||||
console.warn("scanDir failed");
|
|
||||||
return reject(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check file extensions */
|
|
||||||
if (!re.exec(file)) {
|
|
||||||
return resolve(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* If there is a different CASE (eg. JPG vs jpg) don't add it, and remove the 'lower case'
|
||||||
|
* version from disk. */
|
||||||
|
if (file != files[i] && file.toUpperCase() == files[i]) {
|
||||||
|
removeNewerFile(path, file, files[i]);
|
||||||
|
console.log("Duplicate file in " + path + ": ", file, files[i]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const replacements = {
|
return file != "raw" && file != "thumbs" && file != ".git" && file != "corrupt";
|
||||||
path: path.slice(picturesPath.length),
|
});
|
||||||
filename: file.replace(rawExtension, ".jpg") /* We will be converting from NEF/ORF => JPG */
|
|
||||||
};
|
|
||||||
|
|
||||||
replacements.path = replacements.path || "/";
|
return mkdir(path + "/thumbs/scaled").then(function() {
|
||||||
|
return Promise.map(files, function(file) {
|
||||||
|
let filepath = path + "/" + file;
|
||||||
|
|
||||||
return photoDB.sequelize.query("SELECT id FROM photos WHERE path=:path AND filename=:filename", {
|
return stat(filepath).then(function(stats) {
|
||||||
replacements: replacements,
|
if (stats.isDirectory()) {
|
||||||
type: photoDB.sequelize.QueryTypes.SELECT
|
return scanDir(parent, filepath).catch(function(error) {
|
||||||
}).then(function(photo) {
|
console.warn("Could not scanDir " + filepath + ": " + error);
|
||||||
if (photo.length == 0) {
|
|
||||||
processQueue.push([ replacements.path, file, stats.mtime, parent ]);
|
|
||||||
}
|
|
||||||
return resolve(true);
|
|
||||||
}).catch(function(error) {
|
|
||||||
console.error("Sequelize.query failed");
|
|
||||||
return reject(error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}, {
|
|
||||||
concurrency: 1
|
|
||||||
}).then(function() {
|
|
||||||
scanning--;
|
|
||||||
if (scanning == 0) {
|
|
||||||
const endStamp = Date.now();
|
|
||||||
console.log("Scanning completed in " + Math.round(((endStamp - startStamp))) + "ms. " + processQueue.length + " items to process.");
|
|
||||||
}
|
}
|
||||||
}).then(function() {
|
|
||||||
return resolve();
|
/* Check file extensions */
|
||||||
|
if (!re.exec(file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacements = {
|
||||||
|
path: path.slice(picturesPath.length),
|
||||||
|
filename: file.replace(rawExtension, ".jpg") /* We will be converting from NEF/ORF => JPG */
|
||||||
|
};
|
||||||
|
|
||||||
|
replacements.path = replacements.path || "/";
|
||||||
|
|
||||||
|
return photoDB.sequelize.query("SELECT id FROM photos WHERE path=:path AND filename=:filename", {
|
||||||
|
replacements: replacements,
|
||||||
|
type: photoDB.sequelize.QueryTypes.SELECT
|
||||||
|
}).then(function(photo) {
|
||||||
|
if (photo.length == 0) {
|
||||||
|
processQueue.push([ replacements.path, file, stats.mtime, parent ]);
|
||||||
|
}
|
||||||
|
}).catch(function(error) {
|
||||||
|
console.error("Sequelize.query failed: ", error);
|
||||||
|
});
|
||||||
|
}).catch(function(error) {
|
||||||
|
console.warn("Could not stat " + filepath + ": " + error);
|
||||||
});
|
});
|
||||||
}).catch(function(error) {
|
}, {
|
||||||
console.error("Processing 'tmp' failed");
|
concurrency: 1
|
||||||
return reject(error);
|
}).then(function() {
|
||||||
|
scanning--;
|
||||||
|
if (scanning == 0) {
|
||||||
|
const endStamp = Date.now();
|
||||||
|
console.log("Scanning completed in " + Math.round(((endStamp - startStamp))) + "ms. " + processQueue.length + " items to process.");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -190,44 +161,59 @@ let processRunning = false;
|
|||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
|
|
||||||
const sharp = require("sharp"), exif = require("exif-reader");
|
const sharp = require("sharp"), exif = require("exif-reader");
|
||||||
|
const stat = function (path) {
|
||||||
function mkdirPromise(path) {
|
|
||||||
if (path.indexOf(picturesPath) != 0) {
|
if (path.indexOf(picturesPath) != 0) {
|
||||||
path = picturesPath + path;
|
path = picturesPath + path;
|
||||||
}
|
}
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
fs.stat(path, function(err) {
|
fs.stat(path, function (error, stats) {
|
||||||
if (err && err.code != 'ENOENT') {
|
if (error) {
|
||||||
console.warn("Could not stat " + path);
|
return reject(error);
|
||||||
return reject();
|
}
|
||||||
|
return resolve(stats);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const mkdir = function (_path) {
|
||||||
|
if (_path.indexOf(picturesPath) == 0) {
|
||||||
|
_path = _path.substring(picturesPath.length + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parts = _path.split("/"), path;
|
||||||
|
parts.unshift(picturesPath);
|
||||||
|
return Promise.mapSeries(parts, function (part) {
|
||||||
|
if (!path) {
|
||||||
|
path = picturesPath;
|
||||||
|
} else {
|
||||||
|
path += "/" + part;
|
||||||
|
}
|
||||||
|
return stat(path).catch(function (error) {
|
||||||
|
if (error.code != "ENOENT") {
|
||||||
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err) {
|
return new Promise(function (resolve, reject) {
|
||||||
return resolve();
|
console.log("mkdir " + path);
|
||||||
}
|
fs.mkdir(path, function (error) {
|
||||||
|
if (error) {
|
||||||
|
return reject(error);
|
||||||
|
}
|
||||||
|
|
||||||
fs.mkdir(path, function(err) {
|
return resolve();
|
||||||
if (err && err.code != 'EEXIST') {
|
});
|
||||||
return reject("Unable to create " + path + "\n" + err);
|
|
||||||
}
|
|
||||||
return resolve();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function existsPromise(path) {
|
|
||||||
return new Promise(function(resolve, reject) {
|
const exists = function(path) {
|
||||||
fs.stat(path, function(err, stats) {
|
return stat(path).then(function() {
|
||||||
if (!err) {
|
return true;
|
||||||
return resolve(true);
|
}).catch(function() {
|
||||||
}
|
return false;
|
||||||
if (err.code == 'ENOENT') {
|
});
|
||||||
return resolve(false);
|
|
||||||
}
|
|
||||||
return reject(err);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertRawToJpg(path, file) {
|
function convertRawToJpg(path, file) {
|
||||||
@ -236,10 +222,10 @@ function convertRawToJpg(path, file) {
|
|||||||
path = picturesPath + path;
|
path = picturesPath + path;
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
fs.stat(path + "/" + file.replace(rawExtension, ".jpg"), function(err, stats) {
|
return exists(path + "/" + file.replace(rawExtension, ".jpg")).then(function(exist) {
|
||||||
if (!err) {
|
if (exist) {
|
||||||
console.log("Skipping already converted file: " + file);
|
console.log("Skipping already converted file: " + file);
|
||||||
return resolve();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ufraw = spawn("ufraw-batch", [
|
const ufraw = spawn("ufraw-batch", [
|
||||||
@ -259,30 +245,32 @@ function convertRawToJpg(path, file) {
|
|||||||
stderr.push(data);
|
stderr.push(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
ufraw.on('exit', function(stderr, code, signal) {
|
return new Promise(function(ufraw, resolve, reject) {
|
||||||
if (signal || code != 0) {
|
ufraw.on('exit', function(stderr, code, signal) {
|
||||||
let error = "UFRAW for " + path + "/" + file + " returned an error: " + code + "\n" + signal + "\n" + stderr.join("\n") + "\n";
|
if (signal || code != 0) {
|
||||||
console.error(error);
|
let error = "UFRAW for " + path + "/" + file + " returned an error: " + code + "\n" + signal + "\n" + stderr.join("\n") + "\n";
|
||||||
return moveCorrupt(path, file).then(function() {
|
console.error(error);
|
||||||
console.warn("ufraw failed");
|
return moveCorrupt(path, file).then(function() {
|
||||||
return reject(error);
|
console.warn("ufraw failed");
|
||||||
|
return reject(error);
|
||||||
|
}).catch(function(error) {
|
||||||
|
console.warn("moveCorrupt failed");
|
||||||
|
return reject(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return mkdir(path + "/raw").then(function() {
|
||||||
|
fs.rename(path + "/" + file, path + "/raw/" + file, function(err) {
|
||||||
|
if (err) {
|
||||||
|
console.error("Unable to move RAW file: " + path + "/" + file);
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
console.warn("moveCorrupt failed");
|
console.warn("mkdir failed");
|
||||||
return reject(error);
|
return reject(error);
|
||||||
});
|
});
|
||||||
}
|
}.bind(this, ufraw));
|
||||||
return mkdirPromise(path + "/raw").then(function() {
|
|
||||||
fs.rename(path + "/" + file, path + "/raw/" + file, function(err) {
|
|
||||||
if (err) {
|
|
||||||
console.error("Unable to move RAW file: " + path + "/" + file);
|
|
||||||
return reject(err);
|
|
||||||
}
|
|
||||||
return resolve();
|
|
||||||
});
|
|
||||||
}).catch(function(error) {
|
|
||||||
console.warn("mkdirPromise failed");
|
|
||||||
return reject(error);
|
|
||||||
});
|
|
||||||
}.bind(this, stderr));
|
}.bind(this, stderr));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -295,7 +283,7 @@ function moveCorrupt(path, file) {
|
|||||||
|
|
||||||
console.warn("Moving corrupt file '" + file + "' to " + path + "/corrupt");
|
console.warn("Moving corrupt file '" + file + "' to " + path + "/corrupt");
|
||||||
|
|
||||||
return mkdirPromise(path + "/corrupt").then(function() {
|
return mkdir(path + "/corrupt").then(function() {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
fs.rename(path + "/" + file, path + "/corrupt/" + file, function(err) {
|
fs.rename(path + "/" + file, path + "/corrupt/" + file, function(err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -323,17 +311,15 @@ function triggerWatcher() {
|
|||||||
return Promise.map(processing, function(entry) {
|
return Promise.map(processing, function(entry) {
|
||||||
var path = entry[0], file = entry[1], created = entry[2], albumId = entry[3];
|
var path = entry[0], file = entry[1], created = entry[2], albumId = entry[3];
|
||||||
|
|
||||||
// console.log("Processing " + src);
|
|
||||||
|
|
||||||
let tmp = Promise.resolve(file);
|
let tmp = Promise.resolve(file);
|
||||||
/* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */
|
/* If this is a Nikon RAW file, convert it to JPG and move to /raw dir */
|
||||||
if (rawExtension.exec(file)) {
|
if (rawExtension.exec(file)) {
|
||||||
tmp = existsPromise(picturesPath + path + "/" + file.replace(rawExtension, ".jpg")).then(function(exists) {
|
tmp = exists(picturesPath + path + "/" + file.replace(rawExtension, ".jpg")).then(function(exist) {
|
||||||
if (exists) {
|
if (exist) {
|
||||||
return file.replace(rawExtension, ".jpg"); /* We converted from NEF/ORF => JPG */
|
return file.replace(rawExtension, ".jpg"); /* We converted from NEF/ORF => JPG */
|
||||||
}
|
}
|
||||||
|
|
||||||
return mkdirPromise(picturesPath + path + "/raw").then(function() {
|
return mkdir(picturesPath + path + "/raw").then(function() {
|
||||||
return convertRawToJpg(path, file);
|
return convertRawToJpg(path, file);
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
return file.replace(rawExtension, ".jpg"); /* We converted from NEF/ORF => JPG */
|
return file.replace(rawExtension, ".jpg"); /* We converted from NEF/ORF => JPG */
|
||||||
@ -343,7 +329,6 @@ function triggerWatcher() {
|
|||||||
|
|
||||||
return tmp.then(function(file) {
|
return tmp.then(function(file) {
|
||||||
var src = picturesPath + path + "/" + file,
|
var src = picturesPath + path + "/" + file,
|
||||||
dst = picturesPath + path + "/thumbs/" + file,
|
|
||||||
image = sharp(src);
|
image = sharp(src);
|
||||||
|
|
||||||
return image.limitInputPixels(1073741824).metadata().then(function(metadata) {
|
return image.limitInputPixels(1073741824).metadata().then(function(metadata) {
|
||||||
@ -407,24 +392,35 @@ function triggerWatcher() {
|
|||||||
replacements.taken = replacements.modified = date;
|
replacements.taken = replacements.modified = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
return existsPromise(dst).then(function(exists) {
|
let dst = picturesPath + path + "/thumbs/" + file;
|
||||||
let resize;
|
|
||||||
if (!exists) {
|
return exists(dst).then(function(exist) {
|
||||||
resize = image.resize(256, 256).toFile(dst);
|
if (exist) {
|
||||||
} else {
|
return;
|
||||||
resize = Promise.resolve();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resize.then(function() {
|
return image.resize(256, 256).toFile(dst).catch(function(error) {
|
||||||
return photoDB.sequelize.query("INSERT INTO photos " +
|
console.error("Error resizing image: " + dst, error);
|
||||||
"(albumId,path,filename,added,modified,taken,width,height,name)" +
|
|
||||||
"VALUES(:albumId,:path,:filename,DATETIME(:added),DATETIME(:modified),DATETIME(:taken),:width,:height,:name)", {
|
|
||||||
replacements: replacements
|
|
||||||
});
|
|
||||||
}).catch(function(error) {
|
|
||||||
console.error("Error resizing image, writing to disc, or updating DB: " + src, error);
|
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
}).then(function() {
|
||||||
|
let dst = picturesPath + path + "/thumbs/scaled/" + file;
|
||||||
|
return exists(dst).then(function(exist) {
|
||||||
|
if (exist) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return image.resize(Math.min(1024, metadata.width)).toFile(dst).catch(function(error) {
|
||||||
|
console.error("Error resizing image: " + dst, error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}).then(function() {
|
||||||
|
return photoDB.sequelize.query("INSERT INTO photos " +
|
||||||
|
"(albumId,path,filename,added,modified,taken,width,height,name)" +
|
||||||
|
"VALUES(:albumId,:path,:filename,DATETIME(:added),DATETIME(:modified),DATETIME(:taken),:width,:height,:name)", {
|
||||||
|
replacements: replacements
|
||||||
|
});
|
||||||
}).then(function() {
|
}).then(function() {
|
||||||
toProcess--;
|
toProcess--;
|
||||||
if (moment().add(-5, 'seconds') > lastMessage) {
|
if (moment().add(-5, 'seconds') > lastMessage) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user