mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Update dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java
Adds high quality scaling and blurring options for thumbnails. Boolean options thumbnail.blurring and thumbnail.hqscaling need to be added to dspace.cfg for behavior to change.
This commit is contained in:
@@ -8,7 +8,9 @@
|
||||
package org.dspace.app.mediafilter;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.*;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Transparency;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
@@ -71,6 +73,10 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
.getIntProperty("thumbnail.maxwidth");
|
||||
float ymax = (float) ConfigurationManager
|
||||
.getIntProperty("thumbnail.maxheight");
|
||||
boolean blurring = (boolean) ConfigurationManager
|
||||
.getBooleanProperty("thumbnail.blurring");
|
||||
boolean hqscaling = (boolean) ConfigurationManager
|
||||
.getBooleanProperty("thumbnail.hqscaling");
|
||||
|
||||
// now get the image dimensions
|
||||
float xsize = (float) buf.getWidth(null);
|
||||
@@ -131,6 +137,23 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
BufferedImage thumbnail = new BufferedImage((int) xsize, (int) ysize,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
// Use blurring if selected in config.
|
||||
// a little blur before scaling does wonders for keeping moire in check.
|
||||
if (blurring)
|
||||
{
|
||||
// send the buffered image off to get blurred.
|
||||
buf = getBlurredInstance((BufferedImage) buf);
|
||||
}
|
||||
|
||||
// Use high quality scaling method if selected in config.
|
||||
// this has a definite performance penalty.
|
||||
if (hqscaling)
|
||||
{
|
||||
// send the buffered image off to get an HQ downscale.
|
||||
buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize,
|
||||
(Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true);
|
||||
}
|
||||
|
||||
// now render the image into the thumbnail buffer
|
||||
Graphics2D g2d = thumbnail.createGraphics();
|
||||
g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null);
|
||||
@@ -163,4 +186,97 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats
|
||||
// return ImageIO.getReaderFileSuffixes();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage getBlurredInstance(BufferedImage buf)
|
||||
{
|
||||
/**
|
||||
* Convenience method that returns a blurred instance of the
|
||||
* provided {@code BufferedImage}.
|
||||
*
|
||||
*/
|
||||
|
||||
// kernel for blur op
|
||||
float[] matrix = {
|
||||
0.111f, 0.111f, 0.111f,
|
||||
0.111f, 0.111f, 0.111f,
|
||||
0.111f, 0.111f, 0.111f,
|
||||
};
|
||||
|
||||
// perform the blur and return the blurred version.
|
||||
BufferedImageOp blur = new ConvolveOp( new Kernel(3, 3, matrix) );
|
||||
BufferedImage blurbuf = blur.filter(buf, null);
|
||||
return blurbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that returns a scaled instance of the
|
||||
* provided {@code BufferedImage}.
|
||||
*
|
||||
* @param buf the original image to be scaled
|
||||
* @param targetWidth the desired width of the scaled instance,
|
||||
* in pixels
|
||||
* @param targetHeight the desired height of the scaled instance,
|
||||
* in pixels
|
||||
* @param hint one of the rendering hints that corresponds to
|
||||
* {@code RenderingHints.KEY_INTERPOLATION} (e.g.
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
|
||||
* {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
|
||||
* @param higherQuality if true, this method will use a multi-step
|
||||
* scaling technique that provides higher quality than the usual
|
||||
* one-step technique (only useful in downscaling cases, where
|
||||
* {@code targetWidth} or {@code targetHeight} is
|
||||
* smaller than the original dimensions, and generally only when
|
||||
* the {@code BILINEAR} hint is specified)
|
||||
* @return a scaled version of the original {@code BufferedImage}
|
||||
*/
|
||||
public BufferedImage getScaledInstance(BufferedImage buf,
|
||||
int targetWidth,
|
||||
int targetHeight,
|
||||
Object hint,
|
||||
boolean higherQuality)
|
||||
{
|
||||
int type = (buf.getTransparency() == Transparency.OPAQUE) ?
|
||||
BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
|
||||
BufferedImage scalebuf = (BufferedImage)buf;
|
||||
int w, h;
|
||||
if (higherQuality) {
|
||||
// Use multi-step technique: start with original size, then
|
||||
// scale down in multiple passes with drawImage()
|
||||
// until the target size is reached
|
||||
w = buf.getWidth();
|
||||
h = buf.getHeight();
|
||||
} else {
|
||||
// Use one-step technique: scale directly from original
|
||||
// size to target size with a single drawImage() call
|
||||
w = targetWidth;
|
||||
h = targetHeight;
|
||||
}
|
||||
|
||||
do {
|
||||
if (higherQuality && w > targetWidth) {
|
||||
w /= 2;
|
||||
if (w < targetWidth) {
|
||||
w = targetWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (higherQuality && h > targetHeight) {
|
||||
h /= 2;
|
||||
if (h < targetHeight) {
|
||||
h = targetHeight;
|
||||
}
|
||||
}
|
||||
|
||||
BufferedImage tmp = new BufferedImage(w, h, type);
|
||||
Graphics2D g2d = tmp.createGraphics();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
|
||||
g2d.drawImage(scalebuf, 0, 0, w, h, null);
|
||||
g2d.dispose();
|
||||
|
||||
scalebuf = tmp;
|
||||
} while (w != targetWidth || h != targetHeight);
|
||||
|
||||
return scalebuf;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user