[Swing] 按照尺寸最小的图片的长宽,进行统一裁剪

import java.io.File;

import java.awt.Color;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.Graphics;
import java.awt.Dimension;

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.awt.image.BufferedImage;

import java.util.List;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;

import javax.imageio.ImageIO;

/**
 * 把图片集里的所有图片,按照尺寸最小的图片的长宽,进行统一裁剪
 *
 * 1. 拖动图片目录到命令行,开始处理图片目录
 *
 * 2. 为了防止图片再次损失,统一生成 PNG,需要进一步缩减大小
 *
 * 3. 不想操作的图片设置隐藏,记住这个只针对 Windows 系统有效
 *
 * 4. 图片被窗口调出后,鼠标点击要裁剪的范围,记住黄色方框范围一定要在图片内
 *
 * @Author: NeedJava@126.com
 *
 * @Version: 2025.12.14
 */
public final class CropImageToSameSize {
    public static final int MIN_SIZE      = 10;
    public static final int IGNORE_SIZE   = 1;
    public static final String[] OPTIONS  = new String[] {"确定裁剪", "取消裁剪", "退出软件"};

    public static void main(final String[] args) throws Exception {
        final java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(System.in));

        while (true) {
            System.out.println("\r\nPlease input source folder:");

            final String source = reader.readLine().trim();
            final File sourceFolder = new File(source.startsWith("\"") && source.endsWith("\"") ? source.substring(1, source.length() - 1) : source);
            if (sourceFolder.isDirectory() == false) {
                System.err.println("Source folder not exists! " + sourceFolder);
                continue;
            }

            askForBounds(getMinSize(sourceFolder, Integer.MAX_VALUE, Integer.MAX_VALUE));
            System.out.println("\r\nDONE");
        }
    }

    public static Result getMinSize(final File parent, final int initMinWidth, final int initMinHeight) throws Exception {
        final Result result = new Result();
        if (parent == null || initMinWidth < MIN_SIZE || initMinHeight < MIN_SIZE) {
            System.err.println("parent is null or width: " + initMinWidth + "  height: " + initMinHeight);
            return result;
        }
        final String[] children = parent.list();
        if (children == null) {
            return result;
        }

        int minWidth = initMinWidth, minHeight = initMinHeight;
        if (minWidth > minHeight) {  //横向
            //Do nothing
        } else{
            final int temp = minWidth;  //对调
            minWidth = minHeight;
            minHeight = temp;
        }

        File file = null; BufferedImage image = null; int width = -1, height = -1;
        for (int i = 0; i < children.length; i ++) {
            file = new File(parent, children[i]);
            if (file.isDirectory() || file.isHidden()) {
                continue;
            }
            try {
                image = ImageIO.read(file); width = image.getWidth(); height = image.getHeight();
                if (width < MIN_SIZE || height < MIN_SIZE) {
                    continue;
                }

                if (width > height) {  //同为横向
                    if (minWidth > width) {
                        minWidth = width;
                    }
                    if (minHeight > height) {
                        minHeight = height;
                    }
                } else {  //对调
                    if (minWidth > height) {
                        minWidth = height;
                    }
                    if (minHeight > width) {
                        minHeight = width;
                    }
                }

                result.mFiles.add(file);
                System.out.println("ADDED  " + file + "  " + minWidth + "  " + minHeight);
            } catch (Exception e) {
                System.err.println("Failed to read image: " + file + "  " + e.getMessage());
            }
        }

        result.mSizeLarge = minWidth / IGNORE_SIZE * IGNORE_SIZE; result.mSizeSmall = minHeight / IGNORE_SIZE * IGNORE_SIZE;
        return result;
    }

    public static void askForBounds(final Result result) {
        if (result == null || result.mFiles == null) {
            System.err.println("result is null");
            return;
        }

        final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        if (screenSize == null) {
            System.err.println("screenSize is null");
            return;
        }
        final int previewSize = Math.min(screenSize.width, screenSize.height) / 6 * 5;

        File file = null; BufferedImage image = null; int width = -1, height = -1;
        double scale = 0.0F; int scaledWidth = -1, scaledHeight = -1; SelectableLabel label = null; 
        for (int i = 0, count = result.mFiles.size(); i < count; i ++) {
            file = result.mFiles.get(i);
            if (file.isDirectory() || file.isHidden()) {
                continue;
            }
            try {
                image = ImageIO.read(file); width = image.getWidth(); height = image.getHeight();
                if (width < MIN_SIZE || height < MIN_SIZE) {
                    continue;
                }

                if (width > height) {  //获取显示在屏幕上的 Image,给 JLabel 用
                    scale = ((double) previewSize / width);
                    scaledWidth = previewSize; scaledHeight = (int) (scale * height);
                    label = new SelectableLabel(new ImageIcon(image.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_DEFAULT)), (int) (result.mSizeLarge * scale), (int) (result.mSizeSmall * scale));
                    //System.out.println(width + "x" + height + "  scaled: " + scaledWidth + "x" + scaledHeight + "  preview: " + previewSize + "  scale: " + scale + "  " + result.mSizeLarge + "x" + result.mSizeSmall + "  " + (int) (result.mSizeLarge * scale) + "x" + (int) (result.mSizeSmall * scale));
                } else {
                    scale = ((double) previewSize / height);
                    scaledWidth = (int) (scale * width); scaledHeight = previewSize;
                    label = new SelectableLabel(new ImageIcon(image.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_DEFAULT)), (int) (result.mSizeSmall * scale), (int) (result.mSizeLarge * scale));
                    //System.out.println(width + "x" + height + "  scaled: " + scaledWidth + "x" + scaledHeight + "  preview: " + previewSize + "  scale: " + scale + "  " + result.mSizeLarge + "x" + result.mSizeSmall + "  " + (int) (result.mSizeSmall * scale) + "x" + (int) (result.mSizeLarge * scale));
                }

                final int selected = JOptionPane.showOptionDialog(null, label, "选择裁剪位置", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, OPTIONS, OPTIONS[0]);
                if (selected == JOptionPane.YES_OPTION) {
                    System.out.println("Selected: YES_OPTION");
                    if (width > height) {
                        cropImage(file, image, (int) (label.mOffsetX / scale), (int) (label.mOffsetY / scale), result.mSizeLarge, result.mSizeSmall);
                    } else {
                        cropImage(file, image, (int) (label.mOffsetX / scale), (int) (label.mOffsetY / scale), result.mSizeSmall, result.mSizeLarge);
                    }

                } else if (selected == JOptionPane.NO_OPTION) {
                    System.out.println("Selected: NO_OPTION");

                } else if (selected == JOptionPane.CANCEL_OPTION) {
                    System.out.println("Selected: CANCEL_OPTION");
                    break;//System.exit(0);
                }
            } catch (Exception e) {
                System.err.println("Failed to read image: " + file + "  " + e.getMessage());
            }
        }
    }

    public static void cropImage(final File file, final BufferedImage image, final int x, final int y, final int width, final int height) {
        try {
            //System.out.println(x + "  " + y + "  " + width + "  " + height);
            final File outFolder = new File(file.getParent(), "OUT__PUT"); outFolder.mkdirs();
            final File outFile = new File(outFolder, file.getName());
            ImageIO.write(image.getSubimage(x, y, width, height), "PNG", outFile);
            System.out.println("CROPED  " + file + "  to  " + outFile);
        } catch (Exception e) {
            System.err.println("Failed to crop image: " + file + "  " + e.getMessage());
        }
    }
}

class Result {
    public int mSizeLarge;
    public int mSizeSmall;

    public final List<File> mFiles = new ArrayList<>();
}

class SelectableLabel extends JLabel implements MouseListener {
    private static final long serialVersionUID = 1L;

    public int mOffsetX;
    public int mOffsetY;

    public int mWidth;
    public int mHeight;

    public SelectableLabel(final ImageIcon icon, final int width, final int height) {
        super(icon);
        this.mWidth  = (icon == null ? -1 : width);
        this.mHeight = (icon == null ? -1 : height);
        this.addMouseListener(SelectableLabel.this);
    }

    @Override
    protected final void paintComponent(final Graphics g) {
        super.paintComponent(g);
        if (mWidth < 10 || mHeight < 10) {
            return;
        }
        g.setColor(Color.YELLOW);
        g.drawRect(mOffsetX, mOffsetY, mWidth - 1/**/, mHeight - 1/**/);
    }

    @Override
    public final void mouseClicked(final MouseEvent e) {
        if (e == null) {
            System.err.println("event is null");
            return;
        }
        mOffsetX = e.getX(); mOffsetY = e.getY();
        invalidate(); repaint();
        //System.out.println("CLICK AT: " + e.getX() + "  " + e.getY());
    }

    @Override
    public final void mousePressed(final MouseEvent e) {
    }

    @Override
    public final void mouseReleased(final MouseEvent e) {
    }

    @Override
    public final void mouseEntered(final MouseEvent e) {
    }

    @Override
    public final void mouseExited(final MouseEvent e) {
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值