英文:
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;
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论