diff --git a/README.md b/README.md index 9c8d82ca..be280139 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Backend +## Configuration + Edit the file `backend/run.sh` to change the data directory location - this is where all uploaded media content will be stored. By default this is the folder `.plo` in the home directory -If required edit the port number in `run.sh`. This should match the port number entered in the frontend config. +If required edit the port number in `run.sh`; the default is 8008. This should match the port number entered in the frontend config. * Requires `ffmpeg` and `mongo` to be installed. * Ensure that the mongo data store path is set. This can be done with `mongod --dbpath `. It is recommended to use `/data/db`. @@ -21,13 +23,20 @@ Saves all stored content to `export.zip` Restores all content from a previous export Usage: `./plo-import export.zip` +### `plo-compress-existing` +For existing applications prior to the introduction of image compression. +Compresses existing images in the application to be in line with newer versions. +Usage: `./plo-import export.zip` + # Frontend + +## Configuration Before running this project, create a `.env` file in the frontend directory with the contents: ``` - REACT_APP_BACKEND_PORT_BASE= - REACT_APP_SELF_BACKEND= +REACT_APP_BACKEND_PORT_BASE= +REACT_APP_SELF_BACKEND= ``` * The default backend port number is 8008 (N.B: The backend actually uses two successive ports starting with the given port number). diff --git a/backend/imageProcessing.js b/backend/imageProcessing.js new file mode 100644 index 00000000..1c5f2d73 --- /dev/null +++ b/backend/imageProcessing.js @@ -0,0 +1,62 @@ +const jimp = require('jimp') + +// 16 MP +const MAX_SIZE = 16 * 1000 * 1000 +// 80% Quality +const QUALITY = 75 + +const EPSILON = 0.01 + +function processImage(input, cb, overwrite = true) { + jimp.read(input, (err, img) => { + if (err) { + cb(err) + return + } + const split = input.match(/(.*)\.(.*)/) + const filename = split[1] + const fileExt = split[2] + + const size = img.bitmap.width * img.bitmap.height + + if (size < EPSILON * MAX_SIZE) { + return + } + + const factor = Math.sqrt(MAX_SIZE / size) + img + .scale(factor) + .quality(QUALITY) + .write(filename + (overwrite ? '' : '-processed') + '.' + fileExt) + if (cb) { + cb() + } + }) +} + +async function processImageSync(input, overwrite = true) { + await jimp.read(input) + .then(img => { + const split = input.match(/(.*)\.(.*)/) + const filename = split[1] + const fileExt = split[2] + + const size = img.bitmap.width * img.bitmap.height + + if (size < EPSILON * MAX_SIZE) { + return + } + + const factor = Math.sqrt(MAX_SIZE / size) + return img + .scale(factor) + .quality(QUALITY) + .write(filename + (overwrite ? '' : '-processed') + '.' + fileExt) + }) + .catch(err => console.error(err)) +} + +module.exports = { + processImage, + processImageSync +} diff --git a/backend/index.js b/backend/index.js index 04729d8a..87bad67f 100644 --- a/backend/index.js +++ b/backend/index.js @@ -5,6 +5,7 @@ const fs = require('fs') const multer = require('multer') const mongoManager = require('./mongoManager.js') +const imageProcessing = require('./imageProcessing.js') const app = express() const API_PORT = process.env.PORT_BASE @@ -96,6 +97,8 @@ app.post('/:username/addUserMedia', (req, res) => { // Ensure to wait for addUserMedia to finish await mongoManager.addUserMedia(username, req.files, DATA_DIRECTORY) + await compressImages(req.files) + return res.send("Successfully uploaded " + req.files.length + " " + (req.files.length > 1 ? "files" : "file")) } @@ -116,6 +119,8 @@ app.post('/:username/addUserGallery', (req, res) => { // Ensure to wait for addUserMedia to finish await mongoManager.addUserGallery(username, req.files, DATA_DIRECTORY) + await compressImages(req.files) + return res.send("Successfully uploaded " + req.files.length + " " + (req.files.length > 1 ? "files" : "file") + " to gallery") } @@ -124,6 +129,14 @@ app.post('/:username/addUserGallery', (req, res) => { /*----------------------------------------------------------------------------*/ +async function compressImages(files) { + files = files.map(f => DATA_DIRECTORY + "/" + f.filename) + for (var i = 0; i < files.length; i++) { + const file = files[i] + await imageProcessing.processImageSync(file) + } +} + // Delete files that are no longer being referenced async function garbageCollect() { const allMedia = await mongoManager.getAllMedia() diff --git a/backend/package-lock.json b/backend/package-lock.json index 34f8ad09..ac43f6a7 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -4,6 +4,320 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/runtime": { + "version": "7.8.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.7.tgz", + "integrity": "sha512-+AATMUFppJDw6aiR5NVPHqIQBlV/Pj8wY/EZH+lmvRdUo9xBaz/rF3alAwFJQavvKfeOlPE7oaaDHVbcySbCsg==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@jimp/bmp": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/bmp/-/bmp-0.9.6.tgz", + "integrity": "sha512-T2Fh/k/eN6cDyOx0KQ4y56FMLo8+mKNhBh7GXMQXLK2NNZ0ckpFo3VHDBZ3HnaFeVTZXF/atLiR9CfnXH+rLxA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "bmp-js": "^0.1.0", + "core-js": "^3.4.1" + } + }, + "@jimp/core": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-0.9.6.tgz", + "integrity": "sha512-sQO04S+HZNid68a9ehb4BC2lmW6iZ5JgU9tC+thC2Lhix+N/XKDJcBJ6HevbLgeTzuIAw24C5EKuUeO3C+rE5w==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "any-base": "^1.1.0", + "buffer": "^5.2.0", + "core-js": "^3.4.1", + "exif-parser": "^0.1.12", + "file-type": "^9.0.0", + "load-bmfont": "^1.3.1", + "mkdirp": "^0.5.1", + "phin": "^2.9.1", + "pixelmatch": "^4.0.2", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/custom": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/custom/-/custom-0.9.6.tgz", + "integrity": "sha512-ZYKgrBZVoQwvIGlQSO7MFmn7Jn8a9X5g1g+KOTDO9Q0s4vnxdPTtr/qUjG9QYX6zW/6AK4LaIsDinDrrKDnOag==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/core": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/gif": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/gif/-/gif-0.9.6.tgz", + "integrity": "sha512-Z2muC2On8KHEVrWKCCM0L2eua9kw4bQETzT7gmVsizc8MXAKdS8AyVV9T3ZrImiI0o5UkAN/u0cPi1U2pSiD8Q==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1", + "omggif": "^1.0.9" + } + }, + "@jimp/jpeg": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/jpeg/-/jpeg-0.9.6.tgz", + "integrity": "sha512-igSe0pIX3le/CKdvqW4vLXMxoFjTLjEaW6ZHt/h63OegaEa61TzJ2OM7j7DxrEHcMCMlkhUc9Bapk57MAefCTQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1", + "jpeg-js": "^0.3.4" + } + }, + "@jimp/plugin-blit": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-0.9.6.tgz", + "integrity": "sha512-zp7X6uDU1lCu44RaSY88aAvsSKbgqUrfDyWRX1wsamJvvZpRnp1WekWlGyydRtnlUBAGIpiHCHmyh/TJ2I4RWA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-blur": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-0.9.6.tgz", + "integrity": "sha512-xEi63hvzewUp7kzw+PI3f9CIrgZbphLI4TDDHWNYuS70RvhTuplbR6RMHD/zFhosrANCkJGr5OZJlrJnsCg6ug==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-color": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-0.9.6.tgz", + "integrity": "sha512-o1HSoqBVUUAsWbqSXnpiHU0atKWy/Q1GUbZ3F5GWt/0OSDyl9RWM82V9axT2vePZHInKjIaimhnx1gGj8bfxkQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1", + "tinycolor2": "^1.4.1" + } + }, + "@jimp/plugin-contain": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-0.9.6.tgz", + "integrity": "sha512-Xz467EN1I104yranET4ff1ViVKMtwKLg1uRe8j3b5VOrjtiXpDbjirNZjP3HTlv8IEUreWNz4BK7ZtfHSptufA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-cover": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-0.9.6.tgz", + "integrity": "sha512-Ocr27AvtvH4ZT/9EWZgT3+HQV9fG5njwh2CYMHbdpx09O62Asj6pZ4QI0kKzOcux1oLgv59l7a93pEfMOfkfwQ==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-crop": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-0.9.6.tgz", + "integrity": "sha512-d9rNdmz3+eYLbSKcTyyp+b8Nmhf6HySnimDXlTej4UP6LDtkq2VAyVaJ12fz9x6dfd8qcXOBXMozSfNCcgpXYA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-displace": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-0.9.6.tgz", + "integrity": "sha512-SWpbrxiHmUYBVWtDDMjaG3eRDBASrTPaad7l07t73/+kmU6owAKWQW6KtVs05MYSJgXz7Ggdr0fhEn9AYLH1Rg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-dither": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-0.9.6.tgz", + "integrity": "sha512-abm1GjfYK7ru/PoxH9fAUmhl+meHhGEClbVvjjMMe5g2S0BSTvMJl3SrkQD/FMkRLniaS/Qci6aQhIi+8rZmSw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-flip": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-0.9.6.tgz", + "integrity": "sha512-KFZTzAzQQ5bct3ii7gysOhWrTKVdUOghkkoSzLi+14nO3uS/dxiu8fPeH1m683ligbdnuM/b22OuLwEwrboTHA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-gaussian": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-gaussian/-/plugin-gaussian-0.9.6.tgz", + "integrity": "sha512-WXKLtJKWchXfWHT5HIOq1HkPKpbH7xBLWPgVRxw00NV/6I8v4xT63A7/Nag78m00JgjwwiE7eK2tLGDbbrPYig==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-invert": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-invert/-/plugin-invert-0.9.6.tgz", + "integrity": "sha512-Pab/cupZrYxeRp07N4L5a4C/3ksTN9k6Knm/o2G5C789OF0rYsGGLcnBR/6h69nPizRZHBYdXCEyXYgujlIFiw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-mask": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-0.9.6.tgz", + "integrity": "sha512-ikypRoDJkbxXlo6gW+EZOcTiLDIt0DrPwOFMt1bvL8UV2QPgX+GJ685IYwhIfEhBf/GSNFgB/NYsVvuSufTGeg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-normalize": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-normalize/-/plugin-normalize-0.9.6.tgz", + "integrity": "sha512-V3GeuAJ1NeL7qsLoDjnypJq24RWDCwbXpKhtxB+Yg9zzgOCkmb041p7ysxbcpkuJsRpKLNABZeNCCqd83bRawA==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-print": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-0.9.6.tgz", + "integrity": "sha512-gKkqZZPQtMSufHOL0mtJm5d/KI2O6+0kUpOBVSYdGedtPXA61kmVnsOd3wwajIMlXA3E0bDxLXLdAguWqjjGgw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1", + "load-bmfont": "^1.4.0" + } + }, + "@jimp/plugin-resize": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-0.9.6.tgz", + "integrity": "sha512-r5wJcVII7ZWMuY2l6WSbHPG6gKMFemtCHmJRXGUu+/ZhPGBz3IFluycBpHkWW3OB+jfvuyv1EGQWHU50N1l8Og==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-rotate": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-0.9.6.tgz", + "integrity": "sha512-B2nm/eO2nbvn1DgmnzMd79yt3V6kffhRNrKoo2VKcKFiVze1vGP3MD3fVyw5U1PeqwAFu7oTICFnCf9wKDWSqg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugin-scale": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugin-scale/-/plugin-scale-0.9.6.tgz", + "integrity": "sha512-DLsLB5S3mh9+TZY5ycwfLgOJvUcoS7bP0Mi3I8vE1J91qmA+TXoWFFgrIVgnEPw5jSKzNTt8WhykQ0x2lKXncw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1" + } + }, + "@jimp/plugins": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/plugins/-/plugins-0.9.6.tgz", + "integrity": "sha512-eQI29e+K+3L/fb5GbPgsBdoftvaYetSOO2RL5z+Gjk6R4EF4QFRo63YcFl+f72Kc1b0JTOoDxClvn/s5GMV0tg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/plugin-blit": "^0.9.6", + "@jimp/plugin-blur": "^0.9.6", + "@jimp/plugin-color": "^0.9.6", + "@jimp/plugin-contain": "^0.9.6", + "@jimp/plugin-cover": "^0.9.6", + "@jimp/plugin-crop": "^0.9.6", + "@jimp/plugin-displace": "^0.9.6", + "@jimp/plugin-dither": "^0.9.6", + "@jimp/plugin-flip": "^0.9.6", + "@jimp/plugin-gaussian": "^0.9.6", + "@jimp/plugin-invert": "^0.9.6", + "@jimp/plugin-mask": "^0.9.6", + "@jimp/plugin-normalize": "^0.9.6", + "@jimp/plugin-print": "^0.9.6", + "@jimp/plugin-resize": "^0.9.6", + "@jimp/plugin-rotate": "^0.9.6", + "@jimp/plugin-scale": "^0.9.6", + "core-js": "^3.4.1", + "timm": "^1.6.1" + } + }, + "@jimp/png": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/png/-/png-0.9.6.tgz", + "integrity": "sha512-9vhOG2xylcDqPbBf4lzpa2Sa1WNJrEZNGvPvWcM+XVhqYa8+DJBLYkoBlpI/qWIYA+eVWDnLF3ygtGj8CElICw==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/utils": "^0.9.6", + "core-js": "^3.4.1", + "pngjs": "^3.3.3" + } + }, + "@jimp/tiff": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/tiff/-/tiff-0.9.6.tgz", + "integrity": "sha512-pKKEMqPzX9ak8mek2iVVoW34+h/TSWUyI4NjbYWJMQ2WExfuvEJvLocy9Q9xi6HqRuJmUxgNIiC5iZM1PDEEfg==", + "requires": { + "@babel/runtime": "^7.7.2", + "core-js": "^3.4.1", + "utif": "^2.0.1" + } + }, + "@jimp/types": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-0.9.6.tgz", + "integrity": "sha512-PSjdbLZ8d50En+Wf1XkWFfrXaf/GqyrxxgIwFWPbL+wrW4pmbYovfxSLCY61s8INsOFOft9dzzllhLBtg1aQ6A==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/bmp": "^0.9.6", + "@jimp/gif": "^0.9.6", + "@jimp/jpeg": "^0.9.6", + "@jimp/png": "^0.9.6", + "@jimp/tiff": "^0.9.6", + "core-js": "^3.4.1", + "timm": "^1.6.1" + } + }, + "@jimp/utils": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-0.9.6.tgz", + "integrity": "sha512-kzxcp0i4ecSdMXFEmtH+NYdBQysINEUTsrjm7v0zH8t/uwaEMOG46I16wo/iPBXJkUeNdL2rbXoGoxxoeSfrrA==", + "requires": { + "@babel/runtime": "^7.7.2", + "core-js": "^3.4.1" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -39,6 +353,11 @@ "color-convert": "^1.9.0" } }, + "any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==" + }, "anymatch": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", @@ -89,6 +408,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, "basic-auth": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-1.1.0.tgz", @@ -142,6 +466,11 @@ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.0.tgz", "integrity": "sha1-eRQg1/VR7qKJdFOop3ZT+WYG1nw=" }, + "bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha1-4Fpj95amwf8l9Hcex62twUjAcjM=" + }, "body-parser": { "version": "1.19.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", @@ -195,6 +524,20 @@ "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz", "integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg==" }, + "buffer": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.5.0.tgz", + "integrity": "sha512-9FTEDjLjwoAkEwyMGDjYJQN2gfRgOKBKRfiglhvibGbpeeU/pQn1bJxQqm32OD/AIeEuHxU9roxXxg34Byp/Ww==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-equal": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz", + "integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=" + }, "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", @@ -358,6 +701,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "core-js": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==" + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -458,6 +806,11 @@ "streamsearch": "0.1.2" } }, + "dom-walk": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz", + "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=" + }, "dot-prop": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", @@ -526,6 +879,11 @@ "strip-eof": "^1.0.0" } }, + "exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=" + }, "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", @@ -563,6 +921,11 @@ "vary": "~1.1.2" } }, + "file-type": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-9.0.0.tgz", + "integrity": "sha512-Qe/5NJrgIOlwijpq3B7BEpzPFcgzggOTagZmkXQY4LA6bsXKTUstK7Wp12lEJ/mLKTpvIZxmIuRcLYWT6ov9lw==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -664,6 +1027,15 @@ "is-glob": "^4.0.1" } }, + "global": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/global/-/global-4.3.2.tgz", + "integrity": "sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=", + "requires": { + "min-document": "^2.19.0", + "process": "~0.5.1" + } + }, "global-dirs": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", @@ -772,6 +1144,11 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", @@ -837,6 +1214,11 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-function": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.1.tgz", + "integrity": "sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=" + }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", @@ -915,6 +1297,24 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, + "jimp": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-0.9.6.tgz", + "integrity": "sha512-DBDHYeNVqVpoPkcvo0PKTNGvD+i7NYvkKTsl0I3k7ql36uN8wGTptRg0HtgQyYE/bhGSLI6Lq5qLwewaOPXNfg==", + "requires": { + "@babel/runtime": "^7.7.2", + "@jimp/custom": "^0.9.6", + "@jimp/plugins": "^0.9.6", + "@jimp/types": "^0.9.6", + "core-js": "^3.4.1", + "regenerator-runtime": "^0.13.3" + } + }, + "jpeg-js": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.3.7.tgz", + "integrity": "sha512-9IXdWudL61npZjvLuVe/ktHiA41iE8qFyLB+4VDTblEsWBzeg8WQTlktdUK4CdncUqtUgUg0bbOmTE2bKBKaBQ==" + }, "latest-version": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", @@ -923,6 +1323,21 @@ "package-json": "^4.0.0" } }, + "load-bmfont": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.0.tgz", + "integrity": "sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g==", + "requires": { + "buffer-equal": "0.0.1", + "mime": "^1.3.4", + "parse-bmfont-ascii": "^1.0.3", + "parse-bmfont-binary": "^1.0.5", + "parse-bmfont-xml": "^1.1.4", + "phin": "^2.9.1", + "xhr": "^2.0.1", + "xtend": "^4.0.0" + } + }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", @@ -989,6 +1404,14 @@ "mime-db": "1.42.0" } }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "requires": { + "dom-walk": "^0.1.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1118,6 +1541,11 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, + "omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==" + }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -1171,6 +1599,35 @@ "semver": "^5.1.0" } }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=" + }, + "parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=" + }, + "parse-bmfont-xml": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz", + "integrity": "sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==", + "requires": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.4.5" + } + }, + "parse-headers": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.3.tgz", + "integrity": "sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1196,6 +1653,11 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, + "phin": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/phin/-/phin-2.9.3.tgz", + "integrity": "sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==" + }, "picomatch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.1.tgz", @@ -1219,6 +1681,19 @@ "pinkie": "^2.0.0" } }, + "pixelmatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-4.0.2.tgz", + "integrity": "sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=", + "requires": { + "pngjs": "^3.0.0" + } + }, + "pngjs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz", + "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==" + }, "portfinder": { "version": "1.0.25", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", @@ -1249,6 +1724,11 @@ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" }, + "process": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/process/-/process-0.5.2.tgz", + "integrity": "sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1324,6 +1804,11 @@ "picomatch": "^2.0.7" } }, + "regenerator-runtime": { + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==" + }, "registry-auth-token": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", @@ -1387,6 +1872,11 @@ "sparse-bitfield": "^3.0.3" } }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, "secure-compare": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", @@ -1538,6 +2028,16 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" }, + "timm": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/timm/-/timm-1.6.2.tgz", + "integrity": "sha512-IH3DYDL1wMUwmIlVmMrmesw5lZD6N+ZOAFWEyLrtpoL9Bcrs9u7M/vyOnHzDD2SMs4irLkVjqxZbHrXStS/Nmw==" + }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1637,6 +2137,14 @@ "prepend-http": "^1.0.1" } }, + "utif": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/utif/-/utif-2.0.1.tgz", + "integrity": "sha512-Z/S1fNKCicQTf375lIP9G8Sa1H/phcysstNrrSdZKj1f9g58J4NMgb5IgiEZN9/nLMPDwF0W7hdOe9Qq2IYoLg==", + "requires": { + "pako": "^1.0.5" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -1712,6 +2220,36 @@ "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" }, + "xhr": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.5.0.tgz", + "integrity": "sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==", + "requires": { + "global": "~4.3.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha1-qQKekp09vN7RafPG4oI42VpdWig=" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + } + }, + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/backend/package.json b/backend/package.json index 538c7150..6ef03250 100644 --- a/backend/package.json +++ b/backend/package.json @@ -14,6 +14,7 @@ "cors": "^2.8.5", "express": "^4.17.1", "http-server": "^0.12.1", + "jimp": "^0.9.6", "mongodb": "^3.5.5", "multer": "^1.4.2", "nodemon": "^2.0.2", diff --git a/backend/plo-compress-existing.sh b/backend/plo-compress-existing.sh new file mode 100755 index 00000000..78c0deb1 --- /dev/null +++ b/backend/plo-compress-existing.sh @@ -0,0 +1 @@ +bash run.sh --compress-existing diff --git a/backend/plo-export.sh b/backend/plo-export.sh old mode 100644 new mode 100755 diff --git a/backend/plo-import.sh b/backend/plo-import.sh old mode 100644 new mode 100755 diff --git a/backend/processAll.js b/backend/processAll.js new file mode 100644 index 00000000..376d2e9b --- /dev/null +++ b/backend/processAll.js @@ -0,0 +1,31 @@ +const fs = require('fs') +const imageProcessing = require('./imageProcessing.js') + +const NUM_HASHES = 50 + +const args = process.argv.slice(2) + +if (args.length != 1) { + console.log('Usage: plo-compress-existing ') + process.exit(1) +} + +const directory = args[0] + +try { + const files = fs.readdirSync(directory) + + var count = 0 + for (var i = 0; i < files.length; i++) { + const file = files[i] + + imageProcessing.processImage(directory + '/' + file, err => { + const outOf = ++count * NUM_HASHES / files.length + + console.log((err ? 'Could not process ' : 'Processed: ') + file + ' '.repeat(NUM_HASHES)) + process.stdout.write('[' + '#'.repeat(Math.ceil(outOf)) + ' '.repeat(Math.floor(NUM_HASHES - outOf)) + '] ' + Math.ceil(outOf / NUM_HASHES * 100) +'%\r') + }, true) + } +} catch (err) { + console.error('Could not read directory: ' + directory) +} diff --git a/backend/run.sh b/backend/run.sh index 08792a20..5cf51ce7 100755 --- a/backend/run.sh +++ b/backend/run.sh @@ -59,5 +59,19 @@ if [ $1 == "--import" ]; then fi +# Compress Existing +if [ $1 == "--compress-existing" ]; then + + if [ -d "$DATA_DIRECTORY" ]; then + node processAll.js "$DATA_DIRECTORY"; + exit $?; + else + echo "$DATA_DIRECTORY not found"; + exit 1; + fi + +fi + + # Default run bash ./serveData.sh & nodemon index.js &