2010-06-08 22 views
20

Chúng tôi đang sử dụng Java2D để thay đổi kích thước ảnh được tải lên trang web của chúng tôi, nhưng chúng tôi gặp phải vấn đề (một số dường như cũ, cf .: http://forums.sun.com/thread.jspa?threadID=5425569) - một số JPEG cụ thể nâng cao CMMException khi chúng tôi cố gắng ImageIO.read() một InputStream chứa dữ liệu nhị phân của chúng :Có cách thay thế Java 100% cho ImageIO để đọc tệp JPEG không?

java.awt.color.CMMException: Invalid image format 
at sun.awt.color.CMM.checkStatus(CMM.java:131) 
at sun.awt.color.ICC_Transform.<init>(ICC_Transform.java:89) 
at java.awt.image.ColorConvertOp.filter(ColorConvertOp.java:516) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.acceptPixels(JPEGImageReader.java:1114) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImage(Native Method) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:1082) 
at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:897) 
at javax.imageio.ImageIO.read(ImageIO.java:1422) 
at javax.imageio.ImageIO.read(ImageIO.java:1326) 
    ... 

(snipped thời gian còn lại của ngăn xếp dấu vết, đó là ImageIO.read() cuộc gọi, mã của chúng tôi servlet và như vậy)

Chúng tôi thu hẹp nó xuống để lấy hình ảnh từ máy ảnh đặc biệt, và tôi chọn một bức ảnh mà trigger lỗi này: http://img214.imageshack.us/img214/5121/estacaosp.jpg. Chúng tôi nhận thấy rằng điều này chỉ xảy ra với JVM của Sun (trên Linux và Mac, chỉ cần thử nghiệm trên 1.6.0_20) - một máy kiểm tra với OpenJDK đọc cùng một ảnh mà không bị cản trở, có thể do việc triển khai khác nhau của trình đọc JPEG.

Thật không may, chúng tôi không thể chuyển đổi các JVM trong sản xuất, cũng như không sử dụng các giải pháp phụ thuộc vào bản địa như ImageMagick (http://www.imagemagick.org/).

Xét rằng, câu hỏi của tôi là: Liệu một sự thay thế cho trình đọc ảnh ImageIO có thể xử lý ảnh như ảnh được liên kết tồn tại? Nếu không, có một giải pháp thay đổi kích cỡ ảnh Java tinh khiết 100% khác mà chúng ta có thể sử dụng không?

Cảm ơn bạn!

+0

Nhân tiện, tôi biết rằng ImageIO không xử lý hình ảnh CMYK (theo http://stackoverflow.com/questions/2408613/problem-reading-jpeg-image-using-imageio-readfile-file).Nhưng mẫu một là RGB (như xa như Mac Preview là có liên quan, sẽ được vui mừng nếu ai đó có thể xác nhận rằng) – chesterbr

+0

Tôi đã mở một lỗi trên cơ sở dữ liệu Oracle/Sun lỗi ở đây: http://bugs.sun.com/bugdatabase /view_bug.do?bug_id=7064516 Bình chọn nếu bạn vẫn quan tâm đến việc sửa lỗi! –

Trả lời

11

Một thư viện có thể hữu ích cho bạn có thể là Java Imaging Library nâng cao (JAI)

Sử dụng thư viện này có thể phức tạp hơn khá nhiều so với sử dụng ImageIO nhưng trong một thử nghiệm nhanh Tôi chỉ cần chạy nó đã mở và hiển thị tệp hình ảnh sự cố bạn đã liên kết.

public static void main(String[] args) { 
     RenderedImage image = JAI.create("fileload", "estacaosp.jpg"); 

     float scale=(float) 0.5; 

     ParameterBlock pb = new ParameterBlock(); 
     pb.addSource(image); 

     pb.add(scale); 
     pb.add(scale); 
     pb.add(1.0F); 
     pb.add(1.0F); 

     pb.add(new InterpolationNearest());// ;InterpolationBilinear()); 
     image = JAI.create("scale", pb); 

     // Create an instance of DisplayJAI. 
     DisplayJAI srcdj = new DisplayJAI(image); 

     JScrollPane srcScrollPaneImage = new JScrollPane(srcdj); 

// Use a label to display the image 
     JFrame frame = new JFrame(); 

     frame.getContentPane().add(srcScrollPaneImage, BorderLayout.CENTER); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

Sau khi chạy mã này, hình ảnh dường như tải tốt. Sau đó nó được thay đổi kích cỡ bằng 50% sử dụng ParamaterBlock

Và cuối cùng nếu bạn muốn lưu các tập tin bạn chỉ có thể gọi:

String filename2 = new String ("tofile.jpg"); 
    String format = new String ("JPEG"); 
    RenderedOp op = JAI.create ("filestore", image, filename2, format); 

Tôi hy vọng điều này sẽ giúp bạn ra ngoài. May mắn nhất.

+0

Chắc chắn là vậy! Phải kiểm tra xem nó sẽ hoạt động như thế nào trên một thiết lập "không đầu", nhưng tôi tin rằng chúng ta có thể làm việc đó. Cảm ơn bạn! – chesterbr

+1

Để cho bạn biết, các nhà phát triển của chúng tôi đã triển khai giải pháp này và nó hoạt động như một sự quyến rũ. Một lần nữa, cảm ơn bạn! – chesterbr

+1

liên kết chết, vui lòng cập nhật http://www.oracle.com/technetwork/java/current-142188.html hoặc bất kỳ nội dung gì ngay bây giờ. – user1133275

7

Tôi gặp phải sự cố tương tự. Tôi miễn cưỡng sử dụng JAI vì nó đã lỗi thời nhưng có vẻ như đó là giải pháp ngắn nhất.

Mã này chuyển đổi một InputStream để một BufferedImage, sử dụng ImageIO mặt trời (nhanh) hoặc trong vài trường hợp vấn đề này xảy ra, sử dụng JAI:

public static BufferedImage read(InputStream is) throws IOException { 
    try { 
     // We try it with ImageIO 
     return ImageIO.read(ImageIO.createImageInputStream(is)); 
    } catch (CMMException ex) { 
     // If we failed... 
     // We reset the inputStream (start from the beginning) 
     is.reset(); 
     // And use JAI 
     return JAI.create("stream", SeekableStream.wrapInputStream(is, true)).getAsBufferedImage(); 
    } 
} 
8

Cũ bưu điện, nhưng để tham khảo trong tương lai:

Lấy cảm hứng từ câu hỏi này và liên kết tìm thấy ở đây, tôi đã viết một plugin JPEGImageReader cho ImageIO hỗ trợ hình ảnh JPEG với loại cấu hình màu ICC "xấu" này ("vấn đề" là ý định hiển thị trong cấu hình ICC không tương thích với Java ColorConvertOp). Đó là Java đơn giản và không yêu cầu JAI.

Mã nguồn và các bản dựng nhị phân được liên kết có sẵn miễn phí từ TwelveMonkeys project trên GitHub.