Mercurial > hg > digilib-old
view servlet/src/digilib/servlet/DigilibImageWorker.java @ 296:0a212bc468ad
Servlet version 1.5.0b -- the beginning of the next generation :-)
- code restructuring to improve scaleability
- new Initialiser servlet that must be run first
- image transformation work moved to DigilibImageWorker class
- Maximum number of concurrent threads limited by Semaphore
- old JIMI toolkit implementation removed
author | robcast |
---|---|
date | Sun, 24 Oct 2004 20:23:50 +0200 |
parents | |
children | 3baaf11898d2 |
line wrap: on
line source
/* DigilibImageWorker.java -- worker for image operations * * Digital Image Library servlet components * * Copyright (C) 2004 Robert Casties (robcast@mail.berlios.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * Please read license.txt for the full details. A copy of the GPL may be found * at http://www.gnu.org/copyleft/lgpl.html * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * Created on 19.10.2004 */ package digilib.servlet; import java.awt.geom.Rectangle2D; import java.io.IOException; import javax.servlet.http.HttpServletResponse; import digilib.image.DocuImage; import digilib.image.ImageOpException; import digilib.io.FileOpException; import digilib.io.ImageFile; /** * worker for image operations. * * @author casties * */ public class DigilibImageWorker extends DigilibWorker { private DigilibConfiguration dlConfig; HttpServletResponse response; long startTime; String mimeType; int scaleQual; DigilibRequest dlRequest; float paramROT; float paramCONT; float paramBRGT; float[] paramRGBM; float[] paramRGBA; ImageFile fileToLoad; float areaXoff; float areaYoff; float areaWidth; float areaHeight; float scaleXY; Rectangle2D outerUserImgArea; Rectangle2D innerUserImgArea; float minSubsample; boolean wholeRotArea; /** * @param dlConfig * @param response * @param mimeType * @param scaleQual * @param dlRequest * @param paramROT * @param paramCONT * @param paramBRGT * @param paramRGBM * @param paramRGBA * @param fileToLoad * @param areaXoff * @param outerUserImgArea * @param innerUserImgArea * @param minSubsample * @param wholeRotArea */ public DigilibImageWorker(DigilibConfiguration dlConfig, HttpServletResponse response, String mimeType, int scaleQual, DigilibRequest dlRequest, float paramROT, float paramCONT, float paramBRGT, float[] paramRGBM, float[] paramRGBA, ImageFile fileToLoad, float scaleXY, Rectangle2D outerUserImgArea, Rectangle2D innerUserImgArea, float minSubsample, boolean wholeRotArea) { super(); this.dlConfig = dlConfig; this.response = response; this.mimeType = mimeType; this.scaleQual = scaleQual; this.dlRequest = dlRequest; this.paramROT = paramROT; this.paramCONT = paramCONT; this.paramBRGT = paramBRGT; this.paramRGBM = paramRGBM; this.paramRGBA = paramRGBA; this.fileToLoad = fileToLoad; this.scaleXY = scaleXY; this.outerUserImgArea = outerUserImgArea; this.innerUserImgArea = innerUserImgArea; this.minSubsample = minSubsample; this.wholeRotArea = wholeRotArea; } /* * do the work */ public void work() throws FileOpException, IOException, ImageOpException { ; logger.debug("image worker " + this.getName() + " working"); startTime = System.currentTimeMillis(); /* crop and scale image */ // new DocuImage instance DocuImage docuImage = dlConfig.getDocuImageInstance(); if (docuImage == null) { throw new ImageOpException("Unable to load DocuImage class!"); } // set interpolation quality docuImage.setQuality(scaleQual); // use subimage loading if possible if (docuImage.isSubimageSupported()) { logger.debug("Subimage: scale " + scaleXY + " = " + (1 / scaleXY)); float subf = 1f; float subsamp = 1f; if (scaleXY < 1) { subf = 1 / scaleXY; // for higher quality reduce subsample factor by // minSubsample if (scaleQual > 0) { subsamp = (float) Math.max(Math.floor(subf / minSubsample), 1d); } else { subsamp = (float) Math.floor(subf); } scaleXY = subsamp / subf; logger.debug("Using subsampling: " + subsamp + " rest " + scaleXY); } docuImage.loadSubimage(fileToLoad, outerUserImgArea.getBounds(), (int) subsamp); logger.debug("SUBSAMP: " + subsamp + " -> " + docuImage.getWidth() + "x" + docuImage.getHeight()); docuImage.scale(scaleXY, scaleXY); } else { // else load and crop the whole file docuImage.loadImage(fileToLoad); docuImage.crop((int) areaXoff, (int) areaYoff, (int) areaWidth, (int) areaHeight); docuImage.scale(scaleXY, scaleXY); } // mirror image // operation mode: "hmir": mirror horizontally, "vmir": mirror // vertically if (dlRequest.hasOption("mo", "hmir")) { docuImage.mirror(0); } if (dlRequest.hasOption("mo", "vmir")) { docuImage.mirror(90); } // rotate image if (paramROT != 0d) { docuImage.rotate(paramROT); if (wholeRotArea) { // crop to the inner bounding box float xcrop = (float) (docuImage.getWidth() - innerUserImgArea .getWidth() * scaleXY); float ycrop = (float) (docuImage.getHeight() - innerUserImgArea .getHeight() * scaleXY); if ((xcrop > 0) || (ycrop > 0)) { // only crop smaller xcrop = (xcrop > 0) ? xcrop : 0; ycrop = (ycrop > 0) ? ycrop : 0; // crop image docuImage.crop((int) (xcrop / 2), (int) (ycrop / 2), (int) (docuImage.getWidth() - xcrop), (int) (docuImage.getHeight() - ycrop)); } } } // color modification if ((paramRGBM != null) || (paramRGBA != null)) { // make shure we actually have two arrays if (paramRGBM == null) { paramRGBM = new float[3]; } if (paramRGBA == null) { paramRGBA = new float[3]; } // calculate "contrast" values (c=2^x) float[] mult = new float[3]; for (int i = 0; i < 3; i++) { mult[i] = (float) Math.pow(2, (float) paramRGBM[i]); } docuImage.enhanceRGB(mult, paramRGBA); } // contrast and brightness enhancement if ((paramCONT != 0f) || (paramBRGT != 0f)) { float mult = (float) Math.pow(2, paramCONT); docuImage.enhance(mult, paramBRGT); } logger.debug("time " + (System.currentTimeMillis() - startTime) + "ms"); /* write the resulting image */ // setup output -- if source is JPG then dest will be JPG else it's // PNG if (mimeType.equals("image/jpeg") || mimeType.equals("image/jp2")) { mimeType = "image/jpeg"; } else { mimeType = "image/png"; } response.setContentType(mimeType); // write the image docuImage.writeImage(mimeType, response.getOutputStream()); response.flushBuffer(); logger.info("image worker " + this.getName() + " done in " + (System.currentTimeMillis() - startTime)); docuImage.dispose(); } }