imageIOを使用すると、通常は画像ファイルを変換する問題があり、上書きした後はすべてのEXIFデータが失われます。最初に抽出し、キャッシュしてからリセットすることなく保存する方法はありますか?EXIFデータを削除せずに画像を操作する
答えて
ImageIO、ImgscalrとApacheのコモンズイメージングを組み合わせたソリューションです。残念ながら、イメージをそのメタデータと読みとり、メモリ使用量が多すぎるという単一のライブラリはありません。改善は大歓迎です。 (あなたは、このようなリーダーが存在するかどうかもチェックすることをお勧めします)
ImageReader reader = ImageIO.getImageReadersBySuffix("jpg").next();
:
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.common.IImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.io.IOUtils;
import org.imgscalr.Scalr;
public class ImageData {
private byte[] imageData;
public ImageData(InputStream instream) throws IOException {
imageData = IOUtils.toByteArray(instream);
instream.close();
}
public synchronized void resize(int maxDimension) throws IOException, ImageReadException, ImageWriteException {
// Resize the image if necessary
BufferedImage image = readImage(imageData);
if (image.getWidth() > maxDimension || image.getHeight() > maxDimension) {
// Save existing metadata, if any
TiffImageMetadata metadata = readExifMetadata(imageData);
imageData = null; // allow immediate GC
// resize
image = Scalr.resize(image, maxDimension);
// rewrite resized image as byte[]
byte[] resizedData = writeJPEG(image);
image = null; // allow immediate GC
// Re-code resizedData + metadata to imageData
if (metadata != null) {
this.imageData = writeExifMetadata(metadata, resizedData);
} else {
this.imageData = resizedData;
}
}
}
private TiffImageMetadata readExifMetadata(byte[] jpegData) throws ImageReadException, IOException {
IImageMetadata imageMetadata = Imaging.getMetadata(jpegData);
if (imageMetadata == null) {
return null;
}
JpegImageMetadata jpegMetadata = (JpegImageMetadata)imageMetadata;
TiffImageMetadata exif = jpegMetadata.getExif();
if (exif == null) {
return null;
}
return exif;
}
private byte[] writeExifMetadata(TiffImageMetadata metadata, byte[] jpegData)
throws ImageReadException, ImageWriteException, IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
new ExifRewriter().updateExifMetadataLossless(jpegData, out, metadata.getOutputSet());
out.close();
return out.toByteArray();
}
private BufferedImage readImage(byte[] data) throws IOException {
return ImageIO.read(new ByteArrayInputStream(data));
}
private byte[] writeJPEG(BufferedImage image) throws IOException {
ByteArrayOutputStream jpegOut = new ByteArrayOutputStream();
ImageIO.write(image, "JPEG", jpegOut);
jpegOut.close();
return jpegOut.toByteArray();
}
public synchronized void writeJPEG(OutputStream outstream) throws IOException {
IOUtils.write(imageData, outstream);
}
public synchronized byte[] getJPEGData() {
return imageData;
}
}
ありがとうございました。それはきれいに働いた。唯一のことは、明らかにApache Commons Imagingの現在のリポジトリにある 'IImageMetadata'は 'ImageMetadata'という名前になっていることです。 –
もう少し効率的に見える@Rigeborodの他のソリューションもチェックしてください –
ImageIOには、あなたがたImageReaderを使用する必要があります。この機能自体を持っているが、その代わりにImageIO.readの。 そして、あなたが入力を設定する必要があります。
reader.setInput(ImageIO.createImageInputStream(your_imput_stream));
今、あなたはあなたのメタデータ保存可能性があります
IIOMetadata metadata = reader.getImageMetadata(0);
// As far as I understand you should provide
// index as tiff images could have multiple pages
をし、イメージ読む:あなたが新しいイメージを保存したい場合は
BufferedImage bi = reader.read(0);
をImageWriterを使用する必要があります。
// I'm writing to byte array in memory, but you may use any other stream
ByteArrayOutputStream os = new ByteArrayOutputStream(255);
ImageOutputStream ios = ImageIO.createImageOutputStream(os);
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
ImageWriter writer = iter.next();
writer.setOutput(ios);
//You may want also to alter jpeg quality
ImageWriteParam iwParam = writer.getDefaultWriteParam();
iwParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwParam.setCompressionQuality(.95f);
//Note: we're using metadata we've already saved.
writer.write(null, new IIOImage(bi, null, metadata), iwParam);
writer.dispose();
ImageIO.write(bi, "jpg", ios);
これは古い話題なので、この回答は少し遅すぎると思うが、この話題は依然としてグーグルであるので、他人を助けるかもしれない。
私の解決策よりも、私はイメージの1つのコピーがまだメモリ内にあると思うが、実際にそれを避けることはできない。 –
- 1. 搬送波のある画像からEXIF(カメラ)データを削除するには?
- 2. 画像からexifを取り除く
- 3. Cassandra:テーブル構造を削除せずにデータを削除する
- 4. データを削除せずにHive外部テーブルを削除する
- 5. src属性を削除せずに画像を挿入
- 6. 画像からEXIFデータを削除するにはどうすればいいですか?
- 7. PythonでEXIF画像データにGeoTIFFタグを追加するには?
- 8. データベース内のデータを削除せずにFirebaseリサイクラビューアダプタからデータを削除する
- 9. JPEGでEXIFデータを簡単に削除する方法
- 10. node.jsのexifデータを削除するには
- 11. exifデータに到達できません.JPG画像
- 12. Base64の画像データを持つNodeJSでの画像操作
- 13. WordPressのサーバーでファイルを削除せずにメディアライブラリの画像を削除する方法
- 14. Windows PhoneでExif Imageデータを編集/削除する
- 15. この関数でexifデータを削除する方法は?
- 16. pythonで画像からexifデータを取得する
- 17. 画像を削除
- 18. 画像データの操作後に無限大を取得する
- 19. MySQLでデータを削除せずにパーティションを削除する方法は?
- 20. 画像のメタデータを調べるときに、exif-dataにフィールドを操作/追加するiptc
- 21. データを削除せずにJoomlaテンプレートをインストールするには
- 22. 前のデータを削除せずにplistにデータを追加
- 23. データを削除するには:base64の画像部分
- 24. 画像処理 - 削除せずにオブジェクトの厚さを減らす
- 25. エンティティフレームワークを使用してベーステーブルから削除せずにテーブルを削除せずにテーブルを削除する
- 26. わずかに異なる画像を生成する画像操作をテストする
- 27. NHibernate削除操作
- 28. カサンドラ削除操作
- 29. 削除「 - 」バイナリ操作
- 30. カメラロール画像とそのEXIFデータを取得しますか?
これを別の場所に保存してから、新しいイメージを古いexifメタで上書きしますか? http://www.screaming-penguin.com/node/7485 –
これは私が避けたいものです。 – preslavrachev
メタのコピーで何が問題になっていますか?ここに別の例がありますhttp://nucleussystems.com/blog/java-copy-exif-data –