package org.summercool.util;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import org.summercool.image.AnimatedGifEncoder;
import org.summercool.image.GifDecoder;
import org.summercool.image.Scalr;
import org.summercool.image.Scalr.Method;
import org.summercool.image.Scalr.Mode;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ImageUtil {
static Font FONT = new Font("微软雅黑", Font.BOLD, 18);
static final Color COLOR = Color.WHITE;
static final Color FONT_COLOR = new Color(255, 255, 255, 150);
static final Color FONT_SHADOW_COLOR = new Color(170, 170, 170, 77);
public static boolean isJpg(String str) {
return isEndWid(str, "jpg");
}
public static boolean isPng(String str) {
return isEndWid(str, "png");
}
public static boolean isGif(String str) {
return isEndWid(str, "gif");
}
private static boolean isEndWid(String str, String ext) {
if (str == null || "".equals(str.trim())) {
return false;
}
int position = str.lastIndexOf(".");
if (position == -1 || (position == str.length() - 1)) {
return false;
}
String suffix = str.substring(position + 1);
if (ext.equalsIgnoreCase(suffix)) {
return true;
} else {
return false;
}
}
public static boolean isJpg(InputStream in) throws IOException {
InputStream iis = in;
if (!in.markSupported()) {
throw new IllegalArgumentException("Input stream must support mark");
}
iis.mark(30);
// If the first two bytes are a JPEG SOI marker, it's probably
// a JPEG file. If they aren't, it definitely isn't a JPEG file.
try {
int byte1 = iis.read();
int byte2 = iis.read();
if ((byte1 == 0xFF) && (byte2 == 0xD8)) {
return true;
}
} finally {
iis.reset();
}
return false;
}
public static boolean isPng(InputStream in) throws IOException {
if (!in.markSupported()) {
throw new IllegalArgumentException("Input stream must support mark");
}
byte[] b = new byte[8];
try {
in.mark(30);
in.read(b);
} finally {
in.reset();
}
return (b[0] == (byte) 137 && b[1] == (byte) 80 && b[2] == (byte) 78 && b[3] == (byte) 71 && b[4] == (byte) 13
&& b[5] == (byte) 10 && b[6] == (byte) 26 && b[7] == (byte) 10);
}
public static boolean isGif(InputStream in) throws IOException {
if (!in.markSupported()) {
throw new IllegalArgumentException("Input stream must support mark");
}
byte[] b = new byte[6];
try {
in.mark(30);
in.read(b);
} finally {
in.reset();
}
return b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8' && (b[4] == '7' || b[4] == '9') && b[5] == 'a';
}
/**
* 压缩图片
*
* @param in
* @param out
* @param maxWidth
* @param maxHeight
* @param type
* 1: jpg 2: png 4: gif 3: jpg+png 5: jpg+gif 6: png+gif 7:
* jpg+png+gif
* @throws IOException
*/
public static void resize(InputStream in, OutputStream out, int maxWidth, int maxHeight, int type, float quality,
String[] watermark, Font font, Color fontColor) throws IOException {
if (!(type >= 1 && type <= 7)) {
throw new IOException("can not support type: " + type + ", type must be in [1-7] ");
}
if (type == 1) {
if (!isJpg(in)) {
throw new IOException("image format is not jpg ");
}
resizeJpg(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (type == 2) {
if (!isPng(in)) {
throw new IOException("image format is not png ");
}
resizePng(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (type == 3) {
if (isJpg(in)) {
resizeJpg(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (isPng(in)) {
resizePng(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
}
throw new IOException("image format is not jpg or png ");
} else if (type == 4) {
if (!isGif(in)) {
throw new IOException("image format is not gif ");
}
resizeGif(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (type == 5) {
if (isJpg(in)) {
resizeJpg(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (isGif(in)) {
resizeGif(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
}
throw new IOException("image format is not jpg or gif ");
} else if (type == 6) {
if (isPng(in)) {
resizePng(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (isGif(in)) {
resizeGif(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
}
throw new IOException("image format is not png or gif ");
} else if (type == 7) {
if (isJpg(in)) {
resizeJpg(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (isPng(in)) {
resizePng(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
} else if (isGif(in)) {
resizeGif(in, out, maxWidth, maxHeight, quality, watermark, font, fontColor);
return;
}
throw new IOException("image format is not jpg or png or gif ");
}
}
public static void resizeJpg(InputStream in, OutputStream out, int maxWidth, int maxHeight, float quality,
String[] watermark, Font font, Color fontColor) throws IOException {
checkParams(in, out, maxWidth, maxHeight, quality);
//
BufferedImage image = ImageIO.read(in);
image = Scalr.resize(image, Method.AUTOMATIC, Mode.AUTOMATIC, maxWidth, maxHeight);
// create new image with right size/format
BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = bufferedImage.createGraphics();
// 因为有的图片背景是透明色,所以用白色填充 FIXED
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
g.fillRect(0, 0, image.getWidth(), image.getHeight());
g.drawImage(image, 0, 0, null);
image = bufferedImage;
//
if (watermark != null && watermark.length > 0) {
makeWatermark(watermark, image, font, fontColor);
}
//
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(image);
param.setQuality(quality, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(image);
}
public static void resizePng(InputStream in, OutputStream out, int maxWidth, int maxHeight, float quality,
String[] watermark, Font font, Color fontColor) throws IOException {
checkParams(in, out, maxWidth, maxHeight, quality);
//
BufferedImage image = ImageIO.read(in);
image = Scalr.resize(image, Method.AUTOMATIC, Mode.AUTOMATIC, maxWidth, maxHeight);
if (watermark != null && watermark.length > 0) {
makeWatermark(watermark, image, font, fontColor);
}
ImageIO.write(image, "png", out);
}
public static void resizeGif(InputStream in, OutputStream out, int maxWidth, int maxHeight, float quality,
String[] watermark, Font font, Color fontColor) throws IOException {
checkParams(in, out, maxWidth, maxHeight, quality);
//
GifDecoder gd = new GifDecoder();
int status = gd.read(in);
if (status != GifDecoder.STATUS_OK) {
return;
}
//
AnimatedGifEncoder ge = new AnimatedGifEncoder();
ge.start(out);
ge.setRepeat(0);
for (int i = 0; i < gd.getFrameCount(); i++) {
BufferedImage frame = gd.getFrame(i);
BufferedImage rescaled = Scalr.resize(frame, Method.AUTOMATIC, Mode.AUTOMATIC, maxWidth, maxHeight);
if (watermark != null && watermark.length > 0) {
makeWatermark(watermark, rescaled, font, fontColor);
}
//
int delay = gd.getDelay(i);
ge.setDelay(delay);
ge.addFrame(rescaled);
}
ge.finish();
}
private static void makeWatermark(String[] text, BufferedImage image, Font font, Color fontColor) {
Graphics2D graphics = image.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (font != null) {
graphics.setFont(font);
} else {
graphics.setFont(FONT);
}
if (fontColor == null) {
fontColor = COLOR;
}
//
graphics.setColor(fontColor);
for (int i = 0; i < text.length; i++) {
if ("".equals(text[i].trim())) {
continue;
}
FontRenderContext context = graphics.getFontRenderContext();
Rectangle2D fontRectangle = font.getStringBounds(text[i], context);
int sw = (int) fontRectangle.getWidth();
int sh = (int) fontRectangle.getHeight();
if (text.length - i == 1) {
graphics.drawString(text[i], image.getWidth() - sw - 6, image.getHeight() - 8);
} else {
graphics.drawString(text[i], image.getWidth() - sw - 6, image.getHeight() - sh * (text.length - 1) - 8);
}
}
graphics.dispose();
}
private static void checkParams(InputStream in, OutputStream out, int maxWidth, int maxHeight, float quality)
throws IOException {
if (in == null) {
throw new IOException("InputStream can not be null ");
}
if (out == null) {
throw new IOException("OutputStream can not be null ");
}
if (maxWidth < 1 || maxHeight < 1) {
throw new IOException("maxWidth or maxHeight can not be less than 1 ");
}
if (quality < 0f || quality > 1f) {
throw new IOException("quality must be in [0-1] ");
}
}
public static void main(String[] args) throws IOException {
FileInputStream in = new FileInputStream(new File("D:/gif/f1.jpg"));
FileOutputStream out = new FileOutputStream(new File("D:/gif/f1_b.jpg"));
try {
resizeJpg(in, out, 640, 640, 0.85f, new String[] {"@王少-_-","weibo.com/dragonsoar"}, FONT, FONT_COLOR);
} catch (Exception e) {
e.printStackTrace();
} finally {
out.close();
in.close();
}
}
}