2011-11-22 24 views
8

Tôi có một tệp bitmap, test3.bmp, mà tôi có thể xem và chỉnh sửa với mọi trình xem hình ảnh mà tôi đã thử nghiệm.Tại sao ImageIO không đọc tệp BMP cho đến khi nó được lưu lại trong MS Paint?

Điều đó nói rằng, tôi không thể đọc nó vào ứng dụng Java của mình. Nếu tôi chỉnh sửa BMP trong MS Paint, hãy lưu nó, hoàn tác thay đổi và lưu nó (test3_resaved.bmp), tôi có cùng một hình ảnh, nhưng với kích thước tệp khác. Các kích thước tập tin khác nhau không liên quan đến tôi ... những gì hiện, là ứng dụng của tôi có thể đọc các tập tin được lưu lại.

Ai đó có thể khai sáng cho tôi về lý do tại sao một hình ảnh hoạt động với mã của tôi, nhưng hình kia không?

hình ảnh tập tin:

Dưới đây là một ứng dụng thử nghiệm tối thiểu:

package Test; 

import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.image.BufferedImage; 
import java.io.File; 
import java.io.IOException; 

import javax.swing.ImageIcon; 
import javax.swing.JFrame; 

@SuppressWarnings("serial") 
public class Test extends JFrame { 
    private ImageIcon imageIcon; 

    public Test(String filename) throws IOException { 
     super(); 
     BufferedImage image = javax.imageio.ImageIO.read(new File(filename)); 
     imageIcon = new ImageIcon(image); 
     setVisible(true); 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     repaint(); 
    } 

    public void paint(Graphics g) { 
     Graphics2D g2d = (Graphics2D) g; 
     setSize(imageIcon.getIconWidth(), imageIcon.getIconHeight()); 
     if (imageIcon != null) 
      g2d.drawImage(imageIcon.getImage(), 0, 0, this); 
    } 


    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     try { 
      if (args.length > 0) 
       new Test(args[0]); 
      else 
       System.out.println("usage - specify image filename on command line"); 
     } 
     catch (Throwable t) { 
      t.printStackTrace(); 
     } 
    } 

} 
+2

có ** ** ** ** ** ** ** ** ** nhiều loại tệp BMP khác nhau. Có thể là * MS Paint * của bạn có thể đọc định dạng gốc nhưng đang sử dụng các tiêu đề BMP/mã hóa khác khi lưu lại tệp. Tôi biết chắc chắn rằng Java chắc chắn không thể đọc tất cả các tập tin BMP khác nhau ra khỏi đó (vài người đọc BMP có thể). Nó chỉ xảy ra là Java hỗ trợ loại BMP cụ thể mà MS Paint xuất ra. Tại sao BMP? Nếu bạn muốn lossless, PNG sẽ là một lựa chọn? – TacticalCoder

+0

cùng một vấn đề ở đây là "Roman B." ... Các liên kết cho tệp BMP không thể hoạt động. Bạn có thể hexdump các tiêu đề (đầu) của cả hai tập tin và thêm kết quả cho câu hỏi của bạn nhưng với tôi anyway vấn đề là chính xác những gì tôi mô tả ở trên: -/ – TacticalCoder

Trả lời

10

(mở rộng về ý kiến ​​của tôi)

Vấn đề nắm này: mọi người thường tin rằng "định dạng" được đưa ra bởi lệnh sau:

ImageIO.getReaderFileSuffixes(); 

được hỗ trợ bởi Java.

Nhưng đó không phải là cách đọc/hiểu vì nó đơn giản không phải là cách nó hoạt động.

sai: "ImageIO có thể đọc bất kỳ tập tin được mã hóa với một trong những định dạng"

Đúng: "ImageIO không thể đọc được hình ảnh mã hóa với một định dạng mà không phải là một trong những định dạng"

Nhưng bây giờ điều gì nói về các định dạng xuất hiện trong danh sách đó? Vâng ... Nó trở nên phức tạp.

Ví dụ danh sách đó thường trả về cả "PNG" và "BMP" (và các định dạng khác). Nhưng không có "một" PNG cũng như "một" BMP. Tôi có thể đến vào ngày mai với định dạng PNG (phụ) hợp lệ sẽ hoàn toàn ổn nhưng không có bộ giải mã PNG nào có thể giải mã (nó sẽ phải được xác nhận và chấp nhận: nhưng một khi nó được chấp nhận, nó sẽ "phá vỡ" "tất cả các bộ giải mã PNG hiện có trên mạng). May mắn thay, đối với hình ảnh PNG, vấn đề không quá tệ.

Định dạng BMP rất phức tạp. Bạn có thể nén hoặc không (có thể giải thích kích thước tệp khác nhau mà bạn đã thấy). Bạn có thể có nhiều tiêu đề khác nhau (có độ dài khác nhau, điều này cũng có thể giải thích kích thước tệp khác nhau mà bạn đã thấy). Heck, BMP thực sự phức tạp đến mức tôi nghĩ rằng bạn có thể nhúng các pixel được mã hóa PNG bên trong một "vỏ" BMP.

Về cơ bản có hai loại vấn đề các tập tin BMP:

  • biến BMP đã xuất hiện sau khi giải mã Java được tạo ra
  • biến BMP có đủ che khuất sao cho implementors Java ImageIO không xem xét nó xứng đáng với sự hỗ trợ

"Lỗi" bao gồm suy nghĩ rằng có một định dạng PNG hoặc một BMP. Cả hai định dạng (và các định dạng hình ảnh khác quá) thực sự là "mở rộng". Mỗi khi một biến thể mới xuất hiện, nó có khả năng phá vỡ bất kỳ bộ giải mã nào.

Vì vậy, những gì đang xảy ra trong trường hợp của bạn là thế này:

  1. bạn đang đọc tập tin BMP gốc từ MS Paint và MS Paint là khả năng đọc tập tin đó bởi vì nó sẽ xảy ra là một định dạng BMP rằng MS Sơn hiểu.

  2. định dạng BMP giống với phiên bản Java bạn đang sử dụng (hy vọng rằng nó sẽ được hỗ trợ trong phiên bản Java khác nhưng tôi sẽ không tính vào nó).

  3. khi bạn lưu lại tập tin đó từ MS Paint, bạn đang lưu trong một định dạng BMP rằng chắc chắn là không giống như định dạng ban đầu (kích thước tập tin khác nhau là khá tell)

  4. định dạng khác sẽ được hỗ trợ bởi phiên bản Java của bạn.

Bây giờ để thực sự giải quyết vấn đề của bạn: trong thư viện hình ảnh kinh nghiệm của tôi như ImageMagick có thể đọc nhiều hơn thế nữa hình ảnh hơn so với mặc định Java ImageIO API vì vậy tôi muốn cung cấp cho một cái nhìn tại một trong hai thư viện hình ảnh khác hoặc trình bao bọc xung quanh ImageMagick.

Các thư viện này cũng thường được cập nhật để hỗ trợ các biến thể mới hơn và định dạng mới hơn nhanh hơn Java. Ví dụ: định dạng tuyệt vời WebP từ Google (tối đa 28% đến 34% tốt hơn PNG trên hình ảnh không có + mờ) đã được hỗ trợ bởi một số thư viện thao tác hình ảnh nhưng tôi không nín thở khi thực hiện ImageIO.read (someWebPpicture) ...

Một tùy chọn khác là sử dụng PNG: mặc dù về mặt lý thuyết PNG có thể được mở rộng, bạn ít có khả năng tìm thấy PNG "không được hỗ trợ" trong tự nhiên. Với BMP, tất cả đều quá phổ biến.

+0

Tôi thường bỏ qua đề cập rằng hình ảnh (và hầu hết các định dạng âm thanh) là 'định dạng vùng chứa' trừ khi một số loại cây trồng lên nhấn mạnh sự khác biệt giữa các mã hóa. 1 cho lời giải thích toàn diện của bạn. –

0

Có một số mã ví dụ ở đây http://www.java2s.com/Code/Java/2D-Graphics-GUI/ListAllreaderandwriterformatssupportedbyImageIO.htm sẽ liệt kê các định dạng hình ảnh được hỗ trợ bởi JDK của bạn.

BMP được hỗ trợ bởi bộ công cụ hình ảnh tiên tiến http://www.oracle.com/technetwork/java/release-jai-imageio-1-0-01-140367.html nhưng tôi biết rằng nó cũng có những thứ trong đó hiện được hỗ trợ bởi JDK cơ sở. Vì vậy, nếu được hỗ trợ bởi cả hai, thì có lẽ sự hỗ trợ JAI là toàn diện hơn. Điều đó dường như không chắc chắn, vì nó không có ý nghĩa nhiều. OTOH, nó Mặt trời.

Nếu bạn đang sử dụng JDK 6, bạn chắc chắn có thể làm PNG (di động hơn), bạn có thể chuyển đổi hình ảnh của mình không? IIRC MS Paint sẽ tiết kiệm png.

+1

hình ảnh "định dạng" tuyên bố được hỗ trợ bởi * ImageIO * reader (s) là rất gây hiểu lầm, như đã giải thích trong câu trả lời lenghty của tôi:) Nếu BMP đã thực sự được hỗ trợ, OP có thể mở hình ảnh của mình bằng cách sử dụng * ImageIO * giống như ông có thể mở nó từ MS Paint. Đây không phải là trường hợp. – TacticalCoder

0

Tôi đã thử nghiệm hai hình ảnh bằng bộ giải mã Java BMP của riêng tôi. Nó cũng đổ một số thông tin của hình ảnh. Tôi tìm thấy bản gốc là một bmp 32 bit và một tái lưu là một trong 24 bit. Vì vậy, tôi giả sử người đọc bmp imageio không thể xử lý 32 bit bmp chính xác.

Cập nhật: Để xác nhận thời gian dài trước đây, tôi đã thử nghiệm lại hình ảnh và vẫn gặp sự cố. Vấn đề là không có hình ảnh hiển thị và lý do là Java ImageIO cho rằng hình ảnh hoàn toàn trong suốt. Sau đây là một bãi chứa từ Java ImageIO đã tạo BufferedImage:

DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 
IntegerInterleavedRaster: width = 494 height = 516 #Bands = 4 xOff = 0 yOff = 0 
dataOffset[0] 0 
[email protected] 

Chúng ta có thể thấy ở đây có 4 băng tần đại diện cho RGBA như Java ImageIO giải thích nó. Sự thật là băng tần thứ tư hoặc byte thứ tư không phải là kênh alpha cho hình ảnh Windows 32 bit BMP. Nó chỉ đơn giản là rác hoặc để làm cho nó đôi từ liên kết.

Trình giải mã BMP 3.x Windows và nhiều hơn nữa từ đây https://github.com/dragon66/icafe

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