2013-07-28 18:29:38 +02:00
|
|
|
package com.sismics.util;
|
|
|
|
|
2017-11-12 14:49:52 +01:00
|
|
|
import com.google.common.base.Charsets;
|
|
|
|
import com.google.common.hash.Hashing;
|
2013-07-28 18:29:38 +02:00
|
|
|
|
|
|
|
import javax.imageio.IIOImage;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
import javax.imageio.ImageWriteParam;
|
|
|
|
import javax.imageio.ImageWriter;
|
2013-08-20 21:51:07 +02:00
|
|
|
import javax.imageio.stream.ImageOutputStream;
|
2017-11-23 15:40:53 +01:00
|
|
|
import java.awt.*;
|
2017-11-12 14:49:52 +01:00
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.awt.image.WritableRaster;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.util.Iterator;
|
2013-07-28 18:29:38 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Image processing utilities.
|
|
|
|
*
|
|
|
|
* @author jtremeaux
|
|
|
|
*/
|
|
|
|
public class ImageUtil {
|
|
|
|
/**
|
|
|
|
* Write a high quality JPEG.
|
|
|
|
*
|
2018-03-02 19:05:20 +01:00
|
|
|
* @param image Image
|
2013-08-20 21:51:07 +02:00
|
|
|
* @param outputStream Output stream
|
2018-03-02 19:05:20 +01:00
|
|
|
* @throws IOException e
|
2013-07-28 18:29:38 +02:00
|
|
|
*/
|
2013-08-20 21:51:07 +02:00
|
|
|
public static void writeJpeg(BufferedImage image, OutputStream outputStream) throws IOException {
|
2013-07-28 18:29:38 +02:00
|
|
|
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
|
|
|
|
ImageWriter writer = null;
|
2013-08-20 21:51:07 +02:00
|
|
|
ImageOutputStream imageOutputStream = null;
|
2013-07-28 18:29:38 +02:00
|
|
|
try {
|
2017-11-12 14:49:52 +01:00
|
|
|
writer = iter.next();
|
2013-07-28 18:29:38 +02:00
|
|
|
ImageWriteParam iwp = writer.getDefaultWriteParam();
|
|
|
|
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
|
|
|
iwp.setCompressionQuality(1.f);
|
2013-08-20 21:51:07 +02:00
|
|
|
imageOutputStream = ImageIO.createImageOutputStream(outputStream);
|
|
|
|
writer.setOutput(imageOutputStream);
|
2017-11-23 15:40:53 +01:00
|
|
|
|
|
|
|
if (image.getColorModel().hasAlpha()) {
|
|
|
|
// Strip alpha channel
|
|
|
|
BufferedImage noAlphaImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
|
|
|
|
Graphics graphics = noAlphaImage.getGraphics();
|
|
|
|
graphics.setColor(Color.WHITE);
|
|
|
|
graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
|
|
|
|
graphics.drawImage(image, 0, 0, null);
|
|
|
|
image = noAlphaImage;
|
|
|
|
}
|
|
|
|
|
2013-07-28 18:29:38 +02:00
|
|
|
IIOImage iioImage = new IIOImage(image, null, null);
|
|
|
|
writer.write(null, iioImage, iwp);
|
|
|
|
} finally {
|
2013-08-20 21:51:07 +02:00
|
|
|
if (imageOutputStream != null) {
|
2013-07-28 18:29:38 +02:00
|
|
|
try {
|
2013-08-20 21:51:07 +02:00
|
|
|
imageOutputStream.close();
|
2013-07-28 18:29:38 +02:00
|
|
|
} catch (Exception inner) {
|
|
|
|
// NOP
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (writer != null) {
|
|
|
|
writer.dispose();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-19 00:05:04 +01:00
|
|
|
/**
|
|
|
|
* Compute Gravatar hash.
|
|
|
|
* See https://en.gravatar.com/site/implement/hash/.
|
|
|
|
*
|
2017-11-12 14:49:52 +01:00
|
|
|
* @param email Email
|
2015-11-19 00:05:04 +01:00
|
|
|
* @return Gravatar hash
|
|
|
|
*/
|
2018-10-21 11:54:19 +02:00
|
|
|
@SuppressWarnings("deprecation") // Gravatar uses MD5, nothing we can do about it
|
2015-11-19 00:05:04 +01:00
|
|
|
public static String computeGravatar(String email) {
|
|
|
|
if (email == null) {
|
|
|
|
return null;
|
|
|
|
}
|
2018-10-21 11:54:19 +02:00
|
|
|
|
2015-11-19 00:05:04 +01:00
|
|
|
return Hashing.md5().hashString(
|
|
|
|
email.trim().toLowerCase(), Charsets.UTF_8)
|
|
|
|
.toString();
|
|
|
|
}
|
2017-11-12 14:49:52 +01:00
|
|
|
|
2018-03-02 19:05:20 +01:00
|
|
|
/**
|
|
|
|
* Return true if a pixel is black.
|
|
|
|
*
|
|
|
|
* @param image Image
|
|
|
|
* @param x X
|
|
|
|
* @param y Y
|
|
|
|
* @return True if black
|
|
|
|
*/
|
2017-11-12 14:49:52 +01:00
|
|
|
public static boolean isBlack(BufferedImage image, int x, int y) {
|
|
|
|
if (image.getType() == BufferedImage.TYPE_BYTE_BINARY) {
|
|
|
|
WritableRaster raster = image.getRaster();
|
|
|
|
int pixelRGBValue = raster.getSample(x, y, 0);
|
|
|
|
return pixelRGBValue == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int luminanceValue = 140;
|
|
|
|
return isBlack(image, x, y, luminanceValue);
|
|
|
|
}
|
|
|
|
|
2018-03-02 19:05:20 +01:00
|
|
|
/**
|
|
|
|
* Return true if a pixel is black.
|
|
|
|
*
|
|
|
|
* @param image Image
|
|
|
|
* @param x X
|
|
|
|
* @param y Y
|
|
|
|
* @param luminanceCutOff Luminance cutoff
|
|
|
|
* @return True if black
|
|
|
|
*/
|
|
|
|
private static boolean isBlack(BufferedImage image, int x, int y, int luminanceCutOff) {
|
2017-11-12 14:49:52 +01:00
|
|
|
int pixelRGBValue;
|
|
|
|
int r;
|
|
|
|
int g;
|
|
|
|
int b;
|
|
|
|
double luminance = 0.0;
|
|
|
|
|
|
|
|
// return white on areas outside of image boundaries
|
|
|
|
if (x < 0 || y < 0 || x > image.getWidth() || y > image.getHeight()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
pixelRGBValue = image.getRGB(x, y);
|
|
|
|
r = (pixelRGBValue >> 16) & 0xff;
|
|
|
|
g = (pixelRGBValue >> 8) & 0xff;
|
|
|
|
b = (pixelRGBValue) & 0xff;
|
|
|
|
luminance = (r * 0.299) + (g * 0.587) + (b * 0.114);
|
|
|
|
} catch (Exception e) {
|
2018-03-02 19:05:20 +01:00
|
|
|
// NOP
|
2017-11-12 14:49:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return luminance < luminanceCutOff;
|
|
|
|
}
|
2013-07-28 18:29:38 +02:00
|
|
|
}
|