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