Java小图片拼接为图集

news/2024/7/7 14:33:06

使用的是暴力拼接(从左向右,从上到下,先放矮的图片进去)
对于后缀为_strip[数字]的图片会再次分割提高图集密度
效果
拼接前
在这里插入图片描述
拼接后
在这里插入图片描述
对应子图的偏移信息记录类(自动生成)
在这里插入图片描述
单张图片信息类(可能有多张图片因为有后面名为_strip[数字]的情况)

public class ImageInfo implements Comparable<ImageInfo>{

    private int[] xs;
    private int[] ys;
    private int index;
    private int width;
    private int height;
    private int num;
    private String name;
    private BufferedImage image;
    private static final Pattern NAME_COMPILE = Pattern.compile("(.*)_strip(\\d+)\\.");

    public ImageInfo(File file) throws IOException {
        initNameAndNum(file.getName());
        initImage(file);
    }

    private void initImage(File file) throws IOException {
        image= ImageIO.read(file);
        width= image.getWidth()/num;
        height=image.getHeight();
    }

    private void initNameAndNum(String fullName) {
        Matcher matcher = NAME_COMPILE.matcher(fullName);
        if(matcher.find()){
            name=matcher.group(1);
            num=Integer.parseInt(matcher.group(2));
        }else {
            name=fullName.substring(0,fullName.lastIndexOf('.'));
            num=1;
        }
        xs=new int[num];
        ys=new int[num];
        index=0;
    }

    public boolean hasSetAll(){
        return index==num;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    @Override
    public int compareTo(ImageInfo tar) {
        return tar.height-this.height;
    }

    public void setPos(int x, int y) {
        xs[index]=x;
        ys[index]=y;
        index++;
    }

    public void processSelf(Graphics g, ClassMaker classMaker) {
        g.drawImage(image,xs[index],ys[index],xs[index]+width,ys[index]+height,index*width,
                0,(index+1)*width,height,null);
        String name=this.name;
        if(num>1){
            name+=index;
        }
        classMaker.addInfo(xs[index],ys[index],xs[index]+width,ys[index]+height,name);
        index++;
    }

    public void reset() {
        index=0;
    }

}

单个图集信息(可能数据量太大,打出多个图集)

public class BigImage {

    private List<ImageInfo> imageInfos;
    private int width;
    private int height;
    private int x;
    private int y;
    private int offsetH;

    public BigImage(int width, int height) {
        this.width = width;
        this.height = height;
        initData();
    }

    private void initData() {
        x=0;
        y=0;
        offsetH=0;
        imageInfos=new ArrayList<>();
    }

    public boolean addImage(ImageInfo imageInfo) {
        if(offsetH==0)offsetH=imageInfo.getHeight();
        while (y+imageInfo.getHeight()<=height){
            if(x+imageInfo.getWidth()>width){
                y+=offsetH;
                x=0;
                offsetH=imageInfo.getHeight();
            }else {//横向放入
                imageInfo.setPos(x,y);
                imageInfos.add(imageInfo);
                x+=imageInfo.getWidth();
                return true;
            }
        }
        return false;
    }

    public void processImage(String tarPath, int index, ClassMaker classMaker) throws IOException {
        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_4BYTE_ABGR);
        Graphics g = image.getGraphics();
        String fileName="create_"+index+".png";
        classMaker.setImageName(fileName);
        for (ImageInfo imageInfo:imageInfos){
            imageInfo.processSelf(g,classMaker);
        }
        ImageIO.write(image,"png",new File(tarPath,fileName));
    }

}

主处理类

public class ImageProcessor {

    public static void main(String[] args) throws IOException {
                    //      资源目录                    目标目录                  图集大小
        processImage("src/testGame/res","src/testGame/tar",1024,1024);
    }

    private static void processImage(String srcPath,String tarPath, int width, int height) throws IOException {
        File[] files = new File(srcPath).listFiles();
        ImageInfo[] imageInfos=new ImageInfo[files.length];
        for (int i = 0; i < imageInfos.length; i++) {
            imageInfos[i]=new ImageInfo(files[i]);
        }
        Arrays.sort(imageInfos);
        putBigImage(imageInfos,width,height,tarPath);
    }

    private static void putBigImage(ImageInfo[] imageInfos, int width, int height,String tarPath) throws IOException {
        Stack<BigImage> stack=new Stack<>();
        stack.push(new BigImage(width,height));
        int index=0;
        while (index<imageInfos.length){
            while (!imageInfos[index].hasSetAll()){
                if(!stack.peek().addImage(imageInfos[index])){
                    stack.push(new BigImage(width,height));
                }
            }
            imageInfos[index].reset();
            index++;
        }
        index=0;
        ClassMaker classMaker = new ClassMaker();
        while (!stack.isEmpty()){
            stack.pop().processImage(tarPath,index++,classMaker);
        }
        classMaker.create(tarPath);
    }

}

资源类生成器

public class ClassMaker {

    private List<Integer> x1s;
    private List<Integer> y1s;
    private List<Integer> x2s;
    private List<Integer> y2s;
    private List<String> names;
    private List<String> imageNames;
    private String imageName;

    public ClassMaker() {
        initData();
    }

    public void setImageName(String imageName) {
        this.imageName = imageName;
    }

    private void initData() {
        x1s=new ArrayList<>();
        y1s=new ArrayList<>();
        x2s=new ArrayList<>();
        y2s=new ArrayList<>();
        names=new ArrayList<>();
        imageNames=new ArrayList<>();
    }

    public void addInfo(int x1,int y1,int x2,int y2,String name){
        x1s.add(x1);
        y1s.add(y1);
        x2s.add(x2);
        y2s.add(y2);
        names.add(name);
        imageNames.add(imageName);
    }

    public void create(String tarPath) throws IOException {
        String classContent=buildContent();
        FileOutputStream out = new FileOutputStream(tarPath + "/Res.java");
        out.write(classContent.getBytes());
        out.close();
    }

    private String buildContent() {
        StringBuilder builder = new StringBuilder("package testGame.tar;\n\npublic final class Res {\n\n");
        builderInt(builder,x1s,"x1s");
        builderInt(builder,y1s,"y1s");
        builderInt(builder,x2s,"x2s");
        builderInt(builder,y2s,"y2s");
        builderString(builder);
        builder.append("\n");
        for (int i=0;i<names.size();i++){
            builder.append("\tpublic final static int ").append(names.get(i)).append("=").append(i)
                    .append(";\n");
        }
        builder.append("\n}");
        return builder.toString();
    }

    private void builderString(StringBuilder builder) {
        builder.append("\tpublic final static String[] imageNames={");
        for (String imageName:imageNames){
            builder.append("\"").append(imageName).append("\",");
        }
        builder.append("};\n");
    }

    private void builderInt(StringBuilder builder, List<Integer> nums,String name) {
        builder.append("\tpublic final static int[] ").append(name).append("={");
        for (Integer integer:nums){
            builder.append(integer).append(",");
        }
        builder.append("};\n");
    }

    @Override
    public String toString() {
        return "ClassMaker{" +
                "x1s=" + x1s +
                ", \ny1s=" + y1s +
                ", \nx2s=" + x2s +
                ", \ny2s=" + y2s +
                ", \nnames=" + names +
                ", \nimageNames=" + imageNames +
                ", \nimageName='" + imageName + '\'' +
                '}';
    }

}

对于太过极端的不太适合,要设置合适的图集大小,若设置的宽度太小可能造成死循环


http://www.niftyadmin.cn/n/658004.html

相关文章

以xml文件作为数据库的程序一例

xml分为三种&#xff0c;index.xml保存一个最大的索引 &#xff0c;相当于一个序列。flfgcx_list.xml为一个目录&#xff0c;里面保存了所有的信息的索引信息另一种就是内容xml&#xff0c;每一种法律都有一个文件。文件名为一个数字&#xff0c;当录入当前的法律的时候自动创造…

三汇自动挂断问题

三汇自动挂断问题 ACK检测 转载于:https://www.cnblogs.com/devour/p/10901341.html

Java正则表达式使用

这里不讲基本的正则字符&#xff0c;只说一下Java中使用正则的常用API 基本代码&#xff0c;后面的基于他们 // 构建正则 Pattern pattern Pattern.compile("((\\d)(\\d))"); // 匹配字符串 Matcher matcher pattern.matcher("23sgfew8h8erh23gewjrg3er&quo…

推荐两个不错的flink项目

最近flink真是风生水起&#xff0c;但是浪院长看来这不过是阿里错过了创造spark影响力之后&#xff0c;想要在flink领域创建绝对的影响力。但是&#xff0c;不可否认flink在实时领域确实目前来看独树一帜&#xff0c;当然也有它不适合的地方&#xff0c;比如今天要推荐的第一个…

LOJ 6433 「PKUSC2018」最大前缀和——状压DP

题目&#xff1a;https://loj.ac/problem/6433 想到一个方案中没有被选的后缀满足 “该后缀的任一前缀和 <0 ”。 于是令 dp[ S ] 表示选了点集 S &#xff0c;满足任一前缀和 <0 的方案。很好转移。 令 f[ S ] 表示选了点集 S &#xff0c;且 S 整体就是最大前缀和的方案…

Zookeeper简单学习

观察者模式 Zookeeper实际是观察者模式负责存储管理数据&#xff0c;接收观察者的注册&#xff0c;一旦数据发生变化&#xff0c;Zookeeper负责通知对应的观察者 Zookeeper文件系统通知系统 Zookeeper特点 1&#xff0c;一个领导者(Leader)多个跟随着(Follower) 2&#xff…

B. Working out 四角dp

https://codeforces.com/problemset/problem/429/B 这个题目之前写过&#xff0c;不过好像。。忘记了&#xff0c;今天又没有写出来&#xff0c;应该之前没有想明白。。。 这个应该算一个四角dp(网上说的&#xff0c;感觉很符合)&#xff0c;所以呢就是要从四个角进行dp&#x…

xml数据岛 + recordset 数据处理程序简单例子

本程序将数据库中数据一次性装载到客户端xml数据岛中&#xff0c;然后在客户端处理 用recordset 处理数据。 从数据库中提取数据的程序&#xff1a;xmlDeptMatch.asp <!--#include file"../inc/conn.asp"--><!--#include file"../inc/config.asp"…