纯java,不依赖于第三方jar的图片处理类

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();
        }
    }
}

  转: http://dragonsoar.iteye.com/blog/1631330

posted @   吴超文  阅读(893)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· [AI/GPT/综述] AI Agent的设计模式综述
点击右上角即可分享
微信分享提示