1+ var gm = require('gm');
2+ var fs = require('fs');
3+ var path = require('path');
4+ var sharp = require('sharp');
5+ var filequeue = require('filequeue');
6+ var imagesize = require('imagesize');
7+ var express = require('express')
8+ var config = require('./config');
9+ var pjson = require('./package.json');
10+
11+ var fq = new filequeue(200);
12+ var app = express();
13+ var highestImageId = 0;
14+ try {
15+ var images = require('./images.json');
16+ } catch (e) {
17+ var images = [];
18+ }
19+ if (images.length != 0) {
20+ highestImageId = images.length;
21+ }
22+
23+ var checkParameters = function (params, callback) {
24+ if (!params.width || !params.height || isNaN(parseInt(params.width)) || isNaN(parseInt(params.height))) {
25+ return callback(true, 400, 'Invalid arguments');
26+ }
27+ if (params.width > config.max_height || params.height > config.max_width) {
28+ return callback(true, 413, 'Specified dimensions too large');
29+ }
30+ callback(false);
31+ }
32+
33+ var displayError = function (res, code, message) {
34+ res.status(code);
35+ res.send({ error: message });
36+ }
37+
38+ var findMatchingImage = function (id, callback) {
39+ var matchingImages = images.filter(function (image) { return image.id == id; });
40+ if (matchingImages.length == 0) {
41+ return callback(true);
42+ }
43+ callback(null, matchingImages[0].filename);
44+ }
45+
46+ var getDestination = function (width, height, filePath, prefix) {
47+ return 'cache/' + prefix + path.basename(filePath, path.extname(filePath)) + '-' + width + 'x' + height + path.extname(filePath);
48+ }
49+
50+ var getShortDestination = function (width, height, filePath, prefix) {
51+ return 'cache/' + prefix + width + '^' + height + path.extname(filePath);
52+ }
53+
54+ var getAndCheckDestination = function (width, height, filePath, prefix, shortName, callback) {
55+ var destination = shortName ? getShortDestination(width, height, filePath, prefix) : getDestination(width, height, filePath, prefix);
56+ fs.exists(destination, function (exists) {
57+ callback(exists, destination);
58+ })
59+ }
60+
61+ var imageResize = function (width, height, filePath, destination, callback) {
62+ try {
63+ sharp(filePath).rotate().resize(width, height).crop().progressive().toFile(destination, function (err) {
64+ callback(err, destination);
65+ });
66+ } catch (e) {
67+ callback(e, null);
68+ }
69+ }
70+
71+ var getProcessedImage = function (width, height, filePath, shortName, callback) {
72+ getAndCheckDestination(width, height, filePath, '', shortName, function (exists, destination) {
73+ if (exists) {
74+ return callback(null, destination);
75+ }
76+ imageResize(width, height, filePath, destination, function (err, destination) {
77+ if (err) {
78+ return callback(err);
79+ }
80+ callback(null, destination);
81+ })
82+ })
83+ }
84+
85+ var getProcessedGrayImage = function (width, height, filePath, shortName, callback) {
86+ getAndCheckDestination(width, height, filePath, 'gray-', shortName, function (exists, destination) {
87+ if (exists) {
88+ return callback(null, destination);
89+ }
90+ imageResize(width, height, filePath, destination, function (err, destination) {
91+ if (err) {
92+ return callback(err);
93+ }
94+ gm(destination).colorspace('GRAY').write(destination, function (err) {
95+ if (err) {
96+ return callback(err);
97+ }
98+ callback(null, destination);
99+ })
100+ })
101+ })
102+ }
103+
104+ var endsWith = function (str, suffix) {
105+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
106+ }
107+
108+ var scanDirectory = function (dir, done) {
109+ var results = [];
110+ fs.readdir(dir, function (err, list) {
111+ if (err) {
112+ return done(err);
113+ }
114+ var pending = list.length;
115+ if (!pending) {
116+ return done (null, results);
117+ }
118+ list.forEach(function (file) {
119+ file = path.resolve(dir, file);
120+ fs.stat(file, function (err, stat) {
121+ if (stat && stat.isFile() && !endsWith(file, '.DS_Store')) {
122+ results.push(file);
123+ }
124+ if (!--pending) done(null, results);
125+ });
126+ });
127+ });
128+ };
129+
130+ var imageScan = function () {
131+ scanDirectory(config.folder_path, function (err, results) {
132+ if (err) throw err;
133+ var filteredResults = results.filter(function (filename) {
134+ return images.filter(function (image) { return image.filename == filename; }) == 0;
135+ });
136+ var left = filteredResults.length;
137+ filteredResults.forEach(function (filename) {
138+ var rs = fq.createReadStream(filename);
139+ imagesize(rs, function (err, result) {
140+ if (err) {
141+ return console.log(err);
142+ }
143+
144+ console.log(filename);
145+
146+ result.filename = filename;
147+ result.id = highestImageId++;
148+ images.push(result);
149+
150+ if (!--left) {
151+ fs.writeFile('images.json', JSON.stringify(images), 'utf8', function (err) {});
152+ }
153+ });
154+ });
155+ });
156+ }
157+
158+ app.get('/', function (req, res, next) {
159+ res.sendFile('public/index.html', { root: '.'} );
160+ })
161+
162+ app.get('/list', function (req, res, next) {
163+ var newImages = [];
164+ for (var i in images) {
165+ var item = images[i];
166+ var image = {
167+ format: item.format,
168+ width: item.width,
169+ height: item.height,
170+ filename: path.basename(item.filename),
171+ id: item.id
172+ }
173+ newImages.push(image);
174+ }
175+ res.jsonp(newImages);
176+ })
177+
178+ app.get('/:width/:height', function (req, res, next) {
179+ checkParameters(req.params, function (err, code, message) {
180+ if (err) {
181+ return displayError(res, code, message);
182+ }
183+
184+ var filePath;
185+ if (req.query.image) {
186+ findMatchingImage(req.query.image, function (err, matchingImage) {
187+ if (err) {
188+ return displayError(res, 400, 'Invalid image id');
189+ }
190+ filePath = matchingImage;
191+ })
192+ } else {
193+ filePath = images[Math.floor(Math.random() * images.length)].filename;
194+ }
195+
196+ getProcessedImage(req.params.width, req.params.height, filePath, (!req.query.image && !req.query.random && req.query.random != ''), function (err, imagePath) {
197+ if (err) {
198+ return displayError(res, 500, 'Something went wrong');
199+ }
200+ res.sendFile(imagePath, { root: '.' });
201+ })
202+ })
203+ })
204+
205+ app.get('/g/:width/:height', function (req, res, next) {
206+ checkParameters(req.params, function (err, code, message) {
207+ if (err) {
208+ return displayError(res, code, message);
209+ }
210+
211+ var filePath;
212+ if (req.query.image) {
213+ findMatchingImage(req.query.image, function (err, matchingImage) {
214+ if (err) {
215+ return displayError(res, 400, 'Invalid image id');
216+ }
217+ filePath = matchingImage;
218+ })
219+ } else {
220+ filePath = images[Math.floor(Math.random() * images.length)].filename;
221+ }
222+
223+ getProcessedGrayImage(req.params.width, req.params.height, filePath, (!req.query.image && !req.query.random && req.query.random != ''), function (err, imagePath) {
224+ if (err) {
225+ return displayError(res, 500, 'Something went wrong');
226+ }
227+ res.sendFile(imagePath, { root: '.' });
228+ })
229+ })
230+ })
231+
232+ app.get('*', function (req, res, next) {
233+ res.status(404);
234+ res.send({ error: 'Resource not found' });
235+ })
236+
237+ imageScan();
238+ app.listen(process.env.PORT || 5000);
0 commit comments