Mercurial > hg > digilib-old
annotate servlet/src/digilib/servlet/Scaler.java @ 103:0e49645f98c8
Servlet V1.9b2
Fixes error in rotation for ImageLoader DocuImage.
author | robcast |
---|---|
date | Mon, 12 May 2003 22:33:44 +0200 |
parents | cc6a0b9ac78e |
children | 55bc0e928ac5 |
rev | line source |
---|---|
1 | 1 /* Scaler -- Scaler servlet main class |
2 | |
3 Digital Image Library servlet components | |
4 | |
73 | 5 Copyright (C) 2001, 2002, 2003 Robert Casties (robcast@mail.berlios.de) |
1 | 6 |
7 This program is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
9 Free Software Foundation; either version 2 of the License, or (at your | |
10 option) any later version. | |
11 | |
12 Please read license.txt for the full details. A copy of the GPL | |
13 may be found at http://www.gnu.org/copyleft/lgpl.html | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program; if not, write to the Free Software | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 */ | |
20 | |
21 package digilib.servlet; | |
22 | |
86 | 23 import java.awt.Dimension; |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
24 import java.awt.geom.AffineTransform; |
100 | 25 import java.awt.geom.NoninvertibleTransformException; |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
26 import java.awt.geom.Rectangle2D; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
27 import java.io.File; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
28 import java.io.IOException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
29 import java.util.List; |
1 | 30 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
31 import javax.servlet.ServletConfig; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
32 import javax.servlet.ServletContext; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
33 import javax.servlet.ServletException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
34 import javax.servlet.http.HttpServlet; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
35 import javax.servlet.http.HttpServletRequest; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
36 import javax.servlet.http.HttpServletResponse; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
37 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
38 import digilib.Utils; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
39 import digilib.auth.AuthOpException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
40 import digilib.auth.AuthOps; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
41 import digilib.image.DocuImage; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
42 import digilib.image.ImageOpException; |
86 | 43 import digilib.io.DocuDirCache; |
44 import digilib.io.DocuFile; | |
45 import digilib.io.DocuFileset; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
46 import digilib.io.FileOpException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
47 import digilib.io.FileOps; |
1 | 48 |
64
5ea1999befd4
New JAI ImageLoader plugin. Currently uses first beta version of the plugin.
robcast
parents:
62
diff
changeset
|
49 //import tilecachetool.*; |
1 | 50 |
73 | 51 /** |
52 * @author casties | |
53 * | |
54 */ | |
1 | 55 //public class Scaler extends HttpServlet implements SingleThreadModel { |
56 public class Scaler extends HttpServlet { | |
57 | |
73 | 58 // digilib servlet version (for all components) |
103 | 59 public static final String dlVersion = "1.9b2"; |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
60 |
73 | 61 // Utils instance with debuglevel |
62 Utils util; | |
63 // FileOps instance | |
64 FileOps fileOp; | |
65 // AuthOps instance | |
66 AuthOps authOp; | |
67 // ServletOps instance | |
68 ServletOps servletOp; | |
86 | 69 // DocuDirCache instance |
70 DocuDirCache dirCache; | |
1 | 71 |
94 | 72 // DigilibConfiguration instance |
73 | 73 DigilibConfiguration dlConfig; |
1 | 74 |
73 | 75 // use authorization database |
76 boolean useAuthentication = true; | |
1 | 77 |
100 | 78 // EXPRIMENTAL |
79 // try to enlarge cropping area for "oblique" angles | |
80 boolean wholeRotArea = false; | |
81 | |
73 | 82 /** Initialisation on first run. |
83 * | |
84 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) | |
85 */ | |
86 public void init(ServletConfig config) throws ServletException { | |
87 super.init(config); | |
1 | 88 |
73 | 89 // Debuggin! |
90 //TCTool tctool = new TCTool(); | |
1 | 91 |
73 | 92 // get our ServletContext |
93 ServletContext context = config.getServletContext(); | |
94 // see if there is a Configuration instance | |
95 dlConfig = | |
96 (DigilibConfiguration) context.getAttribute( | |
86 | 97 "digilib.servlet.configuration"); |
73 | 98 if (dlConfig == null) { |
99 // create new Configuration | |
100 try { | |
101 dlConfig = new DigilibConfiguration(config); | |
86 | 102 context.setAttribute("digilib.servlet.configuration", dlConfig); |
73 | 103 } catch (Exception e) { |
104 throw new ServletException(e); | |
105 } | |
106 } | |
107 // set the servlet version | |
108 dlConfig.setServletVersion(dlVersion); | |
109 // first we need an Utils | |
110 util = dlConfig.getUtil(); | |
111 // set our AuthOps | |
112 useAuthentication = dlConfig.isUseAuthentication(); | |
113 authOp = dlConfig.getAuthOp(); | |
114 // FileOps instance | |
115 fileOp = new FileOps(util); | |
116 // AuthOps instance | |
117 servletOp = new ServletOps(util); | |
86 | 118 // DocuDirCache instance |
119 dirCache = dlConfig.getDirCache(); | |
73 | 120 } |
1 | 121 |
73 | 122 /** Process the HTTP Get request*/ |
123 public void doGet(HttpServletRequest request, HttpServletResponse response) | |
124 throws ServletException, IOException { | |
125 util.dprintln(1, "The servlet has received a GET!"); | |
126 // create new request with defaults | |
127 DigilibRequest dlReq = new DigilibRequest(); | |
128 // set with request parameters | |
129 dlReq.setWithRequest(request); | |
130 // add DigilibRequest to ServletRequest | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
131 request.setAttribute("digilib.servlet.request", dlReq); |
73 | 132 // do the processing |
133 processRequest(request, response); | |
134 } | |
1 | 135 |
73 | 136 /**Process the HTTP Post request*/ |
137 public void doPost( | |
138 HttpServletRequest request, | |
139 HttpServletResponse response) | |
140 throws ServletException, IOException { | |
141 util.dprintln(1, "The servlet has received a POST!"); | |
142 // create new request with defaults | |
143 DigilibRequest dlReq = new DigilibRequest(); | |
144 // set with request parameters | |
145 dlReq.setWithRequest(request); | |
146 // add DigilibRequest to ServletRequest | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
147 request.setAttribute("digilib.servlet.request", dlReq); |
73 | 148 // do the processing |
149 processRequest(request, response); | |
150 } | |
151 | |
152 /** main request handler. */ | |
153 void processRequest( | |
154 HttpServletRequest request, | |
155 HttpServletResponse response) | |
156 throws ServletException, IOException { | |
1 | 157 |
73 | 158 // time for benchmarking |
159 long startTime = System.currentTimeMillis(); | |
160 // output mime/type | |
161 String mimeType = "image/png"; | |
1 | 162 |
73 | 163 /* |
164 * parameters for a session | |
165 */ | |
1 | 166 |
73 | 167 // scale the image file to fit window size i.e. respect dw,dh |
168 boolean scaleToFit = true; | |
100 | 169 // scale the image by a fixed factor only |
170 boolean absoluteScale = false; | |
73 | 171 // crop the image if needed |
172 boolean cropToFit = true; | |
173 // use heuristics (GIF?) to scale or send as is | |
174 boolean autoScale = true; | |
175 // try prescaled images first | |
176 boolean preScaledFirst = true; | |
177 // interpolation to use for scaling | |
178 int scaleQual = 0; | |
179 // send html error message (or image file) | |
180 boolean errorMsgHtml = false; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
181 // mirror the image |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
182 boolean doMirror = false; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
183 // angle of mirror axis |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
184 double mirrorAngle = 0; |
1 | 185 |
73 | 186 /* |
187 * request parameters | |
188 */ | |
189 | |
190 DigilibRequest dlRequest = | |
191 (DigilibRequest) request.getAttribute("digilib.servlet.request"); | |
1 | 192 |
73 | 193 // destination image width |
194 int paramDW = dlRequest.getDw(); | |
195 // destination image height | |
196 int paramDH = dlRequest.getDh(); | |
197 // relative area x_offset (0..1) | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
198 double paramWX = dlRequest.getWx(); |
73 | 199 // relative area y_offset |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
200 double paramWY = dlRequest.getWy(); |
73 | 201 // relative area width (0..1) |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
202 double paramWW = dlRequest.getWw(); |
73 | 203 // relative area height |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
204 double paramWH = dlRequest.getWh(); |
73 | 205 // scale factor (additional to dw/width, dh/height) |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
206 double paramWS = dlRequest.getWs(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
207 // rotation angle |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
208 double paramROT = dlRequest.getRot(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
209 // contrast enhancement |
86 | 210 float paramCONT = dlRequest.getCont(); |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
211 // brightness enhancement |
86 | 212 float paramBRGT = dlRequest.getBrgt(); |
213 // color modification | |
214 float[] paramRGBM = dlRequest.getRgbm(); | |
215 float[] paramRGBA = dlRequest.getRgba(); | |
1 | 216 |
73 | 217 /* operation mode: "fit": always fit to page, |
218 * "clip": send original resolution cropped, "file": send whole file (if | |
219 * allowed) | |
220 */ | |
221 if (dlRequest.isOption("clip")) { | |
222 scaleToFit = false; | |
100 | 223 absoluteScale = false; |
73 | 224 cropToFit = true; |
225 autoScale = false; | |
100 | 226 preScaledFirst = false; |
73 | 227 } else if (dlRequest.isOption("fit")) { |
228 scaleToFit = true; | |
100 | 229 absoluteScale = false; |
73 | 230 cropToFit = true; |
231 autoScale = false; | |
100 | 232 } else if (dlRequest.isOption("scale")) { |
233 scaleToFit = false; | |
234 absoluteScale = true; | |
235 cropToFit = true; | |
236 autoScale = false; | |
237 preScaledFirst = false; | |
73 | 238 } else if (dlRequest.isOption("file")) { |
239 scaleToFit = false; | |
100 | 240 absoluteScale = false; |
73 | 241 if (dlConfig.isSendFileAllowed()) { |
242 cropToFit = false; | |
243 } else { | |
244 cropToFit = true; | |
245 } | |
246 autoScale = false; | |
100 | 247 preScaledFirst = false; |
73 | 248 } |
249 // operation mode: "errtxt": error message in html, "errimg": error image | |
250 if (dlRequest.isOption("errtxt")) { | |
251 errorMsgHtml = true; | |
252 } else if (dlRequest.isOption("errimg")) { | |
253 errorMsgHtml = false; | |
254 } | |
255 // operation mode: "q0" - "q2": interpolation quality | |
256 if (dlRequest.isOption("q0")) { | |
257 scaleQual = 0; | |
258 } else if (dlRequest.isOption("q1")) { | |
259 scaleQual = 1; | |
260 } else if (dlRequest.isOption("q2")) { | |
261 scaleQual = 2; | |
262 } | |
263 // operation mode: "lores": try to use scaled image, "hires": use unscaled image | |
264 if (dlRequest.isOption("lores")) { | |
265 preScaledFirst = true; | |
266 } else if (dlRequest.isOption("hires")) { | |
267 preScaledFirst = false; | |
268 } | |
1 | 269 |
73 | 270 //"big" try for all file/image actions |
271 try { | |
272 | |
86 | 273 // new DocuImage instance |
73 | 274 DocuImage docuImage = dlConfig.getDocuImageInstance(); |
275 if (docuImage == null) { | |
276 throw new ImageOpException("Unable to load DocuImage class!"); | |
277 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
278 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
279 // set interpolation quality |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
280 docuImage.setQuality(scaleQual); |
73 | 281 |
282 /* | |
283 * find the file to load/send | |
284 */ | |
1 | 285 |
73 | 286 // get PathInfo |
287 String loadPathName = dlRequest.getFilePath(); | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
288 |
73 | 289 /* |
290 * check permissions | |
291 */ | |
292 if (useAuthentication) { | |
293 // get a list of required roles (empty if no restrictions) | |
294 List rolesRequired = authOp.rolesForPath(loadPathName, request); | |
295 if (rolesRequired != null) { | |
296 util.dprintln(1, "Role required: " + rolesRequired); | |
297 util.dprintln(2, "User: " + request.getRemoteUser()); | |
298 // is the current request/user authorized? | |
299 if (!authOp.isRoleAuthorized(rolesRequired, request)) { | |
300 // send deny answer and abort | |
301 util.dprintln(1, "ERROR: access denied!"); | |
302 if (errorMsgHtml) { | |
303 ServletOps.htmlMessage( | |
304 "ERROR: Unauthorized access!", | |
305 response); | |
306 } else { | |
307 servletOp.sendFile( | |
308 new File(dlConfig.getDenyImgFileName()), | |
309 response); | |
310 } | |
311 return; | |
312 } | |
313 } | |
314 } | |
1 | 315 |
73 | 316 // find the file |
86 | 317 DocuFile fileToLoad; |
94 | 318 DocuFileset fileset = |
319 dirCache.getFileset(loadPathName, dlRequest.getPn()); | |
320 if (fileset == null) { | |
321 throw new FileOpException( | |
322 "File " | |
323 + loadPathName | |
324 + "(" | |
325 + dlRequest.getPn() | |
326 + ") not found."); | |
327 } | |
328 | |
100 | 329 // if it's zoomed, try hires version (to be optimized...) |
330 if ((paramWW < 1f) || (paramWH < 1f)) { | |
331 preScaledFirst = false; | |
332 } | |
333 | |
86 | 334 // simplistic selection of resolution |
335 if (preScaledFirst) { | |
94 | 336 // get last element |
337 fileToLoad = fileset.get(fileset.size() - 1); | |
86 | 338 } else { |
94 | 339 // get first element |
340 fileToLoad = fileset.get(0); | |
86 | 341 } |
342 util.dprintln(1, "Loading: " + fileToLoad.getFile()); | |
73 | 343 |
86 | 344 // check the source image |
345 docuImage.checkFile(fileToLoad); | |
346 // get the source image type | |
347 mimeType = fileToLoad.getMimetype(); | |
73 | 348 |
349 /* if autoScale and not zoomed and source is GIF/PNG | |
350 * then send as is. | |
100 | 351 * if not autoScale and not scaleToFit nor cropToFit |
352 * then send as is | |
73 | 353 */ |
354 if ((autoScale | |
355 && (mimeType == "image/gif" || mimeType == "image/png") | |
356 && (paramWW == 1f) | |
357 && (paramWH == 1f)) | |
100 | 358 || (!autoScale && !scaleToFit && !cropToFit)) { |
73 | 359 |
360 util.dprintln(1, "Sending File as is."); | |
1 | 361 |
86 | 362 servletOp.sendFile(fileToLoad.getFile(), response); |
1 | 363 |
73 | 364 util.dprintln( |
365 1, | |
366 "Done in " | |
367 + (System.currentTimeMillis() - startTime) | |
368 + "ms"); | |
369 return; | |
370 } | |
1 | 371 |
73 | 372 /* |
373 * crop and scale the image | |
374 */ | |
1 | 375 |
86 | 376 int imgWidth = 0; |
377 int imgHeight = 0; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
378 // get image size |
86 | 379 if (fileToLoad.getSize() == null) { |
380 // size unknown so far | |
381 imgWidth = docuImage.getWidth(); | |
382 imgHeight = docuImage.getHeight(); | |
383 // remember size | |
384 fileToLoad.setSize(new Dimension(imgWidth, imgHeight)); | |
385 } else { | |
386 imgWidth = fileToLoad.getSize().width; | |
387 imgHeight = fileToLoad.getSize().height; | |
388 } | |
94 | 389 |
73 | 390 util.dprintln(2, "IMG: " + imgWidth + "x" + imgHeight); |
391 util.dprintln( | |
392 2, | |
393 "time " + (System.currentTimeMillis() - startTime) + "ms"); | |
1 | 394 |
73 | 395 // coordinates and scaling |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
396 double areaXoff; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
397 double areaYoff; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
398 double areaWidth; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
399 double areaHeight; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
400 double scaleX; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
401 double scaleY; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
402 double scaleXY; |
1 | 403 |
100 | 404 // coordinates using Java2D |
405 // image size in pixels | |
406 Rectangle2D imgBounds = | |
407 new Rectangle2D.Double(0, 0, imgWidth, imgHeight); | |
408 // user window area in [0,1] coordinates | |
409 Rectangle2D relUserArea = | |
410 new Rectangle2D.Double(paramWX, paramWY, paramWW, paramWH); | |
411 // transform from relative [0,1] to image coordinates. | |
412 AffineTransform imgTrafo = | |
413 AffineTransform.getScaleInstance(imgWidth, imgHeight); | |
85 | 414 // transform user coordinate area to image coordinate area |
100 | 415 Rectangle2D userImgArea = |
416 imgTrafo.createTransformedShape(relUserArea).getBounds2D(); | |
417 | |
418 // calculate scaling factors based on inner user area | |
73 | 419 if (scaleToFit) { |
100 | 420 areaWidth = userImgArea.getWidth(); |
421 areaHeight = userImgArea.getHeight(); | |
73 | 422 scaleX = paramDW / areaWidth * paramWS; |
423 scaleY = paramDH / areaHeight * paramWS; | |
424 scaleXY = (scaleX > scaleY) ? scaleY : scaleX; | |
100 | 425 } else if (absoluteScale) { |
426 // absolute scale | |
427 areaWidth = paramDW * paramWS; | |
428 areaHeight = paramDH * paramWS; | |
429 // reset user area size | |
430 userImgArea.setRect( | |
431 userImgArea.getX(), | |
432 userImgArea.getY(), | |
433 areaWidth, | |
434 areaHeight); | |
435 scaleX = 1f; | |
436 scaleY = 1f; | |
437 scaleXY = 1f; | |
73 | 438 } else { |
439 // crop to fit | |
85 | 440 areaWidth = paramDW * paramWS; |
441 areaHeight = paramDH * paramWS; | |
100 | 442 // reset user area size |
443 userImgArea.setRect( | |
444 userImgArea.getX(), | |
445 userImgArea.getY(), | |
446 areaWidth, | |
447 areaHeight); | |
73 | 448 scaleX = 1f; |
449 scaleY = 1f; | |
450 scaleXY = 1f; | |
100 | 451 } |
85 | 452 |
100 | 453 // enlarge image area for rotations to cover additional pixels |
454 Rectangle2D outerUserImgArea = userImgArea; | |
455 Rectangle2D innerUserImgArea = userImgArea; | |
456 if (wholeRotArea) { | |
457 if (paramROT != 0) { | |
458 try { | |
459 // rotate user area coordinates around center of user area | |
460 AffineTransform rotTrafo = | |
461 AffineTransform.getRotateInstance( | |
462 Math.toRadians(paramROT), | |
463 userImgArea.getCenterX(), | |
464 userImgArea.getCenterY()); | |
465 // get bounds from rotated end position | |
466 innerUserImgArea = | |
467 rotTrafo | |
468 .createTransformedShape(userImgArea) | |
469 .getBounds2D(); | |
470 // get bounds from back-rotated bounds | |
471 outerUserImgArea = | |
472 rotTrafo | |
473 .createInverse() | |
474 .createTransformedShape(innerUserImgArea) | |
475 .getBounds2D(); | |
476 } catch (NoninvertibleTransformException e1) { | |
477 // this shouldn't happen anyway | |
478 e1.printStackTrace(); | |
479 } | |
480 } | |
73 | 481 } |
1 | 482 |
73 | 483 util.dprintln( |
484 1, | |
485 "Scale " | |
486 + scaleXY | |
487 + "(" | |
488 + scaleX | |
489 + "," | |
490 + scaleY | |
491 + ") on " | |
100 | 492 + outerUserImgArea); |
1 | 493 |
73 | 494 // clip area at the image border |
100 | 495 outerUserImgArea = outerUserImgArea.createIntersection(imgBounds); |
85 | 496 |
100 | 497 areaWidth = outerUserImgArea.getWidth(); |
498 areaHeight = outerUserImgArea.getHeight(); | |
499 areaXoff = outerUserImgArea.getX(); | |
500 areaYoff = outerUserImgArea.getY(); | |
1 | 501 |
73 | 502 util.dprintln( |
503 2, | |
85 | 504 "crop: " |
73 | 505 + areaXoff |
506 + "," | |
507 + areaYoff | |
508 + " " | |
509 + areaWidth | |
510 + "x" | |
511 + areaHeight); | |
1 | 512 |
73 | 513 // check image parameters sanity |
514 if ((areaWidth < 1) | |
515 || (areaHeight < 1) | |
516 || (scaleXY * areaWidth < 2) | |
517 || (scaleXY * areaHeight < 2)) { | |
518 util.dprintln(1, "ERROR: invalid scale parameter set!"); | |
519 throw new ImageOpException("Invalid scale parameter set!"); | |
520 } | |
1 | 521 |
85 | 522 /* |
523 * crop and scale image | |
524 */ | |
525 | |
526 // use subimage loading if possible | |
527 if (docuImage.isSubimageSupported()) { | |
528 System.out.println( | |
529 "Subimage: scale " + scaleXY + " = " + (1 / scaleXY)); | |
530 double subf = 1d; | |
531 double subsamp = 1d; | |
532 if (scaleXY < 1) { | |
533 subf = 1 / scaleXY; | |
534 subsamp = Math.floor(subf); | |
535 scaleXY = subsamp / subf; | |
536 System.out.println( | |
537 "Using subsampling: " + subsamp + " rest " + scaleXY); | |
538 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
539 |
85 | 540 docuImage.loadSubimage( |
86 | 541 fileToLoad.getFile(), |
100 | 542 outerUserImgArea.getBounds(), |
85 | 543 (int) subsamp); |
544 | |
545 System.out.println( | |
546 "SUBSAMP: " | |
547 + subsamp | |
548 + " -> " | |
549 + docuImage.getWidth() | |
550 + "x" | |
551 + docuImage.getHeight()); | |
552 | |
553 docuImage.scale(scaleXY); | |
554 | |
555 } else { | |
100 | 556 // else load and crop the whole file |
86 | 557 docuImage.loadImage(fileToLoad.getFile()); |
85 | 558 docuImage.crop( |
559 (int) areaXoff, | |
560 (int) areaYoff, | |
561 (int) areaWidth, | |
562 (int) areaHeight); | |
563 | |
564 docuImage.scale(scaleXY); | |
565 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
566 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
567 // mirror image |
100 | 568 // operation mode: "hmir": mirror horizontally, "vmir": mirror vertically |
569 if (dlRequest.isOption("hmir")) { | |
570 docuImage.mirror(0); | |
571 } | |
572 if (dlRequest.isOption("vmir")) { | |
573 docuImage.mirror(90); | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
574 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
575 |
100 | 576 // rotate image |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
577 if (paramROT != 0) { |
94 | 578 docuImage.rotate(paramROT); |
100 | 579 if (wholeRotArea) { |
580 // crop to the inner bounding box | |
581 double xcrop = | |
582 docuImage.getWidth() | |
583 - innerUserImgArea.getWidth() * scaleXY; | |
584 double ycrop = | |
585 docuImage.getHeight() | |
586 - innerUserImgArea.getHeight() * scaleXY; | |
587 if ((xcrop > 0) || (ycrop > 0)) { | |
588 // only crop smaller | |
589 xcrop = (xcrop > 0) ? xcrop : 0; | |
590 ycrop = (ycrop > 0) ? ycrop : 0; | |
591 // crop image | |
592 docuImage.crop( | |
593 (int) (xcrop / 2), | |
594 (int) (ycrop / 2), | |
595 (int) (docuImage.getWidth() - xcrop), | |
596 (int) (docuImage.getHeight() - ycrop)); | |
597 } | |
598 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
599 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
600 } |
1 | 601 |
86 | 602 // color modification |
603 if ((paramRGBM != null) || (paramRGBA != null)) { | |
604 // make shure we actually have two arrays | |
605 if (paramRGBM == null) { | |
606 paramRGBM = new float[3]; | |
607 } | |
608 if (paramRGBA == null) { | |
609 paramRGBA = new float[3]; | |
610 } | |
100 | 611 // calculate "contrast" values (c=2^x) |
86 | 612 float[] mult = new float[3]; |
613 for (int i = 0; i < 3; i++) { | |
94 | 614 mult[i] = (float) Math.pow(2, (double) paramRGBM[i]); |
86 | 615 } |
616 docuImage.enhanceRGB(mult, paramRGBA); | |
617 } | |
94 | 618 |
100 | 619 // contrast and brightness enhancement |
620 if ((paramCONT != 0) || (paramBRGT != 0)) { | |
621 double mult = Math.pow(2, paramCONT); | |
622 docuImage.enhance((float) mult, (float) paramBRGT); | |
623 } | |
624 | |
73 | 625 util.dprintln( |
626 2, | |
627 "time " + (System.currentTimeMillis() - startTime) + "ms"); | |
628 | |
629 /* | |
630 * write the resulting image | |
631 */ | |
1 | 632 |
73 | 633 // setup output -- if source is JPG then dest will be JPG else it's PNG |
100 | 634 if (mimeType.equals("image/jpeg") |
635 || mimeType.equals("image/jp2")) { | |
636 mimeType = "image/jpeg"; | |
637 } else { | |
73 | 638 mimeType = "image/png"; |
639 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
640 response.setContentType(mimeType); |
1 | 641 |
73 | 642 // write the image |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
643 docuImage.writeImage(mimeType, response.getOutputStream()); |
1 | 644 |
73 | 645 util.dprintln( |
646 1, | |
647 "Done in " + (System.currentTimeMillis() - startTime) + "ms"); | |
648 | |
649 /* | |
650 * error handling | |
651 */ | |
1 | 652 |
73 | 653 } // end of "big" try |
654 catch (FileOpException e) { | |
655 util.dprintln(1, "ERROR: File IO Error: " + e); | |
656 try { | |
657 if (errorMsgHtml) { | |
658 ServletOps.htmlMessage( | |
659 "ERROR: File IO Error: " + e, | |
660 response); | |
661 } else { | |
662 servletOp.sendFile( | |
663 new File(dlConfig.getErrorImgFileName()), | |
664 response); | |
665 } | |
666 } catch (FileOpException ex) { | |
667 } // so we don't get a loop | |
668 return; | |
669 } catch (AuthOpException e) { | |
670 util.dprintln(1, "ERROR: Authorization error: " + e); | |
671 try { | |
672 if (errorMsgHtml) { | |
673 ServletOps.htmlMessage( | |
674 "ERROR: Authorization error: " + e, | |
675 response); | |
676 } else { | |
677 servletOp.sendFile( | |
678 new File(dlConfig.getErrorImgFileName()), | |
679 response); | |
680 } | |
681 } catch (FileOpException ex) { | |
682 } // so we don't get a loop | |
683 return; | |
684 } catch (ImageOpException e) { | |
685 util.dprintln(1, "ERROR: Image Error: " + e); | |
686 try { | |
687 if (errorMsgHtml) { | |
688 ServletOps.htmlMessage( | |
689 "ERROR: Image Operation Error: " + e, | |
690 response); | |
691 } else { | |
692 servletOp.sendFile( | |
693 new File(dlConfig.getErrorImgFileName()), | |
694 response); | |
695 } | |
696 } catch (FileOpException ex) { | |
697 } // so we don't get a loop | |
698 return; | |
699 } catch (RuntimeException e) { | |
700 // JAI likes to throw RuntimeExceptions ;-( | |
701 util.dprintln(1, "ERROR: Other Image Error: " + e); | |
702 try { | |
703 if (errorMsgHtml) { | |
704 ServletOps.htmlMessage( | |
705 "ERROR: Other Image Operation Error: " + e, | |
706 response); | |
707 } else { | |
708 servletOp.sendFile( | |
709 new File(dlConfig.getErrorImgFileName()), | |
710 response); | |
711 } | |
712 } catch (FileOpException ex) { | |
713 } // so we don't get a loop | |
714 return; | |
715 } | |
716 } | |
1 | 717 |
73 | 718 } //Scaler class |