1
2
3
4
5
6
7
8 package com.buckosoft.BuckoVidLib.web;
9
10 import java.awt.Color;
11 import java.awt.Font;
12 import java.awt.FontMetrics;
13 import java.awt.Graphics2D;
14 import java.awt.Image;
15 import java.awt.image.BufferedImage;
16 import java.io.File;
17 import java.io.IOException;
18 import java.io.OutputStream;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.util.Enumeration;
22 import java.util.Iterator;
23
24 import javax.imageio.ImageIO;
25 import javax.imageio.ImageReader;
26 import javax.imageio.ImageWriter;
27 import javax.imageio.stream.ImageInputStream;
28 import javax.imageio.stream.ImageOutputStream;
29 import javax.servlet.http.HttpServletRequest;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.stereotype.Controller;
35 import org.springframework.web.bind.annotation.PathVariable;
36 import org.springframework.web.bind.annotation.RequestMapping;
37
38 import com.buckosoft.BuckoVidLib.business.BuckoVidLib;
39 import com.buckosoft.BuckoVidLib.domain.VideoBase;
40 import com.buckosoft.BuckoVidLib.util.ConfigManager;
41 import com.buckosoft.BuckoVidLib.util.DomainConverter;
42
43
44
45
46
47 @Controller(value="image")
48 @RequestMapping("/image")
49 public class ImageController {
50 private final Log log = LogFactory.getLog(getClass());
51 private final String defaultBackground = "http://www.buckosoft.com/bvlib/static/defaultBackground.jpg";
52 private final String greyBackground = "http://www.buckosoft.com/bvlib/static/greyBackground.png";
53 private final String tteoacBackground = "http://www.buckosoft.com/bvlib/static/tteoacBackground.jpg";
54
55
56 public final static int bgFit = 0;
57
58 public final static int bgFill = 1;
59
60 public final static int bgGrey = 2;
61
62 public final static String keyDefault = "0";
63 public final static String keyNone = "1";
64 public final static String keyTteoac = "2";
65
66
67 @Autowired
68 private BuckoVidLib bvl;
69
70 private boolean useImageCache = false;
71 private String imageCacheBaseDir;
72
73
74 public ImageController() {
75 useImageCache = ConfigManager.getBoolean("BuckoVidLib.useImageCache", false);
76 imageCacheBaseDir = ConfigManager.getString("BuckoVidLib.imageCacheBaseDir", "C:/configureme");
77 }
78
79
80
81
82
83 public void setUseImageCache(boolean useImageCache) {
84 this.useImageCache = useImageCache;
85 }
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 @RequestMapping("/{key}")
105 public void handleRequest(@PathVariable("key") String key,
106 HttpServletRequest request, OutputStream outputStream) {
107
108
109
110 int w = 0;
111 int h = 0;
112 String s;
113 int backgroundFit = bgFit;
114 boolean a = false;
115 s = request.getParameter("w");
116 if (s != null)
117 w = Integer.parseInt(s);
118 s = request.getParameter("h");
119 if (s != null)
120 h = Integer.parseInt(s);
121 s = request.getParameter("a");
122 if (s != null)
123 a = true;
124 log.debug("w/h = " + w + "/" + h);
125 if (w > 3000 || h > 3000 || w < 0 || h < 0) {
126 log.warn("BADGUY! Limiting requested image size " + w + "/" + h);
127 w = 400;
128 h = 400;
129 }
130 backgroundFit = bvl.getBackgroundFit(request, a);
131 if (log.isTraceEnabled()) {
132 for (Enumeration<String> e = request.getHeaderNames(); e.hasMoreElements();) {
133 String ee = e.nextElement();
134 String ww = request.getHeader(ee);
135 log.debug("Header '" + ee + "' : '" + ww + "'");
136 }
137 for (Enumeration<String> e = request.getParameterNames(); e.hasMoreElements();) {
138 String ee = e.nextElement();
139 String ww = request.getParameter(ee);
140 log.debug("Param '" + ee + "' : '" + ww + "'");
141 }
142 }
143 VideoBase v = null;
144 String printedTitle = null;
145 String backgroundUrl;
146 if (key.equals("0")) {
147 backgroundUrl = defaultBackground;
148 backgroundFit = bgFill;
149 } else if (key.equals("1")) {
150 backgroundUrl = greyBackground;
151 } else if (key.equals("2")) {
152 backgroundUrl = tteoacBackground;
153 backgroundFit = bgFill;
154
155 } else {
156 boolean b = bvl.isAllowRestricted(request);
157 v = bvl.getVideoBaseFromKey(DomainConverter.keyToInt(key), b);
158 if (v == null) {
159 log.warn("Video not found for key: " + key);
160 backgroundUrl = defaultBackground;
161 } else {
162 printedTitle = v.getTitle() + " (" + v.getYear() + ")";
163 backgroundUrl = bvl.getPlexUrl() + v.getBackgroundUrl();
164 }
165 }
166 BufferedImage img = null;
167 if (useImageCache) {
168 s = imageCacheBaseDir + "/art/" + key;
169 File f = null;
170 try {
171 f = new File(s);
172 } catch (Exception e) {
173 log.warn("imageController: Can't create file '" + s + "'");
174 return;
175 }
176
177
178 ImageReader reader = null;
179 ImageInputStream iis = null;
180 try {
181 iis = ImageIO.createImageInputStream(f);
182 log.debug("iis = " + iis);
183 if (iis == null) {
184 log.warn("imageController: Can't read file '" + s + "'");
185 return;
186 }
187 Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
188 reader = (ImageReader)readers.next();
189 reader.setInput(iis, true);
190 img = reader.read(0);
191 iis.close();
192 } catch (Exception e) {
193 log.warn(e);
194 if (reader != null)
195 reader.dispose();
196 img = null;
197 if (iis != null) {
198 try {
199 iis.close();
200 } catch (Exception e1) {}
201 }
202 log.warn("imageController: Can't create image '" + s + "'");
203 return;
204 }
205 } else {
206
207 URL url;
208 try {
209 url = new URL(backgroundUrl);
210 } catch (MalformedURLException e2) {
211 log.warn("Failed to convert '" + backgroundUrl + "'");
212 return;
213 }
214 try {
215 img = ImageIO.read(url);
216 } catch (Exception e1) {
217 log.warn("Can't load image for " + (v != null ? v.getTitle() : "null image"));
218 return;
219 }
220 }
221 log.info("Fetch background for: " + printedTitle);
222 log.debug("original image: " + img.getWidth() + "/" + img.getHeight());
223 log.debug("backgroundFit = " + backgroundFit);
224 if (backgroundFit != bgFit) {
225 if (w > 1 && h > 1) {
226 int targetw;
227 int targeth;
228 double wp = (double)img.getWidth() / (double)w;
229 double hp = (double)img.getHeight() / (double)h;
230 if (hp < wp) {
231 targetw = (int)((double)img.getWidth() / hp);
232 targeth = h;
233 } else {
234 targeth = (int)((double)img.getHeight() / wp);
235 targetw = w;
236 }
237 log.debug("grow target: " + targetw + "/" + targeth);
238 BufferedImage scaled = new BufferedImage(targetw, targeth, BufferedImage.TYPE_INT_BGR);
239 Graphics2D g;
240 g = scaled.createGraphics();
241 g.drawImage(img.getScaledInstance(targetw, targeth, Image.SCALE_SMOOTH), null, null);
242
243 img = scaled;
244 g.dispose();
245
246 int overw = img.getWidth() - w;
247 int overh = img.getHeight() - h;
248 int shiftw = (int)(Math.random()*overw);
249 int shifth = (int)(Math.random()*overh);
250 if (key.equals(keyTteoac)) {
251 shiftw = overw/2;
252 shifth = 0;
253 }
254 log.debug("over: " + overw + "/" + overh + " shift: " + shiftw + "/" + shifth);
255 img = img.getSubimage(shiftw, shifth, w-17, h-0);
256 }
257 } else {
258 if (w > 1 && h > 1) {
259 int targetw;
260 int targeth;
261 int x = 0;
262 int y = 0;
263 double wp = (double)w / (double)img.getWidth();
264 double hp = (double)h / (double)img.getHeight();
265 if (hp < wp) {
266 targetw = (int)((double)img.getWidth() * hp);
267 targeth = (int)((double)img.getHeight() * hp);
268 x = w/2 - (targetw/2);
269 } else {
270 targeth = (int)((double)img.getHeight() * wp);
271 targetw = (int)((double)img.getWidth() * wp);
272 y = h/2 - (targeth/2);
273 }
274 log.debug("screen: " + w + " / " + h);
275 log.debug("wp = " + wp + " hp = " + hp);
276 log.debug("grow target: " + targetw + "/" + targeth);
277 log.debug("x/y: " + x + " / " + y);
278 BufferedImage scaled = new BufferedImage(targetw, targeth, BufferedImage.TYPE_INT_BGR);
279 Graphics2D g;
280 g = scaled.createGraphics();
281 g.drawImage(img.getScaledInstance(targetw, targeth, Image.SCALE_SMOOTH), null, null);
282
283 img = scaled;
284 img = new BufferedImage(w-17, h-1, BufferedImage.TYPE_INT_BGR);
285 g = img.createGraphics();
286 g.setColor(Color.gray);
287 g.fillRect(0, 0, w, h);
288
289 g.drawImage(scaled, null, x, y);
290 g.dispose();
291 scaled = null;
292 }
293 }
294
295 if (printedTitle != null && printedTitle.length() > 0) {
296 Graphics2D g = img.createGraphics();
297 Font font = new Font("SansSerif", Font.BOLD, 30);
298 Font oldFont = g.getFont();
299 g.setFont(font);
300 FontMetrics fm = g.getFontMetrics(font);
301 int hofs = h - fm.getHeight() - 0;
302 int wofs = w - fm.stringWidth(printedTitle) - 32;
303 g.setColor(Color.black);
304 g.drawString(printedTitle, wofs, hofs);
305 g.setColor(Color.white);
306 g.drawString(printedTitle, wofs-2, hofs-2);
307
308
309
310
311
312
313
314
315 g.setFont(oldFont);
316 g.dispose();
317 }
318
319 try {
320 ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream);
321 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
322 ImageWriter writer = (ImageWriter)writers.next();
323 writer.setOutput(ios);
324 writer.write(img);
325 } catch (IOException e) {
326 log.warn("Failed to write image " + backgroundUrl);
327 }
328 return;
329 }
330
331
332
333
334
335
336
337
338 public String handleRequest(String key, OutputStream outputStream) {
339 VideoBase v = bvl.getVideoBaseFromKey(DomainConverter.keyToInt(key), true);
340 String backgroundUrl = bvl.getPlexUrl() + v.getBackgroundUrl();
341 BufferedImage img = null;
342 URL url;
343 String s;
344 try {
345 url = new URL(backgroundUrl);
346 } catch (MalformedURLException e2) {
347 s = "Failed to convert '" + backgroundUrl + "'";
348 log.warn(s);
349 return(s);
350 }
351 try {
352 img = ImageIO.read(url);
353 } catch (Exception e1) {
354 s = "Can't load image for " + (v != null ? v.getTitle() : "null image");
355 log.warn(s);
356 return(s);
357 }
358 try {
359 ImageOutputStream ios = ImageIO.createImageOutputStream(outputStream);
360 Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("jpg");
361 ImageWriter writer = (ImageWriter)writers.next();
362 writer.setOutput(ios);
363 writer.write(img);
364 } catch (IOException e) {
365 s = "Failed to write image " + backgroundUrl;
366 log.warn(s);
367 return(s);
368 }
369 return(null);
370 }
371 }