2008-10-24 25 views
14

Tôi đang cố lập trình siêu dữ liệu dpi của hình ảnh jpeg trong Java. Nguồn của hình ảnh là một máy quét, vì vậy tôi nhận được độ phân giải ngang/dọc từ TWAIN, cùng với dữ liệu thô của hình ảnh. Tôi muốn lưu thông tin này để có kết quả in tốt hơn.Ghi siêu dữ liệu dpi vào hình ảnh jpeg trong Java

Đây là mã tôi có cho đến thời điểm này. Nó lưu hình ảnh thô (byteArray) vào một tệp JPEG, nhưng nó bỏ qua thông tin X/Ydensity mà tôi chỉ định thông qua IIOMetadata. Bất kỳ lời khuyên nào tôi đang làm sai?

Bất kỳ giải pháp nào khác (thư viện của bên thứ ba, v.v.) cũng sẽ được chào đón.

import java.awt.image.BufferedImage; 
import java.awt.image.WritableRaster; 
import java.io.File; 

import javax.imageio.IIOImage; 
import javax.imageio.ImageIO; 
import javax.imageio.ImageTypeSpecifier; 
import javax.imageio.metadata.IIOMetadata; 
import javax.imageio.plugins.jpeg.JPEGImageWriteParam; 
import javax.imageio.stream.ImageOutputStream  

import org.w3c.dom.Element;  
import com.sun.imageio.plugins.jpeg.JPEGImageWriter; 

public boolean saveJpeg(int[] byteArray, int width, int height, int dpi, String file) 
{ 
    BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 

    WritableRaster wr = bufferedImage.getRaster(); 
    wr.setPixels(0, 0, width, height, byteArray); 

    try 
    {   
     // Image writer 
     JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix("jpeg").next(); 
     ImageOutputStream ios = ImageIO.createImageOutputStream(new File(file)); 
     imageWriter.setOutput(ios); 

     // Compression 
     JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam(); 
     jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT); 
     jpegParams.setCompressionQuality(0.85f); 

     // Metadata (dpi) 
     IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), jpegParams); 
     Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0"); 
     Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0); 
     jfif.setAttribute("Xdensity", Integer.toString(dpi)); 
     jfif.setAttribute("Ydensity", Integer.toString(dpi)); 
     jfif.setAttribute("resUnits", "1"); // density is dots per inch   

     // Write and clean up 
     imageWriter.write(data, new IIOImage(bufferedImage, null, null), jpegParams); 
     ios.close(); 
     imageWriter.dispose(); 
    } 
    catch (Exception e) 
    { 
     return false; 
    } 

    return true; 
} 

Cảm ơn!

Trả lời

13

Một số vấn đề mà không được xem xét ở đây:

  1. Cây không được ánh xạ trực tiếp đến IOMetaData. Để áp dụng dữ liệu từ cây, thêm cuộc gọi sau đây sau khi cài đặt mật độ và các thông số raster:

    data.setFromTree("javax_imageio_jpeg_image_1.0", tree); 
    
  2. không sử dụng các dữ liệu meta như tham số đầu tiên trong các cuộc gọi ghi. Xem JPEGImageWriter#write(IIOMetaData, IIOImage, ImageWriteParam). Nếu streamMetaData không phải là NULL, một cảnh báo (WARNING_STREAM_METADATA_IGNORED) sẽ được tạo.

  3. đặt dữ liệu meta là IOMetadata của IOImage. Các dữ liệu meta này được sử dụng bởi JPEGImageWriter. Các ghi đúng cuộc gọi sau đó là

    imageWriter.write(null, new IIOImage(F_scaledImg, null, data), jpegParams); 
    
+2

đâu F_scaledImg thiết lập? Nó giống như bufferedImage? Xin lỗi nếu đây là một câu hỏi ngớ ngẩn ... –

+2

Có, đó là trong thực tế bufferedImage. Christoph phải sao chép đoạn trích và quên chỉnh sửa nó. – dasp

1

Tôi có vẻ như đây có thể là lỗi.

tôi thấy bài from a few google searches

này Rõ ràng có rất nhiều chi tiết thời điểm đó một lỗi là tốt.

Bài đăng trên nói về việc sử dụng JMagick làm công việc của bên thứ ba.

Các vấn đề liên quan