imageIO kullanarak, genellikle bir görüntü dosyasını dönüştürme sorunu yaşıyorum ve üzerine yazdıktan sonra, tüm EXIF verilerini kaybeder. İlk önce ayıklamadan, önbelleğe almadan ve sonra yeniden sıfırlamaya gerek kalmadan onu korumanın bir yolu var mı?EXIF verilerini silmeden görüntü yönetme
cevap
Çözümüm, ImageIO, Imgscalr ve Apache commons-görüntüleme özelliklerinin bir kombinasyonunu kullanıyorum. Yazıtın meta verilerle okunmasını birleştiren tek bir kütüphane olmadığı için, bu muhtemelen bellek kullanımı üzerinde oldukça fazladır; İyileştirmeler hoş geldiniz.
ImageReader reader = ImageIO.getImageReadersBySuffix("jpg").next();
(böyle okuyucu varsa da kontrol etmek isteyebilirsiniz):
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;
}
}
Çok teşekkürler. Güzel çalıştı. Tek şey, görünüşte, 'IImageMetadata', Apache Commons Imaging –
için mevcut repoda 'ImageMetadata' olarak isimlendiriliyor. @Rigeborod'dan biraz daha verimli görünen diğer çözümü de kontrol edin. –
ImageIO bu işlevi kendisi var, ama bunun yerine ImageIO.read size ImageReader kullanmanız gerekecektir . Eğer meta kaydedebilirsiniz Şimdi
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
Ve sonra görüntüyü okuyun: Eğer yeni bir resim kaydetmek istediğiniz
BufferedImage bi = reader.read(0);
Sonra girişini ayarlamak gerekir ImageWriter'i kullanmalısınız:
// 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);
Eski bir konu olarak, bu cevabın biraz geç olduğunu düşünüyorum, ancak bu konu hala devam etmekte olduğu için başkalarına yardımcı olabilir.
Bu, benim çözümümden çok daha fazla bellek verimli görünüyor. Sanırım görüntünün bir kopyası hala bellekte, ancak bunu gerçekten engelleyemez. –
- 1. ImageMagick kullanarak metin olarak EXIF verilerini ayıkla
- 2. Android'de bayt dizisinden EXIF verilerini okuma
- 3. EXIF verilerini okuma ve yazma - Ionic/Cordova
- 4. , Exif verileri kaybeder
- 5. EXIF yönlendirme verilerini onurlandırmayan Android cihazlarla nasıl baş edilir?
- 6. Anlık görüntü verilerini XML'ye kaydetme
- 7. EXIF from int8Array
- 8. Exif kütüphanesi
- 9. EXIF Dictionary EXP Dictionary
- 10. IPTC görüntü verilerini PHP GD ile gömme
- 11. Görüntü verilerini Python'daki bir URL'den nasıl okuyabilirim?
- 12. Yalnızca görüntü boyutunu kısıtla WordPress'te yönetme kısıtla Boyutu
- 13. Görüntüyü yüklemeden dosya sistemindeki mevcut bir görüntü için EXIF verileri nasıl yazılır veya değiştirilir?
- 14. Yüce resim verilerini submime metninde nasıl görüntüleyebilirim
- 15. Görüntü nesnesini ikili bloğa dönüştürme
- 16. Resimden exif küçük resmini kaldırma veya güncelleme
- 17. yönetme yapılandırma
- 18. Özel tercih düzenini yönetme
- 19. Resimdeki mevcut exif profiline etiket değeri ekleyin
- 20. Ben android görüntüde exif bilgi okumak istiyorum. Ben galeride görüntüden exif okuyabilir ancak above.I bir resim exif almak bilgiler null seçti Şekilde görüldüğü gibi ben kameraya
- 21. Bir Apple iPhone ile çekilen bir görüntüden EXIF verilerini nasıl okuyabilirim?
- 22. Python, OpenOffice: Programlı Elektronik tabloları yönetme
- 23. UWSGI'yı Upstart ile yönetme
- 24. Python: Görevler listesini yönetme
- 25. Görsellerimı Java'da yönetme
- 26. Vaat bağımlılıklarını yönetme
- 27. Hataları düzenle Yönetme
- 28. Etiketleri .net içinde yönetme
- 29. Kentico TreeNode Bağımlılıkları silmeden yöntemi sil
- 30. Metin dosyasının içeriğini silmeden nasıl silinir
Başka bir yerde saklayın, sonra eski bir exif meta ile yeni resmin üzerine yazın. http://www.screaming-penguin.com/node/7485 –
Bu tam olarak – preslavrachev
'dan kaçınmak istediğim şey, meta kopyalamanın problemi nedir? İşte başka bir örnek http://nucleussystems.com/blog/java-copy-exif-data –