zoukankan      html  css  js  c++  java
  • pgm转png

    研究pgm转png比较消耗内存的问题

    • 2020.01.14 通过Java的ImageIO生成png与jpg图片,5000*5000的pgm需要消耗300M内存以上
    • 2020.01.15 通过jconsole, mat等工具,定位问题是由于在内存中生成整个png所有需要的数据,导致的问题
    • 2020.01.16 研究方向为根据png的实际文件结构,自己写代码生成png图片,基于昨天的研究:png支持灰度图

    使用jdk12测试:

    • 将5000*5000的pgm转换为png消耗12M左右
    • 将10000*10000的pgm转换为png消耗14M左右

    由于需要运行java类库,实际使用估计在2M左右
    如果连续转换,由于java的垃圾回收机制,可能会由于一些垃圾导致内存占用变大
    可以通过设置垃圾回收解决

    代码实现说明

    1. 通过调试ImageIO生成BufferedImage.TYPE_BYTE_GRAY的PNG图片的代码,研究生成PNG的过程
    2. 只保留必须的png文件结构:magic、IHDR、IDAT、IEND
    3. 具体实现,拷贝了com.sun.imageio.plugins.png的实现

    执行pgm转png

    java -jar pgm-to-png.jar pgm=5000-5000.pgm

    参数说明:

    • pgm: 源pgm文件地址,若只有文件名,则为运行时目录
    • png: 转换后的png文件地址,若为空,则将pgm文件路径换成png后缀为png文件地址
    • start: 启动倒数秒数
    • end: 结束倒数秒数

    使用jconsole监控内存使用情况

    设置为1秒采样一次:命令行执行jconsole -interval=1

    • 使用远程连接,方便重试
      java -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=7077 -Dcom.sun.management.jmxremote.local.only=true -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1 -jar pgm-to-png.jar pgm=5000-5000.pgm start=5
    • 本地在jconsole中,直接选择进行ID也可以,多次执行不太方便

    创建pgm文件

    java -cp pgm-to-png.jar com.bdr.demo.PgmCreator无参数默认创建5000*5000的文件

    参数说明:

    • 灰度图长度
    • height: 灰度图高度
    • file: 灰度图保存地址

    示例:
    java -cp pgm-to-png.jar com.bdr.demo.PgmCreator width=100 height=100 file=test.pgm

    代码

    PgmToPng

    import javax.imageio.stream.FileImageOutputStream;
    import javax.imageio.stream.ImageOutputStream;
    import java.io.*;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.concurrent.TimeUnit;
    
    public class PgmToPng {
    
        public static void main(String[] args) throws Exception {
    
            Map<String, String> argMap = new HashMap<>();
            for (String arg : args) {
                String[] argArr = arg.split("=");
                argMap.put(argArr[0], argArr[1]);
            }
    
            String source = argMap.get("pgm");
            if (!Files.isRegularFile(Paths.get(source))) {
                System.out.println("source file not exist: " + source);
                return;
            }
    
            String dest = argMap.get("png");
            dest = dest == null ? source.substring(0, source.lastIndexOf('.')) + ".png" : dest;
    
            if (Files.isRegularFile(Paths.get(dest))) {
                System.out.println("delete file: " + dest);
                Files.deleteIfExists(Paths.get(dest));
            }
    
            System.out.println("source file: " + source);
            System.out.println("dest file: " + dest);
    
            System.out.println("start...");
            countDown(argMap.get("start"));
            new PgmToPng().convertPgmToPng(source, dest);
            System.out.println("convert over: " + dest);
            System.out.println("end.");
            countDown(argMap.get("end"));
        }
    
        private static void countDown(String secondStr) throws Exception {
            if (secondStr == null) {
                return;
            }
            try {
                countDown(Integer.parseInt(secondStr));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static void countDown(int second) throws Exception {
            for (int t = second; t > 0; t--) {
                TimeUnit.SECONDS.sleep(1);
                System.out.println(t + "s...");
            }
        }
    
        private void convertPgmToPng(String source, String dest) throws Exception {
            final BufferedInputStream in = new BufferedInputStream(new FileInputStream(source));
            ImageOutputStream out = new FileImageOutputStream(new File(dest));
            try (in; out) {
                if (!"P5".equals(next(in))) {
                    throw new IOException("File  is not a binary PGM image.");
                }
                final int col = Integer.parseInt(next(in));
                final int row = Integer.parseInt(next(in));
                final int max = Integer.parseInt(next(in));
                if (max < 0 || max > 255) {
                    throw new IOException("The image's maximum gray value must be in range [0, " + 255 + "].");
                }
                writeMagic(out);
                writeIHDR(out, col, row);
                IDATOutputStream os = new IDATOutputStream(out, 32768, 4);
                byte[] curRow = new byte[col];
                for (int i = 0; i < row; ++i) {
                    for (int j = 0; j < col; ++j) {
                        final int p = in.read();
                        if (p < 0 || p > max) {
                            throw new IOException("Pixel value " + p + " outside of range [0, " + max + "].");
                        }
                        curRow[j] = (byte) p;
                    }
                    writeIDAT(os, curRow, col);
                    os.flush();
                }
                os.finish();
                writeIEND(out);
                out.flush();
            }
        }
    
        protected void writeMagic(ImageOutputStream stream) throws Exception {
            byte[] magic = {(byte) 137, 80, 78, 71, 13, 10, 26, 10};
            stream.write(magic);
        }
    
        protected void writeIHDR(ImageOutputStream stream, int col, int row) throws Exception {
            ChunkStream cs = new ChunkStream(0x49484452, stream); // PNGImageReader.PNGImageReader.IHDR_TYPE
            cs.writeInt(col); // IHDR_width
            cs.writeInt(row); // IHDR_height
            cs.writeByte(8); // IHDR_bitDepth
            cs.writeByte(0); // IHDR_colorType
            cs.writeByte(0); // IHDR_compressionMethod
            cs.writeByte(0); // IHDR_filterMethod
            cs.writeByte(0); // IHDR_interlaceMethod
            cs.finish();
        }
    
        protected void writeIDAT(ImageOutputStream os, byte[] currRow, int col) throws Exception {
            os.write(0);
            os.write(currRow, 0, col);
        }
    
        protected void writeIEND(ImageOutputStream stream) throws Exception {
            ChunkStream cs = new ChunkStream(0x49454e44, stream);
            cs.finish();
        }
    
        private static String next(final InputStream stream) throws IOException {
            final List<Byte> bytes = new ArrayList<>();
            while (true) {
                final int b = stream.read();
                if (b != -1) {
                    final char c = (char) b;
                    if (c == '#') {
                        int d;
                        do {
                            d = stream.read();
                        } while (d != -1 && d != '
    ' && d != '
    ');
                    } else if (!Character.isWhitespace(c)) {
                        bytes.add((byte) b);
                    } else if (!bytes.isEmpty()) {
                        break;
                    }
                } else {
                    break;
                }
            }
            final byte[] bytesArray = new byte[bytes.size()];
            for (int i = 0; i < bytesArray.length; ++i)
                bytesArray[i] = bytes.get(i);
            return new String(bytesArray);
        }
    }
    

    PgmCreator

    import java.io.File;
    import java.util.HashMap;
    import java.util.Map;
    
    public class PgmCreator {
        public static void main(String[] args) throws Exception {
            Map<String, String> argMap = new HashMap<>();
            for (String arg : args) {
                String[] argArr = arg.split("=");
                argMap.put(argArr[0], argArr[1]);
            }
            String widthStr = argMap.get("width");
            int width = widthStr == null ? 5000 : Integer.parseInt(widthStr);
    
            String heightStr = argMap.get("height");
            int height = heightStr == null ? 5000 : Integer.parseInt(heightStr);
    
            String file = argMap.get("file");
            file = file == null ? width + "-" + height + ".pgm" : file;
    
            PGMIO.write(PGMUtils.createArc(width, height), new File(file));
        }
    }
    
    
  • 相关阅读:
    Java实体书写规范
    Mybatis配置中遇到的问题和问题分析
    Ubuntu下eclipse的Extjs提示插件安装
    Ubuntu中root用户和user用户的相互切换
    ubuntu下启动和关闭tomcat的简单方法
    Ubuntu上安装Maven Eclipse以及配置
    IE8兼容<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
    心情
    更改Eclipse下Tomcat的部署目录
    Tomcat:IOException while loading persisted sessions: java.io.EOFException 解决
  • 原文地址:https://www.cnblogs.com/chencye/p/12204760.html
Copyright © 2011-2022 走看看