/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.servershepherd.beume;
import com.mortennobel.imagescaling.AdvancedResizeOp;
import com.mortennobel.imagescaling.ResampleOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import net.coobird.thumbnailator.Thumbnails;
import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.blocking.SelfPopulatingCache;
import net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory;
import org.imgscalr.Scalr;
/**
*
* @author marc
*/
class FrontCacheUpdater implements UpdatingCacheEntryFactory {
SelfPopulatingCache backCache;
public FrontCacheUpdater(SelfPopulatingCache back) {
backCache = back;
}
@Override
public void updateEntryValue(Object key, Object value) {
Object im = calculateResize(key);
// Do not update the entry if its returning errors
if (im instanceof String) {
return;
}
value = im;
}
@Override
public Object createEntry(Object key) {
Object im = calculateResize(key);
if (im instanceof String) {
return new Element(key, im, 0, CommonResources.FRONT_ERROR_RETAIN_SECS);
}
return im;
}
private Object calculateResize(Object key) {
FrontKey fk = (FrontKey) key;
String message = "Unknown error";
try {
Element e = backCache.get(new BackKey(fk));
byte[] res = null;
if (e != null) {
if (e.getObjectValue() instanceof String) {
// Backend generated an error
return e.getObjectValue();
}
byte[] img = (byte[]) e.getObjectValue();
ByteArrayInputStream bais = new ByteArrayInputStream(img);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
switch (fk.resize_filter.toLowerCase()) {
case "lanczos":
// Lanczos3 rescale algorithm from:
// Always non proportion preserving
// https://code.google.com/p/java-image-scaling/
BufferedImage src = ImageIO.read(bais);
ResampleOp resampleOp = new ResampleOp(fk.resize_x, fk.resize_y);
resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.None);
resampleOp.setNumberOfThreads(2);
createJPEG(fk.mod, baos, resampleOp.filter(src, null));
src.flush();
break;
case "imgscalr" :
// imgscalr method (Always proportion preserving)
// http://www.thebuzzmedia.com/software/imgscalr-java-image-scaling-library/
// Lile slower than lanczos
BufferedImage src2 = ImageIO.read(bais);
createJPEG(fk.mod,baos,Scalr.resize(src2, Scalr.Method.QUALITY, fk.resize_x, fk.resize_y, Scalr.OP_ANTIALIAS));
src2.flush();
break;
default:
// Thumbnailator library method
// https://code.google.com/p/thumbnailator/
Thumbnails.of(bais)
.forceSize(fk.resize_x, fk.resize_y)
.outputFormat("jpg").outputQuality((double) fk.mod / 100.0).toOutputStream(baos);
}
res = baos.toByteArray();
return res;
}
} catch (IOException ex) {
message = "Request: " + fk.source_url + " resize failed.";
Logger.getLogger(FrontCacheUpdater.class.getName()).log(Level.WARNING, message, ex);
} catch (IllegalStateException ex2) {
message = "Unknown Error " + ex2.getLocalizedMessage();
Logger.getLogger(FrontCacheUpdater.class.getName()).log(Level.WARNING, message, ex2);
}
return message;
}
private void createJPEG(int mod, ByteArrayOutputStream baos, BufferedImage ri) throws IOException {
Iterator iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = (ImageWriter) iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality((float) mod / (float) 100);
writer.setOutput(ImageIO.createImageOutputStream(baos));
IIOImage image = new IIOImage(ri, null, null);
writer.write(null, image, iwp);
writer.dispose();
ri.flush();
}
}