package cc.abstra.trantor.pdfconverter;
import com.mortennobel.imagescaling.AdvancedResizeOp;
import com.mortennobel.imagescaling.DimensionConstrain;
import com.mortennobel.imagescaling.ResampleOp;
import javax.media.jai.PlanarImage;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
* @author nando
*/
public class ImageHelper {
static BufferedImage resizeImageToDINA4WithDPI(BufferedImage img, int previewDpi, float scaleDown) {
return resizeImageToDINA4WithDPI(img, previewDpi, previewDpi, previewDpi, previewDpi, scaleDown);
}
static BufferedImage resizeImageToDINA4WithDPI(BufferedImage origImage, int targetDpiX, int targetDpiY,
int origDpiX, int origDpiY) {
return resizeImageToDINA4WithDPI(origImage, targetDpiX, targetDpiY, origDpiX, origDpiY, 1.0f);
}
private static BufferedImage resizeImageToDINA4WithDPI(BufferedImage origImage, int targetDpiX, int targetDpiY,
int origDpiX, int origDpiY, float scaleDown) {
float targetRatioX = (float)Consts.millisToPixels(Consts.A4_W_MM, targetDpiX)/origImage.getWidth();
float targetRatioY = (float)Consts.millisToPixels(Consts.A4_H_MM, targetDpiY)/origImage.getHeight();
float targetRatio = Math.min(1.0f, Math.min(targetRatioX, targetRatioY)/scaleDown);
Logger.getLogger(ImageHelper.class.getName()).log(Level.INFO,
"Resizing BufferedImage (px) --- "+
"Original dimensions: ("+Integer.toString(origImage.getWidth())+
","+Integer.toString(origImage.getHeight())+")"+
" - Fraction: ("+Float.toString(targetRatioX)+","+Float.toString(targetRatioY)+")"+
" - Using ratio: "+Float.toString(targetRatio));
ResampleOp resampleOp = new ResampleOp(DimensionConstrain.createRelativeDimension(targetRatio, targetRatio));
resampleOp.setUnsharpenMask(AdvancedResizeOp.UnsharpenMask.Normal);
return resampleOp.filter(origImage, null);
}
public static BufferedImage sanitizeImage(RenderedImage origRi, boolean applyAlpha) {
BufferedImage image;
if (origRi instanceof BufferedImage) {
image = (BufferedImage) origRi;
} else {
ColorModel cm = PlanarImage.createColorModel(origRi.getSampleModel());
image = PlanarImage.wrapRenderedImage(origRi).getAsBufferedImage(null, cm);
}
if(applyAlpha){ //HACK until TiffDoc.toPdf readers are used in .toPng
int origColorSpace = image.getColorModel().getColorSpace().getType();
if(origColorSpace != ColorSpace.TYPE_GRAY && origColorSpace != ColorSpace.TYPE_RGB) {
image = convertToRGB(image);
}
}
return image;
}
public static Object hasLandscapeOrientation(BufferedImage img) {
if(img.getWidth() > img.getHeight()) {
return true;
} else {
return false;
}
}
private static BufferedImage convertToRGB(BufferedImage src){
BufferedImage dst = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
ColorConvertOp op = new ColorConvertOp(null);
dst = op.filter(src, dst);
// CAVEAT:
// ImageHelper.sanitizeImage(img) might leak brightness from any non-sRGB
// color space (such as CMYK) to the sRGB target, "sanitized" space.
// Because of that artifact, ImageHelper.gammaCorrection() is available.
ColorSpace origCs = src.getColorModel().getColorSpace();
if (!origCs.isCS_sRGB()){
if(ColorSpace.TYPE_CMYK == origCs.getType()){
Logger.getLogger(ImageHelper.class.getName()).log(Level.INFO,
"Applying CMYK to sRGB gamma correction: "+Consts.CMYK_RGB_GAMMA_CORRECTION);
dst = gammaCorrection(dst,Consts.CMYK_RGB_GAMMA_CORRECTION);
}
}
return dst;
}
/**
* Gamma correction algorithm
*
* Author: Bostjan Cigan (http://zerocool.is-a-geek.net)
*
*
* Note: another impl (platform-dependent) can be found at the end of this thread:
* https://forums.oracle.com/forums/thread.jspa?messageID=5387100
* but it didn't work in Linux.
*/
private static BufferedImage gammaCorrection(BufferedImage original, double gamma) {
int alpha, red, green, blue;
int newPixel;
double gamma_new = 1 / gamma;
int[] gamma_LUT = gamma_LUT(gamma_new);
BufferedImage gamma_cor = new BufferedImage(original.getWidth(), original.getHeight(), original.getType());
for(int i=0; i<original.getWidth(); i++) {
for(int j=0; j<original.getHeight(); j++) {
// Get pixels by R, G, B
alpha = new Color(original.getRGB(i, j)).getAlpha();
red = new Color(original.getRGB(i, j)).getRed();
green = new Color(original.getRGB(i, j)).getGreen();
blue = new Color(original.getRGB(i, j)).getBlue();
red = gamma_LUT[red];
green = gamma_LUT[green];
blue = gamma_LUT[blue];
// Return back to original format
newPixel = colorToRGB(alpha, red, green, blue);
// Write pixels into image
gamma_cor.setRGB(i, j, newPixel);
}
}
return gamma_cor;
}
// Create the gamma correction lookup table
private static int[] gamma_LUT(double gamma_new) {
int[] gamma_LUT = new int[256];
for(int i=0; i<gamma_LUT.length; i++) {
gamma_LUT[i] = (int) (255 * (Math.pow((double) i / (double) 255, gamma_new)));
}
return gamma_LUT;
}
// Convert R, G, B, Alpha to standard 8 bit
private static int colorToRGB(int alpha, int red, int green, int blue) {
int newPixel = 0;
newPixel += alpha;
newPixel = newPixel << 8;
newPixel += red; newPixel = newPixel << 8;
newPixel += green; newPixel = newPixel << 8;
newPixel += blue;
return newPixel;
}
}