Mercurial > hg > digilib-old
annotate servlet/src/digilib/servlet/Scaler.java @ 85:4e6757e8ccd4
New enhanced ImageLoader stuff.
Now uses Subsampling and image regions on read.
Now implements enhance, rotate and mirror for ImageLoader/Java2D
author | robcast |
---|---|
date | Thu, 27 Feb 2003 15:07:29 +0100 |
parents | 63c8186455c1 |
children | 997ba69afb81 |
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 | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
23 import java.awt.geom.AffineTransform; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
24 import java.awt.geom.Point2D; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
25 import java.awt.geom.Rectangle2D; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
26 import java.io.File; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
27 import java.io.IOException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
28 import java.util.List; |
1 | 29 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
30 import javax.servlet.ServletConfig; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
31 import javax.servlet.ServletContext; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
32 import javax.servlet.ServletException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
33 import javax.servlet.http.HttpServlet; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
34 import javax.servlet.http.HttpServletRequest; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
35 import javax.servlet.http.HttpServletResponse; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
36 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
37 import digilib.Utils; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
38 import digilib.auth.AuthOpException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
39 import digilib.auth.AuthOps; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
40 import digilib.image.DocuImage; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
41 import digilib.image.ImageOpException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
42 import digilib.io.FileOpException; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
43 import digilib.io.FileOps; |
1 | 44 |
64
5ea1999befd4
New JAI ImageLoader plugin. Currently uses first beta version of the plugin.
robcast
parents:
62
diff
changeset
|
45 //import tilecachetool.*; |
1 | 46 |
73 | 47 /** |
48 * @author casties | |
49 * | |
50 */ | |
1 | 51 //public class Scaler extends HttpServlet implements SingleThreadModel { |
52 public class Scaler extends HttpServlet { | |
53 | |
73 | 54 // digilib servlet version (for all components) |
85 | 55 public static final String dlVersion = "1.6b3"; |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
56 |
73 | 57 // Utils instance with debuglevel |
58 Utils util; | |
59 // FileOps instance | |
60 FileOps fileOp; | |
61 // AuthOps instance | |
62 AuthOps authOp; | |
63 // ServletOps instance | |
64 ServletOps servletOp; | |
1 | 65 |
73 | 66 // DigilibParameters instance |
67 DigilibConfiguration dlConfig; | |
1 | 68 |
73 | 69 // use authorization database |
70 boolean useAuthentication = true; | |
1 | 71 |
73 | 72 /** Initialisation on first run. |
73 * | |
74 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) | |
75 */ | |
76 public void init(ServletConfig config) throws ServletException { | |
77 super.init(config); | |
1 | 78 |
73 | 79 // Debuggin! |
80 //TCTool tctool = new TCTool(); | |
1 | 81 |
73 | 82 // get our ServletContext |
83 ServletContext context = config.getServletContext(); | |
84 // see if there is a Configuration instance | |
85 dlConfig = | |
86 (DigilibConfiguration) context.getAttribute( | |
87 "digilib.servlet.parameters"); | |
88 if (dlConfig == null) { | |
89 // create new Configuration | |
90 try { | |
91 dlConfig = new DigilibConfiguration(config); | |
92 } catch (Exception e) { | |
93 throw new ServletException(e); | |
94 } | |
95 } | |
96 // set the servlet version | |
97 dlConfig.setServletVersion(dlVersion); | |
98 // first we need an Utils | |
99 util = dlConfig.getUtil(); | |
100 // set our AuthOps | |
101 useAuthentication = dlConfig.isUseAuthentication(); | |
102 authOp = dlConfig.getAuthOp(); | |
103 // FileOps instance | |
104 fileOp = new FileOps(util); | |
105 // AuthOps instance | |
106 servletOp = new ServletOps(util); | |
107 } | |
1 | 108 |
73 | 109 /** Process the HTTP Get request*/ |
110 public void doGet(HttpServletRequest request, HttpServletResponse response) | |
111 throws ServletException, IOException { | |
112 util.dprintln(1, "The servlet has received a GET!"); | |
113 // create new request with defaults | |
114 DigilibRequest dlReq = new DigilibRequest(); | |
115 // set with request parameters | |
116 dlReq.setWithRequest(request); | |
117 // add DigilibRequest to ServletRequest | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
118 request.setAttribute("digilib.servlet.request", dlReq); |
73 | 119 // do the processing |
120 processRequest(request, response); | |
121 } | |
1 | 122 |
73 | 123 /**Process the HTTP Post request*/ |
124 public void doPost( | |
125 HttpServletRequest request, | |
126 HttpServletResponse response) | |
127 throws ServletException, IOException { | |
128 util.dprintln(1, "The servlet has received a POST!"); | |
129 // create new request with defaults | |
130 DigilibRequest dlReq = new DigilibRequest(); | |
131 // set with request parameters | |
132 dlReq.setWithRequest(request); | |
133 // add DigilibRequest to ServletRequest | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
134 request.setAttribute("digilib.servlet.request", dlReq); |
73 | 135 // do the processing |
136 processRequest(request, response); | |
137 } | |
138 | |
139 /** main request handler. */ | |
140 void processRequest( | |
141 HttpServletRequest request, | |
142 HttpServletResponse response) | |
143 throws ServletException, IOException { | |
1 | 144 |
73 | 145 // time for benchmarking |
146 long startTime = System.currentTimeMillis(); | |
147 // output mime/type | |
148 String mimeType = "image/png"; | |
1 | 149 |
73 | 150 /* |
151 * parameters for a session | |
152 */ | |
1 | 153 |
73 | 154 // scale the image file to fit window size i.e. respect dw,dh |
155 boolean scaleToFit = true; | |
156 // crop the image if needed | |
157 boolean cropToFit = true; | |
158 // use heuristics (GIF?) to scale or send as is | |
159 boolean autoScale = true; | |
160 // try prescaled images first | |
161 boolean preScaledFirst = true; | |
162 // interpolation to use for scaling | |
163 int scaleQual = 0; | |
164 // send html error message (or image file) | |
165 boolean errorMsgHtml = false; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
166 // mirror the image |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
167 boolean doMirror = false; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
168 // angle of mirror axis |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
169 double mirrorAngle = 0; |
1 | 170 |
73 | 171 /* |
172 * request parameters | |
173 */ | |
174 | |
175 DigilibRequest dlRequest = | |
176 (DigilibRequest) request.getAttribute("digilib.servlet.request"); | |
1 | 177 |
73 | 178 // destination image width |
179 int paramDW = dlRequest.getDw(); | |
180 // destination image height | |
181 int paramDH = dlRequest.getDh(); | |
182 // relative area x_offset (0..1) | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
183 double paramWX = dlRequest.getWx(); |
73 | 184 // relative area y_offset |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
185 double paramWY = dlRequest.getWy(); |
73 | 186 // relative area width (0..1) |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
187 double paramWW = dlRequest.getWw(); |
73 | 188 // relative area height |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
189 double paramWH = dlRequest.getWh(); |
73 | 190 // scale factor (additional to dw/width, dh/height) |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
191 double paramWS = dlRequest.getWs(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
192 // rotation angle |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
193 double paramROT = dlRequest.getRot(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
194 // contrast enhancement |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
195 double paramCONT = dlRequest.getCont(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
196 // brightness enhancement |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
197 double paramBRGT = dlRequest.getBrgt(); |
1 | 198 |
73 | 199 /* operation mode: "fit": always fit to page, |
200 * "clip": send original resolution cropped, "file": send whole file (if | |
201 * allowed) | |
202 */ | |
203 if (dlRequest.isOption("clip")) { | |
204 scaleToFit = false; | |
205 cropToFit = true; | |
206 autoScale = false; | |
207 } else if (dlRequest.isOption("fit")) { | |
208 scaleToFit = true; | |
209 cropToFit = true; | |
210 autoScale = false; | |
211 } else if (dlRequest.isOption("file")) { | |
212 scaleToFit = false; | |
213 if (dlConfig.isSendFileAllowed()) { | |
214 cropToFit = false; | |
215 } else { | |
216 cropToFit = true; | |
217 } | |
218 autoScale = false; | |
219 } | |
220 // operation mode: "errtxt": error message in html, "errimg": error image | |
221 if (dlRequest.isOption("errtxt")) { | |
222 errorMsgHtml = true; | |
223 } else if (dlRequest.isOption("errimg")) { | |
224 errorMsgHtml = false; | |
225 } | |
226 // operation mode: "q0" - "q2": interpolation quality | |
227 if (dlRequest.isOption("q0")) { | |
228 scaleQual = 0; | |
229 } else if (dlRequest.isOption("q1")) { | |
230 scaleQual = 1; | |
231 } else if (dlRequest.isOption("q2")) { | |
232 scaleQual = 2; | |
233 } | |
234 // operation mode: "lores": try to use scaled image, "hires": use unscaled image | |
235 if (dlRequest.isOption("lores")) { | |
236 preScaledFirst = true; | |
237 } else if (dlRequest.isOption("hires")) { | |
238 preScaledFirst = false; | |
239 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
240 // operation mode: "hmir": mirror horizontally, "vmir": mirror vertically |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
241 if (dlRequest.isOption("hmir")) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
242 doMirror = true; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
243 mirrorAngle = 0; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
244 } else if (dlRequest.isOption("vmir")) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
245 doMirror = true; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
246 mirrorAngle = 90; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
247 } |
1 | 248 |
73 | 249 //"big" try for all file/image actions |
250 try { | |
251 | |
252 // DocuImage instance | |
253 DocuImage docuImage = dlConfig.getDocuImageInstance(); | |
254 if (docuImage == null) { | |
255 throw new ImageOpException("Unable to load DocuImage class!"); | |
256 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
257 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
258 // set interpolation quality |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
259 docuImage.setQuality(scaleQual); |
73 | 260 |
261 /* | |
262 * find the file to load/send | |
263 */ | |
1 | 264 |
73 | 265 // get PathInfo |
266 String loadPathName = dlRequest.getFilePath(); | |
267 // if it's zoomed, try hires version (to be optimized...) | |
268 if ((paramWW < 1f) || (paramWH < 1f)) { | |
269 preScaledFirst = false; | |
270 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
271 |
73 | 272 /* |
273 * check permissions | |
274 */ | |
275 if (useAuthentication) { | |
276 // get a list of required roles (empty if no restrictions) | |
277 List rolesRequired = authOp.rolesForPath(loadPathName, request); | |
278 if (rolesRequired != null) { | |
279 util.dprintln(1, "Role required: " + rolesRequired); | |
280 util.dprintln(2, "User: " + request.getRemoteUser()); | |
281 // is the current request/user authorized? | |
282 if (!authOp.isRoleAuthorized(rolesRequired, request)) { | |
283 // send deny answer and abort | |
284 util.dprintln(1, "ERROR: access denied!"); | |
285 if (errorMsgHtml) { | |
286 ServletOps.htmlMessage( | |
287 "ERROR: Unauthorized access!", | |
288 response); | |
289 } else { | |
290 servletOp.sendFile( | |
291 new File(dlConfig.getDenyImgFileName()), | |
292 response); | |
293 } | |
294 return; | |
295 } | |
296 } | |
297 } | |
1 | 298 |
73 | 299 // find the file |
300 File fileToLoad = | |
301 fileOp.getFileVariant( | |
302 dlConfig.getBaseDirs(), | |
303 loadPathName, | |
304 dlRequest.getPn(), | |
305 preScaledFirst); | |
306 | |
307 util.dprintln(1, "Loading: " + fileToLoad); | |
1 | 308 |
73 | 309 // get the source image type (if it's known) |
310 mimeType = FileOps.mimeForFile(fileToLoad); | |
311 | |
312 /* if autoScale and not zoomed and source is GIF/PNG | |
313 * then send as is. | |
314 */ | |
315 if ((autoScale | |
316 && (mimeType == "image/gif" || mimeType == "image/png") | |
317 && (paramWW == 1f) | |
318 && (paramWH == 1f)) | |
319 || (autoScale && !(scaleToFit || cropToFit))) { | |
320 | |
321 util.dprintln(1, "Sending File as is."); | |
1 | 322 |
73 | 323 servletOp.sendFile(fileToLoad, response); |
1 | 324 |
73 | 325 util.dprintln( |
326 1, | |
327 "Done in " | |
328 + (System.currentTimeMillis() - startTime) | |
329 + "ms"); | |
330 return; | |
331 } | |
1 | 332 |
73 | 333 // finally load the file |
85 | 334 if (docuImage.isPreloadSupported()) { |
335 // only preload if supported | |
336 docuImage.preloadImage(fileToLoad); | |
337 } else { | |
338 docuImage.loadImage(fileToLoad); | |
339 } | |
1 | 340 |
73 | 341 /* |
342 * crop and scale the image | |
343 */ | |
1 | 344 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
345 // get image size |
73 | 346 int imgWidth = docuImage.getWidth(); |
347 int imgHeight = docuImage.getHeight(); | |
1 | 348 |
73 | 349 util.dprintln(2, "IMG: " + imgWidth + "x" + imgHeight); |
350 util.dprintln( | |
351 2, | |
352 "time " + (System.currentTimeMillis() - startTime) + "ms"); | |
1 | 353 |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
354 // coordinates using Java2D |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
355 // image size |
85 | 356 Rectangle2D imgBounds = |
357 new Rectangle2D.Double(0, 0, imgWidth, imgHeight); | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
358 // user window area in 4-point form (ul, ur, ll, lr) |
85 | 359 Point2D[] userAreaC = |
360 { | |
361 new Point2D.Double(paramWX, paramWY), | |
362 new Point2D.Double(paramWX + paramWW, paramWY), | |
363 new Point2D.Double(paramWX, paramWY + paramWH), | |
364 new Point2D.Double(paramWX + paramWW, paramWY + paramWH)}; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
365 // transformation from relative [0,1] to image coordinates. |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
366 AffineTransform imgTrafo = new AffineTransform(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
367 imgTrafo.scale(imgWidth, imgHeight); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
368 // rotate coordinates |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
369 //imgTrafo.rotate(Math.toRadians(-paramROT)); |
85 | 370 |
73 | 371 // coordinates and scaling |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
372 double areaXoff; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
373 double areaYoff; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
374 double areaWidth; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
375 double areaHeight; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
376 double scaleX; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
377 double scaleY; |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
378 double scaleXY; |
1 | 379 |
85 | 380 /* if (scaleToFit) { |
381 // calculate absolute from relative coordinates | |
382 areaXoff = paramWX * imgWidth; | |
383 areaYoff = paramWY * imgHeight; | |
384 areaWidth = paramWW * imgWidth; | |
385 areaHeight = paramWH * imgHeight; | |
386 // calculate scaling factors | |
387 scaleX = paramDW / areaWidth * paramWS; | |
388 scaleY = paramDH / areaHeight * paramWS; | |
389 scaleXY = (scaleX > scaleY) ? scaleY : scaleX; | |
390 } else { | |
391 // crop to fit | |
392 // calculate absolute from relative coordinates | |
393 areaXoff = paramWX * imgWidth; | |
394 areaYoff = paramWY * imgHeight; | |
395 areaWidth = paramDW; | |
396 areaHeight = paramDH; | |
397 // calculate scaling factors | |
398 scaleX = 1f; | |
399 scaleY = 1f; | |
400 scaleXY = 1f; | |
401 } | |
402 | |
403 util.dprintln( | |
404 1, | |
405 "Scale " | |
406 + scaleXY | |
407 + "(" | |
408 + scaleX | |
409 + "," | |
410 + scaleY | |
411 + ") on " | |
412 + areaXoff | |
413 + "," | |
414 + areaYoff | |
415 + " " | |
416 + areaWidth | |
417 + "x" | |
418 + areaHeight); | |
419 */ | |
420 // Java2D | |
421 // area in image pixel coordinates | |
422 Point2D[] imgAreaC = { null, null, null, null }; | |
423 // transform user coordinate area to image coordinate area | |
424 imgTrafo.transform(userAreaC, 0, imgAreaC, 0, 4); | |
425 areaXoff = imgAreaC[0].getX(); | |
426 areaYoff = imgAreaC[0].getY(); | |
427 // calculate scaling factors | |
73 | 428 if (scaleToFit) { |
85 | 429 areaWidth = imgAreaC[0].distance(imgAreaC[1]); |
430 areaHeight = imgAreaC[0].distance(imgAreaC[2]); | |
73 | 431 scaleX = paramDW / areaWidth * paramWS; |
432 scaleY = paramDH / areaHeight * paramWS; | |
433 scaleXY = (scaleX > scaleY) ? scaleY : scaleX; | |
434 } else { | |
435 // crop to fit | |
85 | 436 areaWidth = paramDW * paramWS; |
437 areaHeight = paramDH * paramWS; | |
73 | 438 scaleX = 1f; |
439 scaleY = 1f; | |
440 scaleXY = 1f; | |
85 | 441 |
73 | 442 } |
1 | 443 |
73 | 444 util.dprintln( |
445 1, | |
446 "Scale " | |
447 + scaleXY | |
448 + "(" | |
449 + scaleX | |
450 + "," | |
451 + scaleY | |
452 + ") on " | |
453 + areaXoff | |
454 + "," | |
455 + areaYoff | |
456 + " " | |
457 + areaWidth | |
458 + "x" | |
459 + areaHeight); | |
1 | 460 |
73 | 461 // clip area at the image border |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
462 /* areaWidth = |
73 | 463 (areaXoff + areaWidth > imgWidth) |
464 ? imgWidth - areaXoff | |
465 : areaWidth; | |
466 areaHeight = | |
467 (areaYoff + areaHeight > imgHeight) | |
468 ? imgHeight - areaYoff | |
469 : areaHeight; | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
470 */ |
85 | 471 |
472 // create new rectangle from coordinates | |
473 Rectangle2D imgArea = | |
474 new Rectangle2D.Double( | |
475 areaXoff, | |
476 areaYoff, | |
477 areaWidth, | |
478 areaHeight); | |
479 // clip area at the image border | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
480 imgArea = imgArea.createIntersection(imgBounds); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
481 areaWidth = imgArea.getWidth(); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
482 areaHeight = imgArea.getHeight(); |
1 | 483 |
73 | 484 util.dprintln( |
485 2, | |
85 | 486 "crop: " |
73 | 487 + areaXoff |
488 + "," | |
489 + areaYoff | |
490 + " " | |
491 + areaWidth | |
492 + "x" | |
493 + areaHeight); | |
1 | 494 |
73 | 495 // check image parameters sanity |
496 if ((areaWidth < 1) | |
497 || (areaHeight < 1) | |
498 || (scaleXY * areaWidth < 2) | |
499 || (scaleXY * areaHeight < 2)) { | |
500 util.dprintln(1, "ERROR: invalid scale parameter set!"); | |
501 throw new ImageOpException("Invalid scale parameter set!"); | |
502 } | |
1 | 503 |
85 | 504 /* |
505 * crop and scale image | |
506 */ | |
507 | |
508 // use subimage loading if possible | |
509 if (docuImage.isSubimageSupported()) { | |
510 System.out.println( | |
511 "Subimage: scale " + scaleXY + " = " + (1 / scaleXY)); | |
512 double subf = 1d; | |
513 double subsamp = 1d; | |
514 if (scaleXY < 1) { | |
515 subf = 1 / scaleXY; | |
516 subsamp = Math.floor(subf); | |
517 scaleXY = subsamp / subf; | |
518 System.out.println( | |
519 "Using subsampling: " + subsamp + " rest " + scaleXY); | |
520 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
521 |
85 | 522 docuImage.loadSubimage( |
523 fileToLoad, | |
524 imgArea.getBounds(), | |
525 (int) subsamp); | |
526 | |
527 System.out.println( | |
528 "SUBSAMP: " | |
529 + subsamp | |
530 + " -> " | |
531 + docuImage.getWidth() | |
532 + "x" | |
533 + docuImage.getHeight()); | |
534 | |
535 docuImage.scale(scaleXY); | |
536 | |
537 } else { | |
538 docuImage.crop( | |
539 (int) areaXoff, | |
540 (int) areaYoff, | |
541 (int) areaWidth, | |
542 (int) areaHeight); | |
543 | |
544 docuImage.scale(scaleXY); | |
545 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
546 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
547 // mirror image |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
548 if (doMirror) { |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
549 docuImage.mirror(mirrorAngle); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
550 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
551 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
552 // rotate image (first shot :-) |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
553 if (paramROT != 0) { |
85 | 554 docuImage.rotate( |
555 paramROT); | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
556 } |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
557 |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
558 // contrast and brightness enhancement |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
559 if ((paramCONT != 0) || (paramBRGT != 0)) { |
85 | 560 double mult = Math.pow(2, paramCONT); |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
561 docuImage.enhance(mult, paramBRGT); |
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
562 } |
1 | 563 |
73 | 564 util.dprintln( |
565 2, | |
566 "time " + (System.currentTimeMillis() - startTime) + "ms"); | |
567 | |
568 /* | |
569 * write the resulting image | |
570 */ | |
1 | 571 |
73 | 572 // setup output -- if source is JPG then dest will be JPG else it's PNG |
573 if (mimeType != "image/jpeg") { | |
574 mimeType = "image/png"; | |
575 } | |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
576 response.setContentType(mimeType); |
1 | 577 |
73 | 578 // write the image |
79
63c8186455c1
Servlet version 1.6b. Further cleanup and new functionality:
robcast
parents:
73
diff
changeset
|
579 docuImage.writeImage(mimeType, response.getOutputStream()); |
1 | 580 |
73 | 581 util.dprintln( |
582 1, | |
583 "Done in " + (System.currentTimeMillis() - startTime) + "ms"); | |
584 | |
585 /* | |
586 * error handling | |
587 */ | |
1 | 588 |
73 | 589 } // end of "big" try |
590 catch (FileOpException e) { | |
591 util.dprintln(1, "ERROR: File IO Error: " + e); | |
592 try { | |
593 if (errorMsgHtml) { | |
594 ServletOps.htmlMessage( | |
595 "ERROR: File IO Error: " + e, | |
596 response); | |
597 } else { | |
598 servletOp.sendFile( | |
599 new File(dlConfig.getErrorImgFileName()), | |
600 response); | |
601 } | |
602 } catch (FileOpException ex) { | |
603 } // so we don't get a loop | |
604 return; | |
605 } catch (AuthOpException e) { | |
606 util.dprintln(1, "ERROR: Authorization error: " + e); | |
607 try { | |
608 if (errorMsgHtml) { | |
609 ServletOps.htmlMessage( | |
610 "ERROR: Authorization error: " + e, | |
611 response); | |
612 } else { | |
613 servletOp.sendFile( | |
614 new File(dlConfig.getErrorImgFileName()), | |
615 response); | |
616 } | |
617 } catch (FileOpException ex) { | |
618 } // so we don't get a loop | |
619 return; | |
620 } catch (ImageOpException e) { | |
621 util.dprintln(1, "ERROR: Image Error: " + e); | |
622 try { | |
623 if (errorMsgHtml) { | |
624 ServletOps.htmlMessage( | |
625 "ERROR: Image Operation Error: " + e, | |
626 response); | |
627 } else { | |
628 servletOp.sendFile( | |
629 new File(dlConfig.getErrorImgFileName()), | |
630 response); | |
631 } | |
632 } catch (FileOpException ex) { | |
633 } // so we don't get a loop | |
634 return; | |
635 } catch (RuntimeException e) { | |
636 // JAI likes to throw RuntimeExceptions ;-( | |
637 util.dprintln(1, "ERROR: Other Image Error: " + e); | |
638 try { | |
639 if (errorMsgHtml) { | |
640 ServletOps.htmlMessage( | |
641 "ERROR: Other Image Operation Error: " + e, | |
642 response); | |
643 } else { | |
644 servletOp.sendFile( | |
645 new File(dlConfig.getErrorImgFileName()), | |
646 response); | |
647 } | |
648 } catch (FileOpException ex) { | |
649 } // so we don't get a loop | |
650 return; | |
651 } | |
652 } | |
1 | 653 |
73 | 654 } //Scaler class |