1 |
|
2 | "use strict";
|
3 |
|
4 | const Path = require('path');
|
5 | const Async = require('async');
|
6 | const Mime = require('mime');
|
7 |
|
8 | const debug = require('debug')('upnpserver:contentHandlers:MetasImages');
|
9 | const logger = require('../logger');
|
10 |
|
11 | const MetasJson = require('./metas.json');
|
12 |
|
13 | const gm = require('gm');
|
14 |
|
15 | class MetasImages extends MetasJson {
|
16 | constructor(configuration) {
|
17 | super(configuration);
|
18 | }
|
19 |
|
20 | _tryDownloadImageURL(url, callback) {
|
21 | callback(null, false);
|
22 | }
|
23 |
|
24 | _addImage(metas, imageURL, imagePath, suggestedWidth, suggestedHeight, key, index, resizeWidths, isBaseURL, callback) {
|
25 | debug("_addImage", "imageURL=", imageURL, "key=", key, "index=", index);
|
26 |
|
27 | var resKey = key + "/" + (index + 1);
|
28 |
|
29 | var resize = (stats, w, h, maxw, maxh) => {
|
30 | if (w > maxw) {
|
31 | var d = maxw / w;
|
32 | w = Math.floor(d * w);
|
33 | h = Math.floor(d * h);
|
34 | }
|
35 |
|
36 | if (h > maxh) {
|
37 | var d2 = maxh / h;
|
38 | w = Math.floor(d2 * w);
|
39 | h = Math.floor(d2 * h);
|
40 | }
|
41 |
|
42 | var i = {
|
43 | contentHandlerKey: this.name,
|
44 | key: resKey,
|
45 | paramURL: "w" + maxw,
|
46 | additionalInfo: "type=" + key,
|
47 | width: w,
|
48 | height: h,
|
49 | imagePath: imagePath
|
50 | };
|
51 |
|
52 | if (stats) {
|
53 | i.mimeType = stats.mimeType;
|
54 | i.mtime = stats.mtime.getTime();
|
55 | } else {
|
56 | var mt = Mime.lookup(imagePath);
|
57 | if (mt) {
|
58 | i.mimeType = mt;
|
59 | }
|
60 | }
|
61 | if (isBaseURL) {
|
62 | i.baseURL = true;
|
63 | }
|
64 |
|
65 | metas.res.push(i);
|
66 | };
|
67 |
|
68 | var addSizes = (stats, w, h) => {
|
69 | metas.res = metas.res || [{}];
|
70 | var i = {
|
71 | contentHandlerKey: this.name,
|
72 | key: resKey,
|
73 | additionalInfo: "type=" + key,
|
74 | width: w,
|
75 | height: h,
|
76 | imagePath: imagePath
|
77 | };
|
78 |
|
79 | if (stats) {
|
80 | i.mimeType = stats.mimeType;
|
81 | i.mtime = stats.mtime.getTime();
|
82 | i.size = stats.size;
|
83 | } else {
|
84 | var mt = Mime.lookup(imagePath);
|
85 | if (mt) {
|
86 | i.mimeType = mt;
|
87 | }
|
88 | }
|
89 | if (isBaseURL) {
|
90 | i.baseURL = true;
|
91 | }
|
92 |
|
93 | metas.res.push(i);
|
94 |
|
95 | if (!resizeWidths) {
|
96 | return;
|
97 | }
|
98 |
|
99 | if (w > 4096 || h > 4096) {
|
100 | resize(stats, w, h, 4096, 4096);
|
101 | }
|
102 |
|
103 | if (w > 1024 || h > 768) {
|
104 | resize(stats, w, h, 1024, 768);
|
105 | }
|
106 |
|
107 | if (w > 640 || h > 480) {
|
108 | resize(stats, w, h, 640, 480);
|
109 | }
|
110 |
|
111 | if (w > 160 || h > 160) {
|
112 | resize(stats, w, h, 160, 160);
|
113 | }
|
114 | };
|
115 |
|
116 | imageURL.stat((error, stats) => {
|
117 | if (error || !stats) {
|
118 | debug("_addImage", "Can not locate imageURL", imageURL, error);
|
119 |
|
120 |
|
121 |
|
122 | |
123 |
|
124 |
|
125 |
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | addSizes(null, suggestedWidth, suggestedHeight);
|
138 | return callback();
|
139 | }
|
140 |
|
141 | if (suggestedWidth && suggestedHeight) {
|
142 | addSizes(stats, suggestedWidth, suggestedHeight);
|
143 | return callback();
|
144 | }
|
145 |
|
146 | var session = null;
|
147 | imageURL.createReadStream(session, {}, (error, stream) => {
|
148 | if (error) {
|
149 | return callback(error);
|
150 | }
|
151 |
|
152 | gm(stream).identify((error, gmJson) => {
|
153 | if (error) {
|
154 | imageURL.contentProvider.end(session, (error2) => {
|
155 | callback(error || error2);
|
156 | });
|
157 |
|
158 | return;
|
159 | }
|
160 |
|
161 |
|
162 |
|
163 | var w = gmJson.size.width;
|
164 | var h = gmJson.size.height;
|
165 |
|
166 | addSizes(stats, w, h);
|
167 | callback();
|
168 | });
|
169 | });
|
170 | });
|
171 | }
|
172 |
|
173 | _convertImageSize(session, imageURL, originalStats, originalSizes, sizeSuffix, width, height, callback) {
|
174 | debug("_convertImageSize", "imageURL=", imageURL, "width=", width, "height=", height);
|
175 |
|
176 | if (!originalSizes) {
|
177 | imageURL.createReadStream(null, {}, (error, stream) => {
|
178 | if (error) {
|
179 | return callback(error);
|
180 | }
|
181 |
|
182 | gm(stream).identify((error, gmJson) => {
|
183 | if (error) {
|
184 | return callback(error);
|
185 | }
|
186 |
|
187 | var sizes = {
|
188 | width: gmJson.size.width,
|
189 | height: gmJson.size.height
|
190 | };
|
191 | this._convertImage(session, imageURL, originalStats, sizes, sizeSuffix, width, height, callback);
|
192 | });
|
193 | });
|
194 | return;
|
195 | }
|
196 |
|
197 |
|
198 | var reg = /(.*)\.([^.]+)$/.exec(imageURL.basename);
|
199 | if (!reg) {
|
200 | logger.error("Can not parse '" + imageURL + "'");
|
201 | return callback("Path problem");
|
202 | }
|
203 |
|
204 | var newBasename = reg[1] + sizeSuffix + '.' + reg[2];
|
205 |
|
206 | var imageURL2 = imageURL.changeBasename(newBasename);
|
207 |
|
208 | debug("_convertImageSize", "imageURL", imageURL, "=> imageURL2=", imageURL2);
|
209 |
|
210 | imageURL2.stat((error, stats2) => {
|
211 | if (!error && stats2 && stats2.size > 0) {
|
212 | debug("_convertImageSize", "date=", originalStats.mtime, "date2=", stats2.mtime);
|
213 |
|
214 | if (stats2.mtime.getTime() > originalStats.mtime.getTime()) {
|
215 | imageURL2.createReadStream(null, {}, (error, stream2) => {
|
216 | if (error) {
|
217 | return callback(error);
|
218 | }
|
219 | gm(stream2).identify((error, json) => {
|
220 | if (error) {
|
221 | return callback(error);
|
222 | }
|
223 |
|
224 | callback(null, imageURL2, stats2, json);
|
225 | });
|
226 | });
|
227 | return;
|
228 | }
|
229 | }
|
230 |
|
231 | imageURL.createReadStream(null, {}, (error, stream) => {
|
232 | if (error) {
|
233 | return callback(error);
|
234 | }
|
235 |
|
236 | imageURL2.createWriteStream({}, (error, writeStream) => {
|
237 | if (error) {
|
238 | return callback(error);
|
239 | }
|
240 |
|
241 | var w = originalSizes.width;
|
242 | var h = originalSizes.height;
|
243 |
|
244 | if (w > width) {
|
245 | var d = width / w;
|
246 | w = Math.floor(d * w);
|
247 | h = Math.floor(d * h);
|
248 | }
|
249 |
|
250 | if (h > height) {
|
251 | var d2 = height / h;
|
252 | w = Math.floor(d2 * w);
|
253 | h = Math.floor(d2 * h);
|
254 | }
|
255 |
|
256 | debug("_convertImageSize", "Resize image width=", w, "height=", h);
|
257 |
|
258 | writeStream.on('finish', () => {
|
259 | debug("_convertImageSize", "Catch end message");
|
260 |
|
261 | imageURL2.stat((error, stats2) => {
|
262 | debug("_convertImageSize", "Stat2=",stats2,"error=",error);
|
263 | if (error) {
|
264 | return callback(error);
|
265 | }
|
266 |
|
267 | imageURL2.createReadStream(null, {}, (error, stream2) => {
|
268 | debug("_convertImageSize", "Create read stream error=",error);
|
269 |
|
270 | if (error) {
|
271 | return callback(error);
|
272 | }
|
273 |
|
274 | gm(stream2).identify((error, json2) => {
|
275 | debug("_convertImageSize", "Identify2 json2=", json2, "error=",error);
|
276 |
|
277 | if (error) {
|
278 | return callback(error);
|
279 | }
|
280 |
|
281 | callback(null, imageURL2, stats2, json2);
|
282 | });
|
283 | });
|
284 | });
|
285 | });
|
286 |
|
287 | writeStream.on('error', (error) => {
|
288 | debug("_convertImageSize", "Catch error message", error);
|
289 | callback(error);
|
290 | });
|
291 |
|
292 | gm(stream).resize(w, h).stream().pipe(writeStream);
|
293 | });
|
294 | });
|
295 | });
|
296 | }
|
297 | }
|
298 |
|
299 | module.exports = MetasImages;
|