【问题标题】:Ant task to extract image dimensions (height, width) from PNG and JPEG files?从 PNG 和 JPEG 文件中提取图像尺寸(高度、宽度)的 Ant 任务?
【发布时间】:2025-12-04 01:45:01
【问题描述】:

根据 Google Page Speed 建议,我想 Specify image dimensions 来“优化浏览器呈现”。

指定所有的宽度和高度 图像允许更快的渲染 消除不必要的需要 回流和重绘。

我正在研究如何遍历我的静态内容项目中的图像文件(PNG、JPEG)并输出一个文件,其中包含每个图像文件的路径和文件名以及以像素为单位的高度和宽度。然后,我将使用它来帮助我构建标签,方法是使用 src 属性数据来查找用于高度和宽度属性的值。

\images\logo.png,100,25

我的第一个想法是寻找 ANT 任务,因为我们的静态内容构建将 Ant 用于其他目的(例如在 JavaScript 和 CSS 文件上使用 YUI Compressor)。我也对其他想法持开放态度,包括解决此问题的其他方法。我宁愿不必手动完成这项工作。

【问题讨论】:

    标签: html optimization ant browser


    【解决方案1】:

    你可以试试这个https://github.com/mattwildig/image-size-report-task,这是我专门为这个问题制作的。

    【讨论】:

    • 我已经实现了这个,但在你回答之前没有更新这个问题。我将您的答案标记为已接受。谢谢。
    【解决方案2】:

    这是我目前实现的(需要测试和清理)。基本上,使用Tutorial: Tasks using Properties, Filesets & Paths 让我开始执行 Ant 任务,使用How to get image height and width using java? 提取图像尺寸。在部署之前,我将与 matt 的答案进行比较。

    我项目中的测试构建脚本:

    <project name="ImagesTask" basedir="." default="test">
        <target name="init">
            <taskdef name="images" classname="ImageInfoTask" classpath="..\dist\ImageTask.jar"/>
        </target>
        <target name="test" depends="init">
            <images outputFile="data/images.xml">
                <fileset dir="data" includes="images/**/*.jpg"/>
                <fileset dir="data" includes="images/**/*.gif"/>
                <fileset dir="data" includes="images/**/*.png"/>
            </images>
        </target>
    </project>
    

    Java 源代码(没有导入):

    public class ImageInfoTask extends Task {
    
        private String outputFile;
        private List fileSetList = new ArrayList();
        private PrintStream outputFileStream;
    
        public void setOutputFile(String outputFile) {
            this.outputFile = outputFile.replace("/", File.separator);
        }
    
        public void addFileset(FileSet fileset) {
            fileSetList.add(fileset);
        }
    
        protected void validate() {
            if (outputFile == null) {
                throw new BuildException("file not set");
            }
    
            if (fileSetList.size() < 1) {
                throw new BuildException("fileset not set");
            }
        }
    
        protected void openOutputFile() throws IOException {
            FileOutputStream out = new FileOutputStream(this.outputFile);
    
            // Connect print stream to the output stream
            this.outputFileStream = new PrintStream(out, true, "UTF-8");
    
            this.outputFileStream.println("<images>");
        }
    
        protected void writeImgToOutputFile(String filename, Dimension dim) {
            String imgTag = "  <img src=\"/" + filename.replace("\\", "/")
                    + "\" height=\"" + dim.height + "\" width=\"" + dim.width
                    + "\" />";
    
            this.outputFileStream.println(imgTag);
        }
    
        protected void closeOutputFile() {
            this.outputFileStream.println("</images>");
    
            this.outputFileStream.close();
        }
    
        @Override
        public void execute() {
            validate();
    
            try {
                openOutputFile();
    
                for (Iterator itFSets = fileSetList.iterator(); itFSets.hasNext();) {
                    FileSet fs = (FileSet) itFSets.next();
                    DirectoryScanner ds = fs.getDirectoryScanner(getProject());
                    String[] includedFiles = ds.getIncludedFiles();
                    for (int i = 0; i < includedFiles.length; i++) {
                        String filename = includedFiles[i];
    
                        Dimension dim = getImageDim(ds.getBasedir() + File.separator + filename);
                        if (dim != null) {
                            writeImgToOutputFile(filename, dim);
                        }
                    }
                }
    
                closeOutputFile();
            }  catch (IOException ex) {
                log(ex.getMessage());
            }
        }
    
        private Dimension getImageDim(final String path) {
            Dimension result = null;
            String suffix = this.getFileSuffix(path);
            Iterator<ImageReader> iter = ImageIO.getImageReadersBySuffix(suffix);
            if (iter.hasNext()) {
                ImageReader reader = iter.next();
                try {
                    ImageInputStream stream = new FileImageInputStream(new File(path));
                    reader.setInput(stream);
                    int width = reader.getWidth(reader.getMinIndex());
                    int height = reader.getHeight(reader.getMinIndex());
                    result = new Dimension(width, height);
                } catch (IOException e) {
                    log(path + ": " + e.getMessage());
                } finally {
                    reader.dispose();
                }
            }
            return result;
        }
    
        private String getFileSuffix(final String path) {
            String result = null;
            if (path != null) {
                result = "";
                if (path.lastIndexOf('.') != -1) {
                    result = path.substring(path.lastIndexOf('.'));
                    if (result.startsWith(".")) {
                        result = result.substring(1);
                    }
                }
            }
            return result;
        }
    }
    

    【讨论】:

    • 我使用相同的 ant 教程来了解如何使用文件集,所以我认为这两种实现在这方面非常相似。我对 ImageIO 了解不多,所以我只是将文件读入 BufferedImage 并从中获取尺寸。这就是我需要设置 java.awt.headless 的原因——我在运行脚本时出现了一个 java 菜单栏。我怀疑您使用的“纯”ImageIO 方法可能会比我的版本快一点,即使代码有点冗长。无论如何 - 这是一个周日晚上的有趣小项目。
    【解决方案3】:

    我不知道这样的蚂蚁任务很容易获得,但编写一个应该相对简单。在 PNG 格式中,图像大小存储在 IHDR 标头中文件的开头。 Google 上有许多 PNG 解析器示例 - 例如 this。将其包裹在 ant task 中就完成了。

    【讨论】:

      最近更新 更多