diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java index 2ab3ef319..0976345ce 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/application/ApplicationImpl.java @@ -6,7 +6,9 @@ import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.Application; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; import edu.cornell.mannlib.vitro.webapp.searchengine.SearchEngineWrapper; import edu.cornell.mannlib.vitro.webapp.searchengine.solr.SolrSearchEngine; @@ -22,6 +24,7 @@ public class ApplicationImpl implements Application { private final ServletContext ctx; private SearchEngine searchEngine; + private ImageProcessor imageProcessor; public ApplicationImpl(ServletContext ctx) { this.ctx = ctx; @@ -41,10 +44,18 @@ public class ApplicationImpl implements Application { this.searchEngine = searchEngine; } + public ImageProcessor getImageProcessor() { + return imageProcessor; + } + + public void setImageProcessor(ImageProcessor imageProcessor) { + this.imageProcessor = imageProcessor; + } + // ---------------------------------------------------------------------- // The Setup class. // ---------------------------------------------------------------------- - + public static class Setup implements ServletContextListener { @Override @@ -53,11 +64,15 @@ public class ApplicationImpl implements Application { StartupStatus ss = StartupStatus.getBean(ctx); try { + ApplicationImpl application = new ApplicationImpl(ctx); + SearchEngine searchEngine = new SearchEngineWrapper( new SolrSearchEngine()); - - ApplicationImpl application = new ApplicationImpl(ctx); application.setSearchEngine(searchEngine); + + ImageProcessor imageProcessor = new JaiImageProcessor(); + application.setImageProcessor(imageProcessor); + ApplicationUtils.setInstance(application); ss.info(this, "Appliation is configured."); } catch (Exception e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadController.java index 7daf6c025..defbdf153 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadController.java @@ -32,6 +32,8 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup; import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo; import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo; import edu.cornell.mannlib.vitro.webapp.i18n.I18n; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil; /** @@ -583,54 +585,6 @@ public class ImageUploadController extends FreemarkerHttpServlet { } } - /** - * Holds the coordinates that we use to crop the main image. - */ - public static class CropRectangle { - public final int x; - public final int y; - public final int height; - public final int width; - - public CropRectangle(int x, int y, int height, int width) { - this.x = x; - this.y = y; - this.height = height; - this.width = width; - } - - /** Produce a new crop rectangle that compensates for scaling. */ - public CropRectangle unscale(float scale) { - int newX = (int) (x / scale); - int newY = (int) (y / scale); - int newHeight = (int) (height / scale); - int newWidth = (int) (width / scale); - return new CropRectangle(newX, newY, newHeight, newWidth); - } - - @Override - public String toString() { - return "CropRectangle[x=" + x + ", y=" + y + ", w=" + width - + ", h=" + height + "]"; - } - - } - - static class Dimensions { - final int width; - final int height; - - Dimensions(int width, int height) { - this.width = width; - this.height = height; - } - - @Override - public String toString() { - return "Dimensions[width=" + width + ", height=" + height + "]"; - } - } - private String getDefaultNamespace() { return ConfigurationProperties.getBean(getServletContext()) .getProperty("Vitro.defaultNamespace"); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadHelper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadHelper.java index 3528ecc35..63ded19f4 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadHelper.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadHelper.java @@ -14,9 +14,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.media.jai.JAI; -import javax.media.jai.RenderedOp; -import javax.media.jai.util.ImagingListener; import javax.servlet.ServletContext; import org.apache.commons.fileupload.FileItem; @@ -24,12 +21,9 @@ import org.apache.commons.io.FilenameUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import com.sun.media.jai.codec.MemoryCacheSeekableStream; - +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.Dimensions; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.UserMistakeException; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.filestorage.TempFileHolder; @@ -37,6 +31,9 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.UploadedFileHelper; import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileAlreadyExistsException; import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage; import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.ImageProcessorException; /** * Handle the mechanics of validating, storing, and deleting file images. @@ -95,15 +92,6 @@ public class ImageUploadHelper { return Collections.unmodifiableMap(map); } - /* - * Prevent Java Advanced Imaging from complaining about the lack of - * accelerator classes. - */ - static { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); - } - private final FileStorage fileStorage; private final UploadedFileHelper uploadedFileHelper; @@ -206,12 +194,8 @@ public class ImageUploadHelper { String filename = fileInfo.getFilename(); source = fileStorage.getInputStream(uri, filename); - MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream( - source); - RenderedOp image = JAI.create("stream", stream); - - Dimensions size = new Dimensions(image.getWidth(), - image.getHeight()); + Dimensions size = ApplicationUtils.instance().getImageProcessor() + .getDimensions(source); log.debug("new image size is " + size); if ((size.height < THUMBNAIL_HEIGHT) @@ -272,8 +256,11 @@ public class ImageUploadHelper { mainStream = fileStorage.getInputStream(mainBytestreamUri, mainFilename); - thumbStream = new ImageUploadThumbnailer(THUMBNAIL_HEIGHT, - THUMBNAIL_WIDTH).cropAndScale(mainStream, crop); + thumbStream = ApplicationUtils + .instance() + .getImageProcessor() + .cropAndScale(mainStream, crop, + new Dimensions(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)); String mimeType = RECOGNIZED_FILE_TYPES.get(".jpg"); String filename = createThumbnailFilename(mainFilename); @@ -288,6 +275,8 @@ public class ImageUploadHelper { } catch (IOException e) { throw new IllegalStateException("Can't create the thumbnail file", e); + } catch (ImageProcessorException e) { + throw new IllegalStateException("Failed to scale the image", e); } finally { if (mainStream != null) { try { @@ -375,35 +364,4 @@ public class ImageUploadHelper { return prefix + filename.substring(0, periodHere) + extension; } } - - /** - *

- * This {@link ImagingListener} means that Java Advanced Imaging won't dump - * an exception log to {@link System#out}. It writes to the log, instead. - *

- *

- * Further, since the lack of native accelerator classes isn't an error, it - * is written as a simple log message. - *

- */ - static class NonNoisyImagingListener implements ImagingListener { - @Override - public boolean errorOccurred(String message, Throwable thrown, - Object where, boolean isRetryable) throws RuntimeException { - if (thrown instanceof RuntimeException) { - throw (RuntimeException) thrown; - } - if ((thrown instanceof NoClassDefFoundError) - && (thrown.getMessage() - .contains("com/sun/medialib/mlib/Image"))) { - log.info("Java Advanced Imaging: Could not find mediaLib " - + "accelerator wrapper classes. " - + "Continuing in pure Java mode."); - return false; - } - log.error(thrown, thrown); - return false; - } - - } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadThumbnailer.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java similarity index 70% rename from webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadThumbnailer.java rename to webapp/src/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java index 68c585af6..6162e33fb 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploadThumbnailer.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessor.java @@ -1,6 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package edu.cornell.mannlib.vitro.webapp.controller.freemarker; +package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; import java.awt.geom.AffineTransform; import java.awt.image.AffineTransformOp; @@ -12,16 +12,20 @@ import java.io.IOException; import java.io.InputStream; import javax.imageio.ImageIO; +import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import javax.media.jai.operator.BandSelectDescriptor; import javax.media.jai.operator.StreamDescriptor; +import javax.media.jai.util.ImagingListener; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.sun.media.jai.codec.MemoryCacheSeekableStream; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.Application; +import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; /** * Crop the main image as specified, and scale it to the correct size for a @@ -41,30 +45,44 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadControl * * Use the javax.imagio pacakge to write the thumbnail image as a JPEG file. */ -public class ImageUploadThumbnailer { +public class JaiImageProcessor implements ImageProcessor { + private static final Log log = LogFactory.getLog(JaiImageProcessor.class); + /** If an image has 3 color bands and 1 alpha band, we want these. */ private static final int[] COLOR_BAND_INDEXES = new int[] { 0, 1, 2 }; - private static final Log log = LogFactory - .getLog(ImageUploadThumbnailer.class); + /** + * Prevent Java Advanced Imaging from complaining about the lack of + * accelerator classes. + */ + @Override + public void startup(Application application, ComponentStartupStatus ss) { + JAI.getDefaultInstance().setImagingListener( + new NonNoisyImagingListener()); + } - /** We won't let you crop to smaller than this many pixels wide or high. */ - private static final int MINIMUM_CROP_SIZE = 5; + @Override + public void shutdown(Application application) { + // Nothing to tear down. + } - private final int thumbnailHeight; - private final int thumbnailWidth; - - public ImageUploadThumbnailer(int thumbnailHeight, int thumbnailWidth) { - this.thumbnailHeight = thumbnailHeight; - this.thumbnailWidth = thumbnailWidth; + @Override + public Dimensions getDimensions(InputStream imageStream) + throws ImageProcessorException, IOException { + MemoryCacheSeekableStream stream = new MemoryCacheSeekableStream( + imageStream); + RenderedOp image = JAI.create("stream", stream); + return new Dimensions(image.getWidth(), image.getHeight()); } /** * Crop the main image according to this rectangle, and scale it to the * correct size for a thumbnail. */ + @Override public InputStream cropAndScale(InputStream mainImageStream, - CropRectangle crop) { + CropRectangle crop, Dimensions limits) + throws ImageProcessorException, IOException { try { RenderedOp mainImage = loadImage(mainImageStream); RenderedOp opaqueImage = makeImageOpaque(mainImage); @@ -77,7 +95,7 @@ public class ImageUploadThumbnailer { bufferedImage, crop); log.debug("bounded crop: " + boundedCrop); - float scaleFactor = figureScaleFactor(boundedCrop); + float scaleFactor = figureScaleFactor(boundedCrop, limits); log.debug("scale factor: " + scaleFactor); BufferedImage scaledImage = scaleImage(bufferedImage, scaleFactor); @@ -100,10 +118,6 @@ public class ImageUploadThumbnailer { } } - private String imageSize(BufferedImage image) { - return image.getWidth() + " by " + image.getHeight(); - } - private RenderedOp loadImage(InputStream imageStream) { return StreamDescriptor.create(new MemoryCacheSeekableStream( imageStream), null, null); @@ -127,6 +141,10 @@ public class ImageUploadThumbnailer { return image; } + private String imageSize(BufferedImage image) { + return image.getWidth() + " by " + image.getHeight(); + } + private CropRectangle limitCropRectangleToImageBounds(BufferedImage image, CropRectangle crop) { @@ -150,18 +168,14 @@ public class ImageUploadThumbnailer { return new CropRectangle(x, y, h, w); } - private float figureScaleFactor(CropRectangle boundedCrop) { - float horizontalScale = ((float) thumbnailWidth) + private float figureScaleFactor(CropRectangle boundedCrop, Dimensions limits) { + float horizontalScale = ((float) limits.width) / ((float) boundedCrop.width); - float verticalScale = ((float) thumbnailHeight) + float verticalScale = ((float) limits.height) / ((float) boundedCrop.height); return Math.min(horizontalScale, verticalScale); } - private BufferedImage cropImage(BufferedImage image, CropRectangle crop) { - return image.getSubimage(crop.x, crop.y, crop.width, crop.height); - } - private BufferedImage scaleImage(BufferedImage image, float scaleFactor) { AffineTransform transform = AffineTransform.getScaleInstance( scaleFactor, scaleFactor); @@ -178,9 +192,42 @@ public class ImageUploadThumbnailer { return new CropRectangle(newX, newY, newHeight, newWidth); } + private BufferedImage cropImage(BufferedImage image, CropRectangle crop) { + return image.getSubimage(crop.x, crop.y, crop.width, crop.height); + } + private byte[] encodeAsJpeg(BufferedImage image) throws IOException { ByteArrayOutputStream bytes = new ByteArrayOutputStream(); ImageIO.write(image, "JPG", bytes); return bytes.toByteArray(); } + + /** + * This ImagingListener means that Java Advanced Imaging won't dump an + * exception log to System.out. It writes to the log, instead. + * + * Further, since the lack of native accelerator classes isn't an error, it + * is written as a simple log message. + */ + static class NonNoisyImagingListener implements ImagingListener { + @Override + public boolean errorOccurred(String message, Throwable thrown, + Object where, boolean isRetryable) throws RuntimeException { + if (thrown instanceof RuntimeException) { + throw (RuntimeException) thrown; + } + if ((thrown instanceof NoClassDefFoundError) + && (thrown.getMessage() + .contains("com/sun/medialib/mlib/Image"))) { + log.info("Java Advanced Imaging: Could not find mediaLib " + + "accelerator wrapper classes. " + + "Continuing in pure Java mode."); + return false; + } + log.error(thrown, thrown); + return false; + } + + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java index cbe44766d..f9204e4e2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/Application.java @@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.modules; import javax.servlet.ServletContext; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; /** @@ -14,6 +15,8 @@ public interface Application { SearchEngine getSearchEngine(); + ImageProcessor getImageProcessor(); + public interface Component { enum LifecycleState { NEW, ACTIVE, STOPPED diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/imageProcessor/ImageProcessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/imageProcessor/ImageProcessor.java new file mode 100644 index 000000000..f11f51b13 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/modules/imageProcessor/ImageProcessor.java @@ -0,0 +1,117 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.modules.imageProcessor; + +import java.io.IOException; +import java.io.InputStream; + +import edu.cornell.mannlib.vitro.webapp.modules.Application; + +/** + * Handle image processing for VIVO; uploads and thumbnailing. + */ +public interface ImageProcessor extends Application.Module { + + /** + * We won't let you crop to smaller than this many pixels wide or high. + */ + public static final int MINIMUM_CROP_SIZE = 5; + + /** + * How big is the image contained in this stream? + * + * @param image + * The image stream. This method will not close it. + * @return The dimensions of the image. Never returns null. + * @throws ImageProcessorException + * if the stream does not contain a valid image. + * @throws IOException + * if the stream cannot be read. + */ + Dimensions getDimensions(InputStream image) throws ImageProcessorException, + IOException; + + /** + * Create a new image from a portion of the supplied image, and reduce to + * fit a limiting size. + * + * If the crop rectangle extends beyond the image boundaries, it is limited + * to fit, or relocated if limiting would make it smaller than the + * MINIMUM_CROP_SIZE. + * + * @param image + * The image stream. This method will not close it. + * @param crop + * x and y determine the upper left corner of the crop area. + * height and width determine the size of the crop area. + * @param limits + * The resulting image will be reduced as necessary to fit within + * these dimensions. + * @return The new image. Client code should close this stream after + * reading. Never returns null. + * @throws ImageProcessorException + * If the image is smaller than the minimum crop size, or if + * there is another problem cropping the image. + * @throws IOException + * if the image stream cannot be read. + */ + InputStream cropAndScale(InputStream image, CropRectangle crop, + Dimensions limits) throws ImageProcessorException, IOException; + + /** + * A problem with the image. + */ + public static class ImageProcessorException extends Exception { + public ImageProcessorException(String message) { + super(message); + } + + public ImageProcessorException(String message, Throwable cause) { + super(message, cause); + } + } + + /** + * The size of a rectangular image, in pixels. + */ + public static class Dimensions { + public final int width; + public final int height; + + public Dimensions(int width, int height) { + this.width = width; + this.height = height; + } + + @Override + public String toString() { + return "ImageProcessor.Dimensions[width=" + width + ", height=" + + height + "]"; + } + } + + /** + * Holds the coordinates that we use to crop an image. + */ + public static class CropRectangle { + public final int x; + public final int y; + public final int height; + public final int width; + + public CropRectangle(int x, int y, int height, int width) { + this.x = x; + this.y = y; + this.height = height; + this.width = width; + } + + @Override + public String toString() { + return "CropRectangle[x=" + x + ", y=" + y + ", w=" + width + + ", h=" + height + "]"; + } + + } + +} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java similarity index 81% rename from webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester.java rename to webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java index b51b1db35..aeb2092ae 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester.java @@ -1,6 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package edu.cornell.mannlib.vitro.webapp.controller.freemarker; +package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_HEIGHT; import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.THUMBNAIL_WIDTH; @@ -17,7 +17,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import javax.media.jai.operator.StreamDescriptor; @@ -26,7 +25,9 @@ import org.apache.log4j.Logger; import com.sun.media.jai.codec.MemoryCacheSeekableStream; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadHelper.NonNoisyImagingListener; +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; /** * This is not a unit test, so it is not named BlahBlahTest. @@ -38,14 +39,13 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadHelper. * This is especially true because the images on the screen look color-correct, * but when viewed in the browser, they might not be. */ -public class ImageUploaderThumbnailerTester extends Frame { - static { - JAI.getDefaultInstance().setImagingListener( - new NonNoisyImagingListener()); - } +public class JaiImageProcessorTester extends Frame { /** Big enough to hold the JPEG file, certainly. */ private final static int BUFFER_SIZE = 200 * 200 * 4; + + private final static Dimensions THUMBNAIL_SIZE = new Dimensions( + THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT); private final static ImageCropData[] THUMBNAIL_DATA = new ImageCropData[] { new ImageCropData("/Users/jeb228/Pictures/JimBlake_20010915.jpg", @@ -56,11 +56,10 @@ public class ImageUploaderThumbnailerTester extends Frame { new ImageCropData("/Users/jeb228/Pictures/DSC04203w-trans.gif", 400, 1200, 800) }; - private final ImageUploadThumbnailer thumbnailer = new ImageUploadThumbnailer( - THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH); + private final JaiImageProcessor thumbnailer = new JaiImageProcessor(); @SuppressWarnings("deprecation") - private ImageUploaderThumbnailerTester() { + private JaiImageProcessorTester() { setTitle("Alpha Killer Test"); addWindowListener(new CloseWindowListener()); setLayout(createLayout()); @@ -68,7 +67,7 @@ public class ImageUploaderThumbnailerTester extends Frame { try { InputStream mainStream = new FileInputStream(icd.filename); File thumbFile = writeToTempFile(thumbnailer.cropAndScale( - mainStream, icd.crop)); + mainStream, icd.crop, THUMBNAIL_SIZE)); System.out.println(thumbFile.getAbsolutePath()); MemoryCacheSeekableStream thumbFileStream = new MemoryCacheSeekableStream( @@ -108,18 +107,19 @@ public class ImageUploaderThumbnailerTester extends Frame { return layout; } + @SuppressWarnings("unused") public static void main(String[] args) { - Logger.getLogger(ImageUploadThumbnailer.class).setLevel(Level.DEBUG); - new ImageUploaderThumbnailerTester(); + Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); + new JaiImageProcessorTester(); } private static class ImageCropData { final String filename; - final ImageUploadController.CropRectangle crop; + final CropRectangle crop; ImageCropData(String filename, int x, int y, int size) { this.filename = filename; - this.crop = new ImageUploadController.CropRectangle(x, y, size, + this.crop = new CropRectangle(x, y, size, size); } } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java similarity index 87% rename from webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java rename to webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java index aef00d0ac..0def41eec 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/imageprocessor/jai/JaiImageProcessorTester2.java @@ -1,6 +1,6 @@ /* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package edu.cornell.mannlib.vitro.webapp.controller.freemarker; +package edu.cornell.mannlib.vitro.webapp.imageprocessor.jai; import java.awt.BorderLayout; import java.awt.Color; @@ -35,9 +35,10 @@ import org.apache.log4j.PatternLayout; import com.sun.media.jai.codec.MemoryCacheSeekableStream; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.CropRectangle; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadHelper.NonNoisyImagingListener; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploaderThumbnailerTester_2.CropDataSet.CropData; +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessorTester2.CropDataSet.CropData; +import edu.cornell.mannlib.vitro.webapp.imageprocessor.jai.JaiImageProcessor.NonNoisyImagingListener; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.CropRectangle; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor.Dimensions; /** * This is not a unit test, so it is not named BlahBlahTest. @@ -49,14 +50,16 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploaderThumb * one or more black edges on the thumbnails. */ @SuppressWarnings("deprecation") -public class ImageUploaderThumbnailerTester_2 extends Frame { +public class JaiImageProcessorTester2 extends Frame { private static final Log log = LogFactory - .getLog(ImageUploaderThumbnailerTester_2.class); + .getLog(JaiImageProcessorTester2.class); private static final int ROWS = 6; private static final int COLUMNS = 9; private static final int EDGE_THRESHOLD = 6000; + + private static final Dimensions THUMBNAIL_SIZE = new Dimensions(200, 200); /** Keep things quiet. */ static { @@ -65,12 +68,12 @@ public class ImageUploaderThumbnailerTester_2 extends Frame { } private final String imagePath; - private final ImageUploadThumbnailer thumbnailer; + private final JaiImageProcessor thumbnailer; - public ImageUploaderThumbnailerTester_2(String imagePath, + public JaiImageProcessorTester2(String imagePath, CropDataSet cropDataSet) { this.imagePath = imagePath; - this.thumbnailer = new ImageUploadThumbnailer(200, 200); + this.thumbnailer = new JaiImageProcessor(); setTitle("Cropping edging test"); addWindowListener(new CloseWindowListener()); @@ -119,7 +122,7 @@ public class ImageUploaderThumbnailerTester_2 extends Frame { CropRectangle rectangle = new CropRectangle(cropData.left, cropData.top, cropData.size, cropData.size); InputStream thumbnailStream = thumbnailer.cropAndScale(mainStream, - rectangle); + rectangle, THUMBNAIL_SIZE); return StreamDescriptor.create(new MemoryCacheSeekableStream( thumbnailStream), null, null); @@ -200,8 +203,8 @@ public class ImageUploaderThumbnailerTester_2 extends Frame { .nextElement(); appender.setLayout(new PatternLayout("%-5p [%c{1}] %m%n")); - Logger.getLogger(ImageUploadThumbnailer.class).setLevel(Level.DEBUG); - Logger.getLogger(ImageUploaderThumbnailerTester_2.class).setLevel( + Logger.getLogger(JaiImageProcessor.class).setLevel(Level.DEBUG); + Logger.getLogger(JaiImageProcessorTester2.class).setLevel( Level.INFO); CropDataSet cropDataSet = new CropDataSet(); @@ -210,7 +213,7 @@ public class ImageUploaderThumbnailerTester_2 extends Frame { cropDataSet.add(0, 0, 201 + i); } - new ImageUploaderThumbnailerTester_2( + new JaiImageProcessorTester2( "C:/Users/jeb228/Pictures/wheel.png", cropDataSet); // new ImageUploaderThumbnailerTester_2( diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java index 39f2e892b..3ee963605 100644 --- a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java +++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/modules/ApplicationStub.java @@ -8,6 +8,7 @@ import javax.servlet.ServletContext; import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import edu.cornell.mannlib.vitro.webapp.modules.Application; +import edu.cornell.mannlib.vitro.webapp.modules.imageProcessor.ImageProcessor; import edu.cornell.mannlib.vitro.webapp.modules.searchEngine.SearchEngine; /** @@ -58,4 +59,11 @@ public class ApplicationStub implements Application { // ---------------------------------------------------------------------- // Un-implemented methods // ---------------------------------------------------------------------- + + @Override + public ImageProcessor getImageProcessor() { + throw new RuntimeException( + "ApplicationStub.getImageProcessor() not implemented."); + + } }