使用仅必要的字节进行图像元数据提取?

huangapple go评论67阅读模式
英文:

Image metadata extraction using only necessary bytes?

问题

我有一个处理成千上万张图像和视频的程序。我希望能够从中读取日期时间元数据,而无需将整个图像保存在内存中。目前,这些图像通过各种流传递到我的程序中。

例如,创建缩略图图像:

public static void createThumbnailImage(Media media, TmpMedia tmpMedia) throws IOException {
        PipedInputStream mediaIn = new PipedInputStream();
        PipedOutputStream mediaOut = new PipedOutputStream(mediaIn);
        new Thread(() -> {
            try {
                App.storage.getMedia(media, mediaOut);
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, "Error getting Media for thumbnail", e);
            }
        }).start();
        // 其余代码...
}

在我的某个步骤中,我需要日期时间信息。我希望只需将metadata-extractor需要的字节数馈送给它并存储在缓冲区中,然后获取信息并继续正常运行。将所有数据都保存在缓冲区中绝对不是一个选择,因为我的程序会耗尽内存。

英文:

I have a programme that handles thousands of images as well as videos. I want to be able to read date-time metadata from them without having to save the whole image in memory. Currently the images are passed through my programme using an assortment of streams.

Eg. creating a thumbnail image:

public static void createThumbnailImage(Media media, TmpMedia tmpMedia) throws IOException {
        PipedInputStream mediaIn = new PipedInputStream();
        PipedOutputStream mediaOut = new PipedOutputStream(mediaIn);
        new Thread(() -> {
            try {
                App.storage.getMedia(media, mediaOut);
            } catch (IOException e) {
                LOGGER.log(Level.WARNING, "Error getting Media for thumbnail", e);
            }
        }).start();
        // Rest of code...
}

For one of my steps I require the date-time information. I hope that I only have to feed metadata-extractor a necessary number of bytes while storing them in a buffer, before getting the information and continuing as normal. Just saving all the data in a buffer is definitely not an option as my programme would run out of memory.

答案1

得分: 1

默认情况下,metadata-extractor 仅读取必要的段字节,因此可以简单地将其使用的所有字节存储在缓冲区中,直到 metadata-extractor 完成。

使用这个类,你可以从一个 InputStream 中获取元数据,然后你可以自行处理剩余的字节。

public class MetadataStreamProcessor {

    private final BufferedInput in;

    public MetadataStreamProcessor(InputStream in) {
        this.in = new BufferedInput(in, 1024); // 一开始使用 1KB 的缓冲区
    }

    public Metadata readMetadata() throws IOException, ImageProcessingException {
        return ImageMetadataReader.readMetadata(in);
    }

    public void writeTo(OutputStream out) throws IOException {
        in.buffer.writeTo(out);

        int read;
        byte[] bytes = new byte[1024];
        while ((read = in.in.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
    }

    private static final class BufferedInput extends InputStream {

        private final InputStream in;
        private final ByteArrayOutputStream buffer;

        public BufferedInput(InputStream in, int size) {
            this.in = in;
            buffer = new ByteArrayOutputStream(size);
        }

        @Override
        public int read() throws IOException {
            int read = in.read();
            if (read != -1) buffer.write(read);
            return read;
        }
    }
}
英文:

By default the metadata-extractor only reads the necessary segment bytes, therefore it is possible to simply store all the bytes that it uses in a buffer until the metadata-extractor finishes.

Using this class you get the metadata from an InputStream after which you can do with the remaining bytes what you want to.

public class MetadataStreamProcessor {

    private final BufferedInput in;

    public MetadataStreamProcessor(InputStream in) {
        this.in = new BufferedInput(in, 1024); // 1KB to start with
    }

    public Metadata readMetadata() throws IOException, ImageProcessingException {
        return ImageMetadataReader.readMetadata(in);
    }

    public void writeTo(OutputStream out) throws IOException {
        in.buffer.writeTo(out);

        int read;
        byte[] bytes = new byte[1024];
        while ((read = in.in.read(bytes)) != -1) {
            out.write(bytes, 0, read);
        }
    }

    private static final class BufferedInput extends InputStream {

        private final InputStream in;
        private final ByteArrayOutputStream buffer;

        public BufferedInput(InputStream in, int size) {
            this.in = in;
            buffer = new ByteArrayOutputStream(size);
        }

        @Override
        public int read() throws IOException {
            int read = in.read();
            if (read != -1) buffer.write(read);
            return read;
        }
    }
}

huangapple
  • 本文由 发表于 2023年6月18日 23:59:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76501412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定